回测中Stop Loss未在次日K线触发的技术问题
问题描述
回测过程中,在当日K线收盘价位置进场开仓后,次日止损(Stop Loss)条件触发,但交易并未通过止损指令即时离场,而是要等到当日K线收盘时才执行平仓操作,导致实际亏损幅度达到13-14%,远超过设定的4.3%止损幅度。交易列表已识别到止损条件,但未及时执行离场。
问题原因分析
代码中策略初始化参数process_orders_on_close=true是核心问题:
- 该参数强制所有订单(包括止损、止盈单)都在K线周期结束时才执行,而非价格触及止损/止盈价位的即时时刻
- 即使盘中价格已经跌破设定的止损线,也会等到收盘才平仓,从而放大了实际亏损
解决方案
- 修改订单执行时机参数:将
process_orders_on_close设为false,让止损/止盈单在价格触发时即时执行 - 优化止损价格计算逻辑:确保止损价仅在持仓状态下基于持仓均价计算,避免非持仓时的无效赋值
- 保留实时计算参数:维持
calc_on_every_tick=true,确保策略能实时监测价格变化触发止损条件
修改后的完整代码
//@version=5 strategy(title="Heikin Ashi Indicator", shorttitle="HA Indicator", overlay=false, calc_on_every_tick=true, calc_on_order_fills=true, process_orders_on_close=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100) //Rev 10 // Calculation HA Values haTicker = ticker.heikinashi(syminfo.tickerid) haOpen = request.security(haTicker, timeframe.period, open) haHigh = request.security(haTicker, timeframe.period, high) haLow = request.security(haTicker, timeframe.period, low) haClose = request.security(haTicker, timeframe.period, close) plotcandle(haOpen, haHigh, haLow, haClose, title='HA', color=haOpen < haClose ? color.green : color.red, wickcolor=haOpen < haClose ? color.green : color.red, bordercolor=haOpen < haClose ? color.green : color.red) // Calculation MA Values len = input.int(14, minval=1, title="MA Length") src = input(close, title="MA Source") offset = input.int(title="MA Offset", defval=0, minval=-500, maxval=500) out = ta.sma(src, len) plot(out, color=color.blue, title="MA", offset=offset) ma(source, length, type) => switch type "SMA" => ta.sma(source, length) "EMA" => ta.ema(source, length) "SMMA (RMA)" => ta.rma(source, length) "WMA" => ta.wma(source, length) "VWMA" => ta.vwma(source, length) typeMA = input.string(title = "Method", defval = "SMA", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="Smoothing") smoothingLength = input.int(title = "Length", defval = 5, minval = 1, maxval = 100, group="Smoothing") smoothingLine = ma(out, smoothingLength, typeMA) plot(smoothingLine, title="Smoothing Line", color=#f37f20, offset=offset, display=display.none) /// i_dateFilter = input.bool(false, "Date Range Filtering On/Off") i_fromYear = input.int(1900, "From Year", minval = 1900) i_fromMonth = input.int(1, "From Month", minval = 1, maxval = 12) i_fromDay = input.int(1, "From Day", minval = 1, maxval = 31) i_toYear = input.int(2999, "To Year", minval = 1900) i_toMonth = input.int(1, "To Month", minval = 1, maxval = 12) i_toDay = input.int(1, "To Day", minval = 1, maxval = 31) fromDate = timestamp(i_fromYear, i_fromMonth, i_fromDay, 00, 00) toDate = timestamp(i_toYear, i_toMonth, i_toDay, 23, 59) f_tradeDateIsAllowed() => not i_dateFilter or (time >= fromDate and time <= toDate) /// ecin1=input.int(3,title="Exit candle 1") ecin2=input.int(14,title="Exit candle 2") long=f_tradeDateIsAllowed() and haOpen < haClose and haOpen[1] > haClose[1] and close>open ex1=haOpen > haClose and haOpen[1] < haClose[1] upcan=haOpen < haClose?1:0 ex2a = ta.cum( upcan ) - ta.valuewhen( haOpen < haClose and haOpen[1] > haClose[1], ta.cum( upcan ),0 )+1 ex2b=ta.barssince(haOpen < haClose and haOpen[1] > haClose[1])+1 ex2=ex2a==ecin1 and ex2b==ecin1 and haClose<out ex3=ex2a==ecin2 and ex2b==ecin2 and haClose>out longexit= ex1 or ex2 or ex3 //bgcolor(ex1?color.red:na) //bgcolor(ex2?color.aqua:na) //bgcolor(long?color.yellow:na) sl_inp = input.float(4.3, title='Stop Loss %',step=0.1)/100 tp_inp = input.float(27.6, title='Take Profit %',step=0.1)/100 // 仅在持仓时计算止损/止盈价格 stop_level = strategy.position_size > 0 ? strategy.position_avg_price * (1 - sl_inp) : na take_level = strategy.position_size > 0 ? strategy.position_avg_price * (1 + tp_inp) : na if long strategy.entry(id="Entry", direction=strategy.long,comment="BUY") // 仅在持仓有效时挂出止损止盈单 if strategy.position_size > 0 strategy.exit(id="B",from_entry="Entry" ,stop=stop_level, limit=take_level,comment_profit="TP",comment_loss="SL" ) if longexit strategy.close(id="Entry",comment="SELL")
额外说明
- 修改
process_orders_on_close=false后,回测中止损单会在价格触及止损线的第一时间执行,而非等到收盘,能有效控制亏损幅度 - 优化后的止损价格计算逻辑避免了非持仓状态下的无效赋值,确保参数仅在持仓时生效
内容的提问来源于stack exchange,提问作者Jerry Roach
相关产品推荐
相关产品推荐

