时间与之前的 K 线
理解逐根 K 线执行,并利用历史值计算变化。
上一章根据单根 K 线计算。要计算收盘价的变化,就需要两根:当前与前一根。本章将把它们联系起来。
程序相同,K 线在变
在演示数据上启动程序时,PyneCore 按时间顺序遍历 K 线。main() 先处理第一根,再处理第二根,以此类推。每次的 close 都表示当前正在处理的 K 线收盘价。
因此,一次 plot(close, "Close") 调用就能绘制整条线。一次执行为线条添加一个点;一系列 K 线最终形成整条线。
上一章的 midpoint = (high + low) / 2 也会在每根 K 线上重新执行。赋值会重新计算该根 K 线的中间价。变量名不变,值可以变化。
处理顺序由执行器保证。你不需要为遍历整张图表编写循环。
使用方括号回看历史
close[1] 表示前一根 K 线的收盘价。方括号中的数字说明向前回看多少根。
| 表达式 | 表示哪根 K 线的收盘价? |
|---|---|
close | 当前处理的 K 线 |
close[0] | 同样是当前处理的 K 线 |
close[1] | 前一根 K 线 |
close[2] | 前两根 K 线 |
如果日线中连续三个收盘价是 100、103、101,那么在第三根 K 线上,close 为 101,close[1] 为 103,close[2] 为 100。
此时 close - close[1] 就是 101 - 103,结果为 −2。这是相邻收盘价的差。close - open 则比较同一根 K 线的开盘价与收盘价。两个计算回答的是不同问题。
回看的单位是 K 线,不是日历天数。在日线市场数据中,周末或休市可能让前一根 K 线的时间早于数天之前。
自己计算的值也能有历史
内置价格的历史值已经可用。如果想回看自己的计算结果,把变量标记为 Series:
midpoint: Series[float] = (high + low) / 2冒号之后是类型标注。float 表示可以带小数部分的数字。Series[float] 还要求执行器保留该变量逐根 K 线的历史值。
赋值依然在每根 K 线上执行。midpoint 是当前计算值,midpoint[1] 是上一根 K 线保存的值。Series 需要从 pynecore 模块导入。
图表上的两种变化
在项目的 scripts 文件夹创建 history_change.py:
"""
@pyne edge
"""
from pynecore import Series
from pynecore.lib import close, color, high, low, plot, script
@script.indicator("Changes Between Candles", overlay=False)
def main():
midpoint: Series[float] = (high + low) / 2
close_change = close - close[1]
midpoint_change = midpoint - midpoint[1]
plot(close_change, "Close change", color=color.blue)
plot(midpoint_change, "Midpoint change", color=color.orange)保存后,选择 Run Pyne code 和 demo 数据。单独面板会出现两条线。蓝线表示收盘价变化,橙线表示中间价变化。某点为正,说明该值高于上一根 K 线。

将鼠标移到某根 K 线上,图表值就会显示该时点的数据;不需要再到代码文件中单独选择时间。
第一根 K 线会发生什么?
数据文件的第一根 K 线没有更早的 K 线。此时 close[1] 是缺失值 na,名称来自 “not available”。
缺失价格不等于零。close - close[1] 的结果也缺失,所以第一根 K 线不会画出有效的变化值。这是正确结果:只有一根 K 线,无法计算两根之间的差。
使用 na(value) 可以判断一个值是否缺失。条件与标记会介绍条件处理。在此之前,不要试图把图表开头的缺失点“修正”为零价格。
这种写法不会让未来 K 线变得可用。close[-1] 也不表示下一个收盘价。决策只能使用在该次执行时已知的数据。
自己试一试
修改蓝线,将当前收盘价与五根 K 线之前的收盘价比较。在线条标题中也写明五根 K 线的间隔。
运行前判断:开头多少根 K 线会缺少结果?
参考答案
close_change = close - close[5]
plot(close_change, "Five-candle change", color=color.blue)前五根 K 线没有五根之前的收盘价。到第六根时就有了:数据文件第一根 K 线的收盘价。
橙线不会因此改变。如果也要将中间价变化改成五根的间隔,还需要修改 midpoint[1]。
检查计算
选择连续三根 K 线,记下它们的收盘价,手算第二根和第三根相对前一根的变化。蓝线应显示相同的值。如有差异,先检查所选时点和回看的根数。
进阶练习:用保留值替代历史访问
单个历史值也可以通过保存到下一根 K 线来使用。这正是 Persistent 变量的用途,程序记住的内容一章会介绍。你也可以读完该章后再做这道题。
改写 history_change.py,使程序中既不出现 close[1],也不出现 midpoint[1]。用两个持久变量保留上一根 K 线的收盘价和中间价。两条线应与原程序一致,第一根 K 线仍然缺少变化值。
思考执行顺序:什么时候读取保留值,什么时候才能用当前值覆盖?
参考答案
将 Series 的导入替换成 Persistent:
from pynecore import Persistent在 pynecore.lib 的导入中添加 na。保留文件开头的标记和指标设置,将 main() 改为:
def main():
previous_close: Persistent[float] = na
previous_midpoint: Persistent[float] = na
midpoint = (high + low) / 2
close_change = close - previous_close
midpoint_change = midpoint - previous_midpoint
plot(close_change, "Close change", color=color.blue)
plot(midpoint_change, "Midpoint change", color=color.orange)
previous_close = close
previous_midpoint = midpoint两个保留变量的初值是 na,因为第一根 K 线还没有前一个价格。因此,第一项差值也缺失。函数末尾保存当前值,下一根 K 线便用它们计算。
如果把 previous_close = close 放在减法前面,就会用当前收盘价减去自身,结果为零。使用持久变量时,需要自己保证更新顺序。
回看一根 K 线时,两种方法都可用。方括号版本更短,也能直接访问多根之前的数值。这两个持久变量只保留最近一次保存的价格。
在同一演示数据上运行两个版本,选几根 K 线比较两条曲线。