保持敬畏之心
交易是一场持久战

Pine Script(81):为什么策略的calc_on_order_fills设置会失灵

#Pine Script入门教学

上一篇我们领略了calc_on_order_fills的强大威力,它能让策略在订单成交后即时反应,触发连锁下单。但很多开发者在实际使用中,会遇到一个极其困惑的现象:我明明在代码里写了 calc_on_order_fills=true,为什么我的策略还是老样子,一点即时反应都没有?

如果你也遇到了这个问题,请放心,这不是 Bug。这背后隐藏着一个关于信号有效期的精妙逻辑陷阱。今天,学长就带你彻底把它弄明白。

一个失灵的策略

我们来看一个交易吞没形态的策略。逻辑很简单:

  • 当出现一根高于EMA的吞没时,做多。
  • 当出现一根低于EMA的吞没时,做空。
  • 我们设置 pyramiding=10,希望在信号出现后,利用 calc_on_order_fills 的连锁反应快速建仓。

策略代码如下:

//@version=6
strategy(title="吞没 - 示例策略", overlay=true,pyramiding=10, calc_on_order_fills=false)

priceData = input.source(hl2, title="价格数据")
emaLen    = input.int(12, title="EMA")
smoothLen = input.int(3, title="EMA 平滑", minval=1)

//计算
emaValue  = ta.ema(priceData[10], emaLen)
emaSmooth = ta.ema(emaValue, smoothLen)
plot(emaSmooth, color=#F4A460, linewidth=2)

//交易
outsideBar = high > high[1] and low < low[1]
enterLong  = priceData > emaSmooth and outsideBar
enterShort = priceData < emaSmooth and outsideBar
bgcolor(outsideBar ? color.new(color.teal,85) : na)

//订单
if enterLong
    strategy.entry("Long Entry", strategy.long)
if enterShort
    strategy.entry("Short Entry", strategy.short)

这是 calc_on_order_fills=false 在默认状态下的策略代码,现在我们打开那个即时反应的开关:

strategy(title="吞没 - 示例策略", overlay=true,pyramiding=10, calc_on_order_fills=true)

保存代码,策略重新加载后,大家会发现,和开启前一模一样,毫无变化! 预想中的连锁下单没有出现,calc_on_order_fills 好像失灵了。

信号过期问题

为什么会这样?要理解原因,我们必须把订单的生成和执行过程在时间轴上拆解开:

  1. 信号K线(假设是第10根K线)收盘时:此时outsideBar 条件为 true(因为它就是一根吞没),策略计算后,enterLong 条件满足,于是生成了一个多头订单。
  2. 成交K线(第11根K线)开盘时:第10根K线生成的订单,在此时被成交了。由于我们开启了 calc_on_order_fills,订单成交的瞬间,立刻触发了一次在第11根K线内部的额外计算。
  3. 额外计算的瞬间(仍在第11根K线上):策略重新检查开仓条件 enterLong,此时代码检查的是当前这根K线(第11根)是不是吞没。然而第11根K线大概率不是一根吞没,所以 outsideBar 条件为 false。因此enterLong 条件也为 false,策略认为无事可做,不会生成新的订单。

结论就是: 触发第一笔订单的那个关键信号(outsideBar),在第二笔订单想要生成时,已经过期失效了,连锁反应的第一环就断了,后续的下单自然无从谈起。

要解决这个问题,我们就必须让我们的交易信号活得久一点,至少能持续到下一根K线,我们需要修改开仓条件,告诉策略:“如果当前这根K线是信号K线,或者上一根K线是信号K线,我都认!”

这个逻辑在PineScript中实现起来非常简单,只需一个小小的改动:

修改前的条件:

enterLong  = priceData > emaSmooth and outsideBar
enterShort = priceData < emaSmooth and outsideBar

修改后的条件:

// 让信号有效期延长一根K线
enterLong  = priceData > emaSmooth and (outsideBar or outsideBar[1])
enterShort = priceData < emaSmooth and (outsideBar or outsideBar[1])

outsideBar[1] 就是获取上一根K线的 outsideBar 状态,通过 or 操作符,我们成功地将信号的有效期延长了一根K线。

应用修改后的完整代码:

//@version=6
strategy(title="吞没 - 示例策略", overlay=true,
     pyramiding=10, calc_on_order_fills=true)

priceData = input.source(hl2, title="价格数据")
emaLen    = input.int(12, title="EMA 长度")
smoothLen = input.int(3, title="EMA 平滑", minval=1)
emaValue  = ta.ema(priceData[10], emaLen)
emaSmooth = ta.ema(emaValue, smoothLen)
plot(emaSmooth, color=#F4A460, linewidth=2)

outsideBar = high > high[1] and low < low[1]
enterLong  = priceData > emaSmooth and (outsideBar or outsideBar[1])
enterShort = priceData < emaSmooth and (outsideBar or outsideBar[1])
bgcolor(outsideBar ? color.new(color.teal, 85) : na)

if enterLong
    strategy.entry("Long Entry", strategy.long)

if enterShort
    strategy.entry("Short Entry", strategy.short)

总结

calc_on_order_fills 并非一个即插即用的魔术开关,它更像是一个催化剂。它只提供了在订单成交后立即进行额外计算的机会,但你的策略代码必须有能力抓住这个机会。

  • 功能失灵的根本原因: 触发初始订单的信号,在订单成交后的额外计算中已经过期失效。
  • 解决方案:让信号的有效期能够至少延续到订单成交的K线上(通常是信号K线的下一根),比如使用 condition or condition[1] 的逻辑。

理解了信号有效期这个概念,你就能真正驾驭 calc_on_order_fills,让你的策略在需要时,爆发出惊人的执行效率。

赞(0)
未经允许不得转载:图道交易 » Pine Script(81):为什么策略的calc_on_order_fills设置会失灵
分享到

评论 抢沙发

登录

找回密码

注册