回测异常:我的Pull-back策略为何开仓即平仓?
策略回测异常排查:开仓同时平仓问题
我采用Pull-back策略开仓,以近期Swing low(图中绿线所示)作为止损,设置1:1风险回报比。但回测时发现,代码在多数情况下会在开仓的同时平仓,仅少数交易正常。
异常交易截图

开仓/平仓逻辑代码
//long condition // we go long when there is a buy signal and no opentrades. longCondition = buy_signal and strategy.opentrades == 0 // entry if longCondition //Stop loss will be a recent swing low longSL = stopLevel //we will target for 1:1 risk/reward from stop loss longTP = close + (close - longSL) strategy.entry("LONG", strategy.long, comment = "LONG") strategy.exit("EXIT LONG", "LONG", stop = longSL, limit = longTP, comment = "LONG SL/TP")
正常交易示例截图

Swing High/Low及Simple Pull-Back计算代码
//====LOGIC FOR SWING HIGH/LOW==== strategy("SIMPLE PULL BACK + SWING HIGH/LOW", overlay=true, precision = 4, initial_capital=1000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, currency=currency.USD, process_orders_on_close=true, pyramiding=0) // Inputs pvtLenL = input.int(3, minval=1, title="Pivot Length Left Hand Side") pvtLenR = input.int(3, minval=1, title="Pivot Length Right Hand Side") showStop = input.bool(true, title="Show Recent Low Stop?") // Get High and Low Pivot Points pvthi_ = ta.pivothigh(high, pvtLenL, pvtLenR) pvtlo_ = ta.pivotlow(low, pvtLenL, pvtLenR) // Force Pivot completion before plotting. Shunt = 1 //Wait for close before printing pivot? 1 for true 0 for flase maxLvlLen = 0 //Maximum Extension Length pvthi = pvthi_[Shunt] pvtlo = pvtlo_[Shunt] // Count How many candles for current Pivot Level, If new reset. counthi = ta.barssince(not na(pvthi)) countlo = ta.barssince(not na(pvtlo)) pvthis = fixnan(pvthi) pvtlos = fixnan(pvtlo) hipc = ta.change(pvthis) != 0 ? na : color.fuchsia lopc = ta.change(pvtlos) != 0 ? na : color.rgb(0, 207, 7) // Stop Levels stopLevel = ta.valuewhen(pvtlo_, low[pvtLenR], 0) // ====LOGIC FOR PULL-BACK==== lookback = input(defval = 5, title = 'Lookback') lower_barrier = input(defval = 20, title = 'Lower Barrier') lower_threshold = input(defval = 33, title = 'Lower Threshold') upper_barrier = input(defval = 80, title = 'Upper Barrier') upper_threshold = input(defval = 67, title = 'Upper Threshold') rsi = ta.rsi(close, lookback) buy_signal = rsi >= lower_barrier and rsi < rsi[1] and rsi[1] > lower_barrier and rsi[1] < lower_threshold and rsi[2] < lower_barrier alertcondition(buy_signal, title = "LONG") sell_signal = rsi <= upper_barrier and rsi > rsi[1] and rsi[1] < upper_barrier and rsi[1] > upper_threshold and rsi[2] > upper_barrier
异常原因排查及解决方案
核心问题:止损价高于开仓价,触发即时平仓
你的策略设置了process_orders_on_close=true,订单在收盘价执行。当计算出的stopLevel(近期Swing low对应价格)大于等于开仓K线的收盘价时,多单的止损逻辑(价格跌破止损价平仓)会被立刻触发——因为当前价格已经低于止损价,导致开仓的同时直接平仓。
具体修正方案
修正止损价计算逻辑
当前用未延迟的pvtlo_取止损价,可能拿到未完全确认的Swing low,甚至价格高于当前收盘价。改用延迟后的已确认Swing low计算:// 取已确认的Swing low对应的最低价 stopLevel = ta.valuewhen(not na(pvtlo), low[pvtLenR], 0)添加止损价有效性校验
在开仓条件中加入止损价必须低于当前收盘价的判断,避免无效止损触发:longCondition = buy_signal and strategy.opentrades == 0 and not na(stopLevel) and stopLevel < close调整订单执行模式(可选)
如果希望订单在下一根K线开盘价执行,可将process_orders_on_close改为false,避免当前K线收盘价直接触发止损,但需结合策略逻辑适配。
额外验证建议
回测时添加plot(stopLevel, color=color.red),对比stopLevel与close的数值关系,确认异常交易发生时两者的大小是否符合上述判断。
内容的提问来源于stack exchange,提问作者Saad Hassan
相关产品推荐
相关产品推荐

