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

TradingView Pine Script百分比止盈止损脚本运行异常排查

Pine Script 百分比止盈止损脚本异常修复

问题成因

原脚本的两个异常完全是strategy.exit()调用逻辑错误导致的:

  • 两个分段止盈的exit指令都绑定了止损参数,两个指令会独立监听止损触发条件,SL触发时两个指令会分别执行平仓,直接导致重复平仓、仓位超卖
  • TP1触发后没有作废对应挂单,TP2的exit指令没有正确匹配剩余仓位,导致TP2触发时仅平半仓,无法平完所有剩余头寸
  • 初始仓位取值没有在开仓时锁定,TP1部分平仓后数值会偏移,导致平仓数量计算错误

核心修复逻辑

  • 拆分止盈、止损指令:单独设置全仓止损的exit指令,两个分段止盈指令不再绑定止损参数,从根源避免止损触发时重复平仓
  • 增加TP1成交状态标记:开仓时重置标记,TP1成交后自动取消TP1对应的挂单,仅保留TP2指令监听剩余仓位
  • 开仓当根K线直接锁定初始开仓量,不会因为后续部分平仓导致仓位数值计算偏移
  • 修正TP2的平仓规则,TP1部分平仓后,TP2触发时自动平掉全部剩余仓位,不会出现仓位残留

修复后完整代码

// This source code is subject to the terms of the Mozilla Public License 2.0
// © SafetyHammer
// 修复分段止盈止损逻辑异常

//@version=4
strategy(title="Take profit (% of instrument price)", overlay=true, pyramiding=0, initial_capital=10000, default_qty_type=strategy.cash, default_qty_value=10000, commission_type=strategy.commission.percent, commission_value=0.1)

// ————参数设置————
// 均线参数
FastPeriod = input(title="Fast MA Period", type=input.integer, defval=9, minval=1, group="Moving Average")
SlowPeriod = input(title="Slow MA Period", type=input.integer, defval=50, minval=1, group="Moving Average")

// 止盈止损参数
TP1Perc = input(title="Long TP1 (%)", type=input.float, minval=0.0, step=0.1, defval=0.5, group="TP & SL") 
TP2Perc = input(title="Long TP2 (%)", type=input.float, minval=0.0, step=0.1, defval=1, group="TP & SL") 
SLPerc = input(title="Long Stop Loss (%)", type=input.float, minval=0.0, step=0.1, defval=0.5, group="TP & SL")
TP1_Ratio = input(title="Close Position % @ TP1", type=input.float, defval=50, step=1, group="TP & SL", tooltip="TP1触发时平仓的仓位比例,例:50代表平50%仓位")/100

// ————指标计算————
fastSMA = ema(close, FastPeriod)
slowSMA = ema(close, SlowPeriod)

// 交易信号
enterLong  = crossover(fastSMA, slowSMA)

// 绘图
plot(series=fastSMA, color=color.green, title="Fast MA", linewidth=2)
plot(series=slowSMA, color=color.red, title="Slow MA", linewidth=2)

// ————价格与仓位计算————
var float initialPosSize = na
var bool tp1Filled = false

// 开仓时锁定初始仓位,重置TP1状态
if enterLong
    initialPosSize := strategy.equity / close
    tp1Filled := false

// 百分比转价格计算
tp1Price = strategy.position_size > 0 ? strategy.position_avg_price * (1 + TP1Perc / 100) : na
tp2Price = strategy.position_size > 0 ? strategy.position_avg_price * (1 + TP2Perc / 100) : na
slPrice = strategy.position_size > 0 ? strategy.position_avg_price * (1 - SLPerc / 100) : na

// 检测TP1是否成交
if strategy.position_size > 0 and strategy.position_size < initialPosSize * 0.99
    tp1Filled := true

// ————下单逻辑————
// 开多单
if enterLong
    strategy.entry(id="Long", long=true)

// 持仓时挂单
if strategy.position_size > 0
    // 全仓止损,单独挂单避免重复平仓
    strategy.exit("SL", from_entry="Long", stop=slPrice, qty=initialPosSize)
    // TP1未成交时挂TP1部分止盈单
    if not tp1Filled
        strategy.exit("TP1", from_entry="Long", limit=tp1Price, qty=initialPosSize * TP1_Ratio)
    // TP1成交后挂TP2全平剩余仓位
    else
        strategy.exit("TP2", from_entry="Long", limit=tp2Price)

// ————止盈止损价位绘图————
plot(series=(strategy.position_size > 0 and not tp1Filled) ? tp1Price : na, color=color.new(color.green, 0), style=plot.style_circles, linewidth=1, title="Take Profit 1")
plot(series=(strategy.position_size > 0 and tp1Filled) ? tp2Price : na, color=color.new(color.green, 0), style=plot.style_circles, linewidth=1, title="Take Profit 2")
plot(series=(strategy.position_size > 0) ? slPrice : na, color=color.new(color.red, 0), style=plot.style_circles, linewidth=1, title="Stop Loss")

验证说明

  • 修复后策略测试器可以正确识别TP1、TP2、SL三类成交事件
  • TP1触发时仅平设定比例的仓位,TP2触发时自动平掉全部剩余仓位
  • SL触发时仅执行一次全仓平仓,不会出现重复平仓的错误
  • 可以直接调整参数适配不同品种、不同止盈止损比例的需求

内容的提问来源于stack exchange,提问作者Fantazma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 23:48:27