如何让Pine Script每个订单仅执行一次strategy.close部分平仓?
解决Pine Script中单次部分平仓的问题
核心问题分析
你当前的代码中,stcDownBreakouts条件可能在多根K线上持续触发,加上用仓位比例判断的逻辑,当使用qty_percent=90时,第一次平仓后剩余仓位为初始的10%,后续若条件再次满足,会继续尝试平仓剩余仓位的90%,这不符合你“仅对同一订单平仓一次”的需求。
解决方案:使用平仓状态标记
通过添加一个持久化的布尔变量记录平仓状态,可确保针对同一笔入场订单仅触发一次指定比例的部分平仓。具体实现步骤:
- 用
var关键字声明跨K线持久化的标记变量 - 触发平仓时同步将标记设为
true - 每次新订单入场时重置标记为
false
修改后的完整代码如下:
//@version=5 strategy('sample', overlay=true, max_labels_count = 500) ////////////////////////////////////////////////////////////// // Simple SMA strategy with TP/SL and Schaff Trend partial close ////////////////////////////////////////////////////////////// // sma length and TP/SL setting sma_per = input.int(200, title='SMA Lookback Period', minval=1) sl_inp = input(4.3, title='Stop Loss %') / 100 tp_inp = input(1.0, title='Take Profit %') / 100 // Getting a SMA sma = ta.sma(close, sma_per) // TP/SL calculate stop_level = strategy.position_avg_price * (1 - sl_inp) take_level = strategy.position_avg_price * (1 + tp_inp) ////////////////////////////////////////////////////////////// // Schaff Trend logic fastLength = input(title='MACD Fast Length', defval=23) slowLength = input(title='MACD Slow Length', defval=50) cycleLength = input(title='Cycle Length', defval=10) d1Length = input(title='1st %D Length', defval=3) d2Length = input(title='2nd %D Length', defval=3) src = input(title='Source', defval=close) upper = input(title='Upper Band', defval=75) lower = input(title='Lower Band', defval=25) highlightBreakouts = input(title='Highlight Breakouts ?', defval=true) macd = ta.ema(src, fastLength) - ta.ema(src, slowLength) k = nz(fixnan(ta.stoch(macd, macd, macd, cycleLength))) d = ta.ema(k, d1Length) kd = nz(fixnan(ta.stoch(d, d, d, cycleLength))) stc = ta.ema(kd, d2Length) stc := math.max(math.min(stc, 100), 0) stcColor1 = stc > stc[1] ? color.green : color.red stcColor2 = stc > upper ? color.green : stc <= lower ? color.red : color.orange stcColor = highlightBreakouts ? stcColor2 : stcColor1 // Using security to close when 1H Schaff Trend is Down ex = request.security(syminfo.tickerid, "60", stc) stcDownBreakouts = ta.crossunder(ex, 75) // 新增:跨K线持久化的平仓状态标记 var bool hasPartialClosed = false ////////////////////////////////////////////////////////////// // Getting a Long position if (ta.crossover(close, sma)) strategy.entry(id = 'Long Entry', direction = strategy.long) // 新订单入场时重置平仓标记 hasPartialClosed := false // Strategy exit for TP/SL if (strategy.opentrades > 0) strategy.exit(id = 'TP/SL Exit', from_entry = 'Long Entry', stop = stop_level, limit = take_level) // 修改后的部分平仓逻辑:仅在未执行过平仓时触发 if (strategy.opentrades > 0 and stcDownBreakouts and not hasPartialClosed) strategy.close(id='Long Entry', qty_percent = 90, comment='Long Partial Exit') // 标记已完成部分平仓 hasPartialClosed := true // Plot for logic plot(sma, color=color.new(color.orange, 0), linewidth=2) plot(stop_level, color=color.new(color.red, 0), style=plot.style_linebr, linewidth=2) plot(take_level, color=color.new(color.green, 0), style=plot.style_linebr, linewidth=2)
关键修改说明
var bool hasPartialClosed = false:var关键字确保变量在脚本运行期间保留值,不会随K线刷新重置- 入场新订单时重置标记,保证每笔新仓位都能触发一次部分平仓
- 平仓条件加入
not hasPartialClosed限制,执行后标记设为true,彻底避免重复平仓
此方案可实现每笔入场订单仅执行一次90%仓位的部分平仓,剩余10%仓位继续由止损/止盈规则接管。
内容的提问来源于stack exchange,提问作者disgem009
相关产品推荐
相关产品推荐

