如果价格连续十根 K 线都在均线上方,close > average 可能十次都为真。若只想标记价格从下方越到上方的那一刻,还需要上一根 K 线的相对关系。

一种状态与它的开始

假设当前和上一根的平均值均为 100,上一收盘价为 99,当前为 101。那么当前价格既在均线上方,也相对于上一根发生了上穿。

如果下个收盘价为 102,仍在均线上方,但没有新的上穿,因为上一根就已在上方。

当第一个值当前大于第二个值,而上次执行时小于或等于第二个值,ta.crossover(first, second) 为真。ta.crossunder 则是向下的对应版本。

当前仅仅相等还不算交叉。如果第一个值只是达到第二个值,> 不成立。但上一根相等时,当前越到上方仍然可以算上穿。

位于上方与向上交叉收盘价只在第三根K线向上穿过均线。第四根K线仍在均线上方,但没有新信号。前一根K线的值相等,也允许当前K线形成向上交叉。 close: 99 → 100 → 101 → 102. average: 100 → 100 → 100 → 100. close > average: False → False → True → True. ta.crossover(close, average): False → False → True → False.收盘价average = 100991FalseFalse1002FalseFalse1013TrueTrue1024TrueFalseK线close > averageta.crossover(close, average)
位于上方与向上交叉收盘价只在第三根K线向上穿过均线。第四根K线仍在均线上方,但没有新信号。前一根K线的值相等,也允许当前K线形成向上交叉。

两条移动平均线交叉

继续使用移动平均线一章的两条线。短而快的设为蓝色,长而慢的设为橙色。绿色三角形标记快速线上穿,红色三角形标记下穿。

创建 cross_signals.py:

"""
@pyne edge
"""
from pynecore.lib import close, color, input, location, plot, plotshape, script, shape, ta


@script.indicator("Average Crossings", overlay=True)
def main(
    fast_length: int = input.int(5, title="Fast length", minval=1, maxval=200),
    slow_length: int = input.int(20, title="Slow length", minval=1, maxval=200),
):
    fast_average = ta.sma(close, fast_length)
    slow_average = ta.sma(close, slow_length)
    crosses_up = ta.crossover(fast_average, slow_average)
    crosses_down = ta.crossunder(fast_average, slow_average)
    plot(fast_average, "Fast average", color=color.blue, linewidth=2)
    plot(slow_average, "Slow average", color=color.orange, linewidth=2)
    plotshape(crosses_up, "Cross up", style=shape.triangleup,
              location=location.belowbar, color=color.green)
    plotshape(crosses_down, "Cross down", style=shape.triangledown,
              location=location.abovebar, color=color.red)

在演示数据上用默认值 5 和 20 运行。标记只出现在交叉的 K 线上。如果蓝线在一段较长时间里始终高于橙线,不会每根都出现新绿色信号。

cross_signals.py 的图表显示快慢移动平均线,以及绿色和红色交叉标记。
两条移动平均线的交叉被显示为独立事件。

为什么单独计算交叉?

ta.crossover 和 ta.crossunder 在每根 K 线上运行,这样它们各自上一次执行就对应前一根已处理 K 线。

如果只在另一个条件满足时才调用交叉函数,其先前状态就未必来自前一根 K 线。绘制的线与标记可能在检查不同的时间序列。

所以仍遵守上一章的规则:先在每根 K 线上计算所有需要状态的结果,再用这些结果决策。

这里同样有预热期

二十期 SMA 到第二十根才有效。首个有效值出现时,上一根二十期 SMA 仍然缺失,因此还无法根据两根完整 K 线判断交叉。

条件需要两条均线的当前值和上一根值。

不要为了获得信号而把 na 换成零。零均线可能在真实均线还无法计算的位置制造虚假交叉。

数据对应的时间

本书在已结束的历史 K 线上运行程序。根据日线收盘价生成的信号,使用的是该 K 线结束时已知的数据。

尚在形成中的 K 线,其收盘价还会变化。盘中看到的交叉到收盘时可能消失。不要将它与已收盘 K 线上的检查混为一谈。

历史图上的信号不会自动变成同一根 K 线成交的交易。指标只是画出信号;订单和成交时间会在策略部分规定。

自己试一试

复制为 price_crossings.py。不再标记两条均线交叉,而是标记收盘价上穿或下穿慢线。图表中保留慢线。

参考答案
crosses_up = ta.crossover(close, slow_average)
crosses_down = ta.crossunder(close, slow_average)

标记使用这两个逻辑变量,因此不用修改 plotshape 行。不过,建议将标题改成 Price cross up 与 Price cross down。

如果不再使用快线,删除其计算、绘图及对应输入。这样界面只提供实际使用的设置。

跟踪一次交叉

选择一根带绿色标记的 K 线,查看这根和前一根上两条线的值。说出让信号为真的两个比较。验证策略时也可以采用这种方法。