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

TradingView Pine脚本重绘、移动止损失效及告警异常问题求助

问题汇总
  • 策略运行存在矛盾:设置calc_on_order_fills=true时出现重绘(repainting)问题,关闭该参数后strategy.exit内的移动止损无法在入场首根K线生效,仅能在下一根K线触发
  • 策略告警触发频率过高,待确认是否与重绘相关
  • 已尝试以下方案均未解决问题:
    • 改用ATR计算移动止损,替换入场订单中的trail_price、trail_offset参数
    • 采用前一根K线的open/close/high/low参数计算入场订单条件
    • 增加strategy.closedtrades.entry_time(strategy.closedtrades) != time或strategy.closedtrades.entry_bar_index(strategy.closedtrades) != bar_index判断逻辑
问题根因
  1. 重绘与告警过频根源
    calc_on_order_fills=true的运行逻辑是订单成交时,会在当前未收盘的K线内重新执行全量脚本计算。此时当前K线的价格数据是实时变动的未定型数据,必然导致信号重绘;同时未收盘K线内的重复计算会反复触发告警,这就是告警频率过高的直接原因。
    另外代码中平均K线(Heikin Ashi)计算存在未来函数问题:HAhigh、HAlow直接引用当前未收盘K线的价格数据,没有偏移引用已收盘的历史K线,也会加重重绘问题。

  2. 移动止损首根K线不生效根源
    关闭calc_on_order_fills后,脚本默认在K线收盘时才更新持仓状态,入场当根K线内脚本识别不到持仓,自然不会执行strategy.exit挂载止损单,只能等到下一根K线才触发出场逻辑。同时代码中trail_price = strategy.position_avg_price的写法存在逻辑问题:trail_price是移动止损的激活价格,入场当根K线strategy.position_avg_price还未完成赋值,无法正确挂载止损。

修复方案
  1. 策略初始化参数关闭calc_on_order_fills,保留calc_on_every_tick = false,从根源避免未收盘K线重复计算导致的重绘、告警重复问题。
  2. 修正平均K线计算逻辑,所有价格参数引用已收盘的前一根K线数据,消除未来函数。
  3. 调整出场逻辑:入场订单直接绑定固定止盈止损,保证入场当根就挂载好出场单;持仓超过1根K线后再启动移动止损跟踪,避免首根K线持仓状态识别延迟问题。
  4. 移除strategy.exit中直接引用strategy.position_avg_price作为trail_price的写法,手动计算持仓后的最高/最低盈利点位,动态调整移动止损触发价。
修复后完整代码
//@version=5
strategy("My strategy", overlay=true, calc_on_every_tick = false, calc_on_order_fills = false)


// Set exit levels with input options (optional)
LimitPerc = input.int(title="Take Profit (0,1%)", minval=0, step=1, defval=10) * 0.001
StopPerc = input.int(title="Stop Loss / Trailing Offset (0,1%)", minval=0, step=1, defval=5) * 0.001
TrailPerc = input.int(title="Trailing Offset (0,1%)", minval=0, step=1, defval=2) * 0.001

 
//Movin Averages incl Plot
//EMA
emaplot = input (true, title="Show EMA on chart")
len = input.int(minval=1, step=1, defval=9, title="ema Length")
src = close[1]
out = ta.ema(src, len)
up = out > out[1]
down = out < out[1]
mycolor = up ? color.green : down ? color.red : color.blue
plot(out and emaplot ? out :na, title="EMA", color=mycolor, linewidth=3)

//SMA
smaplot = input (true, title="Show SMA on chart")
len2 = input.int(minval=1, step=1, defval=2, title="sma Length")
src2 = close[1]
out2 = ta.sma(src2, len2)
up2 = out2 > out2[1]
down2 = out2 < out2[1]
mycolor2 = up2 ? color.green : down2 ? color.red : color.blue
plot(out2 and smaplot ? out2 :na , title="SMA", color=mycolor2, linewidth=1)


//Stochastic Momentum Index incl Plot
//Stoch RSI
a = input.int(minval=1, step=1, defval=2, title = "Percent K Length")
b = input.int(minval=1, step=1, defval=2, title = "Percent D Length")
// Range Calculation
ll = ta.lowest (low[1], a)
hh = ta.highest (high[1], a)
diff = hh - ll
rdiff = close[1] - (hh+ll)/2
// Nested Moving Average for smoother curves
avgrel = ta.ema(ta.ema(rdiff,b),b)
avgdiff = ta.ema(ta.ema(diff,b),b)
// SMI calculations
SMI = avgdiff != 0 ? (avgrel/(avgdiff/2)*100) : 0
SMIsignal = ta.ema(SMI,b)
SMIup = SMI > SMI[1]
SMIdown = SMI < SMI[1]


//Heikin Ashi 修正为全量引用前一根已收盘K线数据
HAopen  = (open[1]+close[1])/2
HAclose = ohlc4[1]
HAhigh  = math.max (high[1], open[1], close[1])
HAlow   = math.min (low[1], open[1], close[1])
HAup    = HAopen < HAclose
HAdown  = HAopen > HAclose


//Conditions for trades
LongCondition = HAup and SMIup and up and up2 and (strategy.opentrades == 0)
ShortCondition = HAdown and SMIdown and down and down2 and (strategy.opentrades == 0)

// 记录入场K线索引
var longEntryBar = na
var shortEntryBar = na

//Submit entry orders 直接绑定固定止盈止损,入场当根生效
if (LongCondition and time>timestamp(2022, 07, 04, 07, 00))
    longStop = close * (1 - StopPerc)
    longLimit = close * (1 + LimitPerc)
    strategy.entry(id = "Long", direction = strategy.long, alert_message = "Place Long Order", comment = "Long Entry", stop=longStop, limit=longLimit)
    longEntryBar := bar_index

if (ShortCondition and time>timestamp(2022, 07, 04, 07, 00))
    shortStop = close * (1 + StopPerc)
    shortLimit = close * (1 - LimitPerc)
    strategy.entry(id = "Short", direction = strategy.short, alert_message = "Place Short Order", comment = "Short Entry", stop=shortStop, limit=shortLimit)
    shortEntryBar := bar_index


// 持仓超过1根K线后启动移动止损
if (strategy.position_size > 0 and bar_index > longEntryBar)
    // 计算持仓后最高价
    longHighest = ta.highest(high, bar_index - longEntryBar)
    // 移动止损价
    longTrailStop = longHighest * (1 - TrailPerc)
    strategy.exit(id = "Long", alert_trailing = "Exit Long Order", stop=longTrailStop, comment = "Long Exit")

if (strategy.position_size < 0 and bar_index > shortEntryBar)
    // 计算持仓后最低价
    shortLowest = ta.lowest(low, bar_index - shortEntryBar)
    // 移动止损价
    shortTrailStop = shortLowest * (1 + TrailPerc)
    strategy.exit(id = "Short", alert_trailing = "Exit Short Order", stop=shortTrailStop, comment = "Short Exit")

//END

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:24:22