在PineScript的世界里,回测引擎的默认工作流程是谋定而后动。具体来说,是这样的:
- 等待K线走完: 策略会耐心等待当前这根K线完全收盘。
- 收盘后复盘: K线一收盘,策略立刻基于这个最新的收盘价进行计算,判断是否满足开仓或平仓条件。
- 如果条件满足,策略会生成一个交易订单。但此时此刻,这根K线的交易时间已经结束了,所以这个订单无法立刻成交,它就像一张预售票。
- 这张预售票要等到下一根K线开盘的瞬间才能兑现成交。
这个次根K线开盘成交的模式在大多数情况下是合理的,但有些策略思想明确要求以收盘价作为执行点。比如一个经典的周末效应策略,要求在周五收盘时买入,以捕捉周末可能发酵的消息带来的周一跳空,如果等到周一开盘再买,策略的立足之本就没了。
为了应对这类需求,PineScript提供了一个开关:process_orders_on_close
。
process_orders_on_close
是 strategy()
函数里的一个布尔参数。
- 默认情况 (
false
): 如果你省略不写,或者写process_orders_on_close=false
,就采用我们上面说的预售票模式,即次根K线开盘成交。 - 开启新模式 (
true
): 当你明确设置为process_orders_on_close=true
时,整个流程就变了。
//@version=6
strategy(title="我的策略", process_orders_on_close=true)
启用后,策略的行为会变成:
- K线收盘,策略复盘计算。
- 如果条件满足,生成订单。
- 不再等待! 订单会立即以当前这根K线的收盘价被视为成交。
这样一来,当下一根K线开盘时,你的策略就已经持有仓位了,能够完整地捕捉到两根K线之间的价格跳空。
process_orders_on_close=true
是一个强大的工具,但它也可能是回测中最“美丽”的陷阱。
优点很明显但缺点是致命的,严重脱离现实。 在真实交易中,想精准地以官方公布的收盘价成交一笔市价单,几乎是不可能的。因为当收盘价产生的那一刻,常规交易时段已经结束,这意味着你的回测结果会过度乐观。
因此学长在这里给个建议: 如果你决定使用 process_orders_on_close=true
,那么你必须同时为策略配置其他更接近现实的参数,作为一种补偿:
- 为市价单添加滑点 (
slippage
) - 为限价单验证成交深度 (
backtest_fill_limits_assumption
)
只有这样,你的回测才不至于沦为自欺欺人的数字游戏。
实战演练:捕捉周末行情
在周五如果收盘价高于45MA,就买入做多,期待周末后的跳空高开。然后在下周的周四,或者当价格跌破EMA时平仓。
策略代码如下:
//@version=6
strategy(title="在收盘时处理订单示例", overlay=true)
//计算
emaValue = ta.ema(close, 45)
plot(emaValue, color=color.orange, linewidth=2, title="EMA")
// 入场
if close > emaValue and dayofweek == dayofweek.friday
strategy.entry("Enter Long", strategy.long)
// 离场
if ta.crossunder(close, emaValue) or dayofweek == dayofweek.thursday
strategy.close("Enter Long", comment="Exit Long")
bgcolor(dayofweek == dayofweek.friday ? color.new(color.blue, 90) : na)
上面这段代码实际的入场成交发生在了下一根K线,也就是周一的开盘价,这完全违背了我们“捕捉周末跳空”的初衷。
现在,我们打开那个关键的开关,只需在 strategy()
函数中增加一个参数:
strategy(title="在收盘时处理订单示例", overlay=true,
process_orders_on_close=true)
现在入场成交是位于周五K线的收盘价上,平仓也相应地发生在了周四的收盘价。
总结
process_orders_on_close
是一个用于改变订单执行时间的专用开关,让策略从默认的次根K线开盘成交切换到当根K线收盘成交。
- 它是实现特定交易思想(如周末效应、日内收盘交易)的关键工具。
- 它本身会带来极度理想化的成交假设,导致回测结果过于乐观。
- 强烈建议在使用
process_orders_on_close=true
的同时,配合slippage
或backtest_fill_limits_assumption
参数。