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

PineScript如何实现新plotshape出现后停止旧标记显示

PineScript平均K线策略x标记趋势隔离修复

问题背景

我是PineScript新手,正在TradingView平台基于开源脚本开发Heikin-Ashi(平均K线)交易策略。
开发目标为:平均K线买卖信号出现后,计算对应买卖趋势周期内K线的涨跌幅,即代码中定义的percUP、percDOWN变量,同时生成用于告警的"x"形plotshape标记。
现有代码已经完成基础计算逻辑,但存在显示问题:"x"形标记没有跟随趋势做隔离,买入趋势中会出现卖出类x标记,卖出趋势中会出现买入类x标记,需要修正为:

  • 买入趋势周期内仅显示买入类x标记,隐藏所有卖出类x标记
  • 卖出趋势周期内仅显示卖出类x标记,隐藏所有买入类x标记

问题原因

原有lTrend、sTrend的判断逻辑仅校验了距离上次买卖信号的K线间隔、涨跌幅阈值,没有绑定当前趋势状态,只要满足数值条件就会渲染标记,哪怕趋势已经发生反转;同时原有ta.barssince()逻辑没有处理无历史信号时返回na的边界情况,会出现判断异常。

修复方案

核心修改三点:

  • 给两类x标记的显示条件增加趋势状态校验:买入x仅在多头趋势(trendState == true)下显示,卖出x仅在空头趋势(trendState == false)下显示
  • 增加na值判断,兼容策略加载初期没有历史买卖信号的边界场景
  • 修正卖出x标记的显示位置,从K线下方调整到K线上方,和卖出标签位置保持一致,避免遮挡;同时修正原代码中卖出x标记title误写为买入标记的小bug

修改后的核心代码段

// 涨跌幅计算逻辑保持不变
percUP = ((high - open) / open) * 100
percUP := math.round(percUP, 2)

percDOWN = ((low - open) / open) * 100
percDOWN := math.round(percDOWN, 2)

// 修复:增加趋势判断+na值兼容
lTrend = not na(ta.barssince(long_final)) and trendState == true and percUP < 0.1 
sTrend = not na(ta.barssince(short_final)) and trendState == false and percDOWN > -0.1

// 修复:卖出x标记位置调整到K线上方,修正title命名
plotshape(lTrend, style=shape.xcross, location=location.belowbar, color=color.new(color.blue, 0), size=size.tiny, title='buy X label', textcolor=color.new(color.blue, 0))
plotshape(sTrend, style=shape.xcross, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny, title='sell X label', textcolor=color.new(color.red, 0))

完整可运行代码

//@version=5
indicator('heikin ashi alert', overlay=true)
EMAlength = input(15, 'EMA LENGTH?')

src = ohlc4
haOpen = 0.0
haOpen := (src + nz(haOpen[1])) / 2
haC = (ohlc4 + nz(haOpen) + math.max(high, nz(haOpen)) + math.min(low, nz(haOpen))) / 4
EMA1 = ta.ema(haC, EMAlength)
EMA2 = ta.ema(EMA1, EMAlength)
EMA3 = ta.ema(EMA2, EMAlength)
TMA1 = 3 * EMA1 - 3 * EMA2 + EMA3
EMA4 = ta.ema(TMA1, EMAlength)
EMA5 = ta.ema(EMA4, EMAlength)
EMA6 = ta.ema(EMA5, EMAlength)
TMA2 = 3 * EMA4 - 3 * EMA5 + EMA6
IPEK = TMA1 - TMA2
YASIN = TMA1 + IPEK
EMA7 = ta.ema(hlc3, EMAlength)
EMA8 = ta.ema(EMA7, EMAlength)
EMA9 = ta.ema(EMA8, EMAlength)
TMA3 = 3 * EMA7 - 3 * EMA8 + EMA9
EMA10 = ta.ema(TMA3, EMAlength)
EMA11 = ta.ema(EMA10, EMAlength)
EMA12 = ta.ema(EMA11, EMAlength)
TMA4 = 3 * EMA10 - 3 * EMA11 + EMA12
IPEK1 = TMA3 - TMA4
YASIN1 = TMA3 + IPEK1

mavi = YASIN1
kirmizi = YASIN

longCond = mavi > kirmizi and mavi[1] <= kirmizi[1] 
shortCond = mavi < kirmizi and mavi[1] >= kirmizi[1]

trendState = kirmizi < mavi ? true : kirmizi > mavi ? false : na
closePlot = plot(kirmizi, title='Close Line', color=color.new(#009900, 90), linewidth=10, style=plot.style_line)
openPlot = plot(mavi, title='Open Line', color=color.new(#CC0000, 90), linewidth=10, style=plot.style_line)
closePlotU = plot(trendState ? kirmizi : na, editable=false, transp=100)
openPlotU = plot(trendState ? mavi : na, editable=false, transp=100)
closePlotD = plot(trendState ? na : kirmizi, editable=false, transp=100)
openPlotD = plot(trendState ? na : mavi, editable=false, transp=100)
fill(openPlotU, closePlotU, title='Up Trend Fill', color=color.new(#009900, 1))
fill(openPlotD, closePlotD, title='Down Trend Fill', color=color.new(#CC0000, 1))


last_signal = 0
long_final = longCond and (nz(last_signal[1]) == 0 or nz(last_signal[1]) == -1) 
short_final = shortCond and (nz(last_signal[1]) == 0 or nz(last_signal[1]) == 1)


alertcondition(long_final, title='buy alarm', message='buy signal!!!')
alertcondition(short_final, title='sell alarm', message='sell signal!!!')

last_signal := long_final ? 1 : short_final ? -1 : last_signal[1]

plotshape(long_final, style=shape.labelup, location=location.belowbar, color=color.new(color.blue, 0), size=size.tiny, title='buy label', text='BUY', textcolor=color.new(color.white, 0))
plotshape(short_final, style=shape.labeldown, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny, title='sell label', text='SELL', textcolor=color.new(color.white, 0))


// 涨跌幅计算
percUP = ((high - open) / open) * 100
percUP := math.round(percUP, 2)

percDOWN = ((low - open) / open) * 100
percDOWN := math.round(percDOWN, 2)

// 修复后x标记判断逻辑
lTrend = not na(ta.barssince(long_final)) and trendState == true and percUP < 0.1 
sTrend = not na(ta.barssince(short_final)) and trendState == false and percDOWN > -0.1

plotshape(lTrend, style=shape.xcross, location=location.belowbar, color=color.new(color.blue, 0), size=size.tiny, title='buy X label', textcolor=color.new(color.blue, 0))
plotshape(sTrend, style=shape.xcross, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny, title='sell X label', textcolor=color.new(color.red, 0))


plot(percUP, style=plot.style_columns, color=color.new(#00ffaa, 90))
plot(percDOWN, style=plot.style_columns, color=color.new(color.red, 90))


// 告警配置
// alertcondition(lTrend[1], title='alert1', message='')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:36:29