在PineScript的世界里,存在一个终极开关,它能让你的策略从一个稳重的步兵,瞬间化身为一个反应速度快到极致的超级战士,这个开关就是 calc_on_every_tick
。
正常情况下,你的策略只会在K线收盘时才思考和行动一次,但一旦你开启了 calc_on_every_tick=true
,你的策略就被赋予了超能力,在实时行情中,每一次价格的跳动(每一个Tick),都会触发策略进行一次完整的计算和行动。
这意味着:
- 毫秒级反应: 价格突破前高的瞬间,你的订单就能发出,而不是等到K线收盘。
- K线内高频交易: 你可以在一根尚未走完的K线内部,完成多次买入和卖出。
- 极限加仓: 只要条件允许,你可以在一根K线内瞬间把仓位打满。
- 即时警报: 在K线内的任何时刻,只要条件触发,就能立刻发出警报。
听起来是不是很诱人?但请先收起你的兴奋,因为这个超能力附带了一个足以致命的副作用,我们稍后会讲。
如何开启逐笔计算模式
开启这个模式很简单,只需在 strategy()
函数中,将 calc_on_every_tick
的值设为 true
:
//@version=6
strategy(title="我的策略", calc_on_every_tick=true)
它的默认值是 false
。如果你想让策略保持常规的K线收盘时计算模式,直接省略这个参数即可。
现在,我们来谈谈那个致命的副作用。
划重点,请刻在脑子里:calc_on_every_tick
的所有超能力,仅仅在实时数据上生效,在历史数据(也就是你的全部回测)上,它会被完全忽略!
这意味着:你的回测结果,是基于K线收盘计算模式跑出来的,它完全无法反映策略在开启逐笔计算后,在真实行情中的实际行为。你的策略在回测时是一个样子(稳重,每根K线行动一次),在实盘时却变成了另一个样子(激进,每次价格跳动都可能行动),你回测的根本不是你将要交易的那个策略!
这是一个灾难性的差异,如果你不理解这一点,盲目地相信回测报告,直接投入实盘,后果不堪设想。
实战演练
我们来看一个20的突破策略,允许最多加仓10次。
策略代码如下:
//@version=6
strategy(title="逐笔实时计算示例", overlay=true,pyramiding=10, calc_on_every_tick=true)
//计算
highestHigh = ta.highest(high, 20)[1]
lowestLow = ta.lowest(low, 20)[1]
plot(highestHigh, color=color.green, title="最高高点")
plot(lowestLow, color=color.red, title="最低低点")
//逻辑
if close > highestHigh
strategy.entry("Enter Long", strategy.long)
if close < lowestLow
strategy.entry("Enter Short", strategy.short)
我们将 calc_on_every_tick
设为 true
,在价格跌破支撑位的同一根K线内部,会瞬间将仓位打满,这就是逐笔计算的威力,反应极度灵敏。
如果关闭 calc_on_every_tick
,完全相同的K线,策略的行为截然不同,在第一根K线跌破支撑位后,它等到K线收盘才计算,然后在下一根K线的开盘价才成交了第一笔空单;由于只开了一笔仓,当后面价格再次跌破支撑时,它才会慢悠悠地开了第二笔。
完全不同的两种行为模式,前者是激进的、K线内的、毫秒级的交易者;后者是保守的、K线间的、需要等待的交易者。
你回测的是后者,但你实盘交易的却是前者,这就是 calc_on_every_tick
最大的坑。
你也可以在策略的“属性”设置中,勾选逐笔实时重新计算来手动开启此功能,这个手动设置会覆盖你在代码中的配置。
总结
calc_on_every_tick
是为超短线交易者、剥头皮策略、以及对执行速度有极致要求的场景而设计的。赋予策略最快的反应速度,能够在K线内部根据价格的实时跳动进行交易。致命缺点是该行为只在实时数据中生效,导致历史回测结果与真实交易行为完全脱节,参考价值极低。
学长建议如果你不是在开发专门的超高频或剥头皮策略,请离 calc_on_every_tick=true
远一点。如果你确实需要使用它,你必须清醒地认识到,回测报告对你几乎没有意义,你的策略验证必须通过长时间的模拟盘交易或小资金实盘测试来完成,绝不能依赖历史回测。驾驭 calc_on_every_tick
需要丰富的经验和对风险的深刻理解。请务必谨慎使用,不要被它在实时图表上华丽的表现所迷惑。