You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

回测中Stop Loss未在次日K线触发的技术问题

问题描述

回测过程中,在当日K线收盘价位置进场开仓后,次日止损(Stop Loss)条件触发,但交易并未通过止损指令即时离场,而是要等到当日K线收盘时才执行平仓操作,导致实际亏损幅度达到13-14%,远超过设定的4.3%止损幅度。交易列表已识别到止损条件,但未及时执行离场。

问题原因分析

代码中策略初始化参数process_orders_on_close=true是核心问题:

  • 该参数强制所有订单(包括止损、止盈单)都在K线周期结束时才执行,而非价格触及止损/止盈价位的即时时刻
  • 即使盘中价格已经跌破设定的止损线,也会等到收盘才平仓,从而放大了实际亏损
解决方案
  1. 修改订单执行时机参数:将process_orders_on_close设为false,让止损/止盈单在价格触发时即时执行
  2. 优化止损价格计算逻辑:确保止损价仅在持仓状态下基于持仓均价计算,避免非持仓时的无效赋值
  3. 保留实时计算参数:维持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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 15:15:43