Pine Script分形止损策略平仓后异常重复开仓问题求解
问题根因
平仓后连续同方向重复开仓的核心是3个逻辑漏洞:
- 开仓条件无触发边界、无持仓校验:原代码用
fastEMA>slowEMA作为开多条件,只要快慢线处于多头排列,这个条件在每根K线都成立,止损/止盈平仓后会立刻触发重新开仓,不会等新的入场信号 - 空单平仓逻辑缺失:原代码只写了多单的EMA死叉平仓规则,空单没有对应的EMA金叉平仓逻辑,空单止损出场后会立刻重新进空
- 止损值未做重置:平仓后旧的止损价位会一直保留,同时原代码写的
limit=1000000、limit=0.0属于无效止盈参数,会干扰策略引擎的出场判定逻辑
修复方案
- 把开仓条件从「EMA多空排列持续成立」改成「EMA金叉/死叉当根K线触发」,只在交叉发生的瞬间允许开仓
- 增加引擎层面的禁加仓设置,从底层禁止同方向重复开仓
- 补全空单的EMA交叉平仓逻辑
- 把止损更新逻辑和持仓状态绑定,平仓后自动清空对应方向的旧止损值,避免干扰下一次开仓
- 移除无效的止盈参数,需要止盈时可传入自定义的止盈价位即可
修复后完整代码
//@version=4 strategy("Fractal SMA ADX 2 修复版", overlay=true, pyramiding=0) //////////////////////////ADX //Average Directional Index Calculation (ADX) lengthADX = input(title="lengthADX", type=input.integer, defval=14) threshold = input(title="ADX threshold Exit", type=input.integer, defval=30) TrueRange = max(max(high-low, abs(high-nz(close[1]))), abs(low-nz(close[1]))) DirectionalMovementPlus = high-nz(high[1]) > nz(low[1])-low ? max(high-nz(high[1]), 0): 0 DirectionalMovementMinus = nz(low[1])-low > high-nz(high[1]) ? max(nz(low[1])-low, 0): 0 SmoothedTrueRange = 0.0 SmoothedTrueRange := nz(SmoothedTrueRange[1]) - (nz(SmoothedTrueRange[1])/lengthADX) + TrueRange SmoothedDirectionalMovementPlus = 0.0 SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - (nz(SmoothedDirectionalMovementPlus[1])/lengthADX) + DirectionalMovementPlus SmoothedDirectionalMovementMinus = 0.0 SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - (nz(SmoothedDirectionalMovementMinus[1])/lengthADX) + DirectionalMovementMinus DIPlus = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100 DIMinus = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100 DX = abs(DIPlus-DIMinus) / (DIPlus+DIMinus)*100 ADX = sma(DX, lengthADX) //Frctals Above/Below Desired Moving Average SmaConditionFractal = sma(close, 55) filteredtopf = ((high[4] < high[3] and high[3] < high[2] and high[2] > high[1] and high[1] > high[0]) and (high[2]<SmaConditionFractal and ADX>threshold)) ? high[2]:na plotshape(filteredtopf, title='Filtered Top Fractals', style=shape.triangledown,size=size.small, location=location.abovebar, color=color.red,offset=-2) filteredbotf = ((low[4] > low[3] and low[3] > low[2] and low[2] < low[1] and low[1] < low[0]) and (low[2]>SmaConditionFractal and ADX>threshold)) ? low[2]:na plotshape(filteredbotf, title='Filtered Bottom Fractals', style=shape.triangleup, size=size.small,location=location.belowbar, color=color.lime,offset=-2) // Define a 5-bar fractals greater than sma55 and adx>30 upFractal = ((high[4] < high[3] and high[3] < high[2] and high[2] > high[1] and high[1] > high[0]) and (high[2]<SmaConditionFractal and ADX>threshold)) dnFractal = ((low[4] > low[3] and low[3] > low[2] and low[2] < low[1] and low[1] < low[0]) and (low[2]>SmaConditionFractal and ADX>threshold)) //Entry Conditions fastEMA = ema(close, 14) slowEMA = ema(close, 28) // 仅在金叉/死叉当根K线触发开仓信号 longCondition = crossover(fastEMA, slowEMA) shortCondition = crossunder(fastEMA, slowEMA) // 平仓信号 longExit = crossunder(fastEMA, slowEMA) shortExit = crossover(fastEMA, slowEMA) // Set your stop-loss var float stop_long_FB = na var float stop_short_FB = na // 持仓时更新对应方向止损,平仓后重置止损值 if strategy.position_size > 0 if dnFractal stop_long_FB := low[2] else stop_long_FB := na if strategy.position_size < 0 if upFractal stop_short_FB := high[2] else stop_short_FB := na //Strategy Execution if longCondition strategy.entry("long", strategy.long) // 仅持多单时绑定多单止损、EMA平仓规则 if strategy.position_size > 0 strategy.exit("Stop Loss Long", "long", stop = stop_long_FB) strategy.close("long", when=longExit) if shortCondition strategy.entry("short", strategy.short) // 仅持空单时绑定空单止损、EMA平仓规则 if strategy.position_size < 0 strategy.exit("Stop Loss Short", "short", stop = stop_short_FB) strategy.close("short", when=shortExit)
内容的提问来源于stack exchange,提问作者mehdi shokati
相关产品推荐
相关产品推荐

