Pine Script优化需求:仅显示蜡烛突破入场线的首个买入信号
问题描述
当蜡烛高点突破绿色入场线时,当前代码会生成6个重复的买入信号,但实际仅需要第一个突破入场线的蜡烛对应的买入信号。
问题根源
原代码的longCondition通过判断过去6根K线的buyLine值,只要当前K线高点大于其中任意一根的buyLine就触发信号,导致后续连续6根K线都满足条件,从而生成重复信号。
解决方案
添加状态变量记录信号触发状态,限制信号仅触发一次,直到止损后重置状态:
- 用
var类型布尔变量标记是否已触发过信号 - 用
ta.valuewhen()直接获取最近一次信号触发时的关键价格,替代多根K线的冗余判断 - 仅当首次满足突破条件且未触发过信号时,生成买入/卖出标签
修改后的完整代码
//VWAP ploting vwapSource = close vwap = ta.vwap(vwapSource) plot(vwap, color=color.blue, linewidth=2, title="VWAP") //date and time input inputTime = input.time(timestamp("026 Jul 2023 09:45:00 GMT+5:30"), "Date") //Searching Bar by time searchBarTime = timestamp(year(time), month(time), dayofmonth(time), hour(inputTime), minute(inputTime)) // Check if the current bar matches the desired time isTargetBar = time == searchBarTime //ploting RSI and avg RSI len = input(title="RSI Length", defval=14) src = input(title="RSI Source", defval=close) buffer = input(0.001, title="Buffer Length") textColor = color.white noneColor = color.new(color.white, 100) ma(source, length, type) => switch type "SMA" => ta.sma(source, length) "Bollinger Bands" => ta.sma(source, length) "EMA" => ta.ema(source, length) "SMMA (RMA)" => ta.rma(source, length) "WMA" => ta.wma(source, length) "VWMA" => ta.vwma(source, length) maTypeInput = input.string("SMA", title="MA Type", options=["SMA", "Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings") maLengthInput = input.int(14, title="MA Length", group="MA Settings") osc = ta.rsi(src, len) rsiMA = ma(osc, maLengthInput, maTypeInput) // plot(osc, title="RSI", linewidth=2, color=color.rgb(255, 255, 255, 20)) // plot(rsiMA, "RSI-based MA", color=color.yellow) bufferHigh = high + (high * buffer) bufferLow = low - (low * buffer) bool isVwapAboveCandle = na bool isVwapBelowCandle = na bool isRsiAboveAvg = na bool isRsipBelowAvg = na if isTargetBar isVwapAboveCandle := vwap > close isVwapBelowCandle := vwap < close isRsiAboveAvg := osc > rsiMA isRsipBelowAvg := osc < rsiMA buySignal = isVwapBelowCandle and isRsiAboveAvg shortSignal = isVwapAboveCandle and isRsipBelowAvg if buySignal buySignalTriangleUp = label.new(bar_index,(low-(0.004 * low)), style=label.style_triangleup, color=color.lime) if shortSignal shortSignalTriangleDown = label.new(bar_index,(high+(0.004 * high)), style=label.style_triangledown, color=color.red) // plotshape(buySignal, location = location.belowbar, style = shape.arrowup, color = color.green, text ="BUY") // plotshape(shortSignal, location = location.abovebar, style = shape.arrowdown, color = color.red, text ="SHORT") // //=====stoploss===== var float sl = 0.0 for i = 1 to 5 if buySignal or shortSignal //or shortcondition or pe_signalcondition1[i] or pe_signalcondition2[i]) sl := bufferHigh - bufferLow // //=========define target for long trades ======= tp1 = sl tp2 = sl*2 tp3 = sl*3 if buySignal l1 = line.new ( bar_index, bufferHigh , bar_index + 7, bufferHigh, color = color.green, width = 2) l2 = line.new ( bar_index, bufferLow , bar_index + 7 , bufferLow , color = color.red , width = 2) l3 = line.new (bar_index, bufferHigh + tp1 , bar_index + 10 , bufferHigh+tp1, style=line.style_dotted, color=color.green, width = 1) l4 = line.new (bar_index, bufferHigh + tp2 , bar_index + 10 , bufferHigh+tp2, style=line.style_dotted, color=color.green, width = 1) l5 = line.new (bar_index, bufferHigh + tp3 , bar_index + 10 , bufferHigh+tp3, style=line.style_dotted, color=color.green, width = 1) if shortSignal s1 = line.new ( bar_index, bufferLow , bar_index + 7, bufferLow, color = color.green, width = 2) s2 = line.new ( bar_index, bufferHigh , bar_index + 7, bufferHigh, color = color.red, width = 2) s3 = line.new ( bar_index, bufferLow - tp1, bar_index + 10, bufferLow - tp1, color = color.green,style=line.style_dotted, width = 1) s4 = line.new ( bar_index, bufferLow - tp2, bar_index + 10, bufferLow - tp2, color = color.green,style=line.style_dotted, width = 1) s5 = line.new ( bar_index, bufferLow - tp3, bar_index + 10, bufferLow - tp3, color = color.green,style=line.style_dotted, width = 1) // 新增状态变量:标记是否已触发过信号 var bool hasTriggeredLong = false var bool hasTriggeredShort = false // 获取最近一次信号触发时的关键价格 lastBuyLine = ta.valuewhen(buySignal, bufferHigh, 0) lastStopLossBuy = ta.valuewhen(buySignal, bufferLow, 0) lastShortLine = ta.valuewhen(shortSignal, bufferLow, 0) lastStopLossSell = ta.valuewhen(shortSignal, bufferHigh, 0) longCondition = high >= lastBuyLine longPositionNegated = low <= lastStopLossBuy shortCondition = low <= lastShortLine shortPositionNegated = high >= lastStopLossSell if longPositionNegated pnL = label.new(bar_index,(low- (0.004 * low)), style=label.style_arrowup, color=color.white, text="pNeg", textcolor=color.white) label.delete(pnL) hasTriggeredLong := false // 止损后重置状态,允许新信号 else if shortPositionNegated pnS = label.new(bar_index,(high+ (0.002 * high)), style=label.style_arrowdown, color=color.white, text="pNeg", textcolor=color.white) hasTriggeredShort := false // 止损后重置状态,允许新信号 else if longCondition and not hasTriggeredLong p1 = label.new(bar_index,(low- (0.004 * low)), style=label.style_arrowup, color=color.white, text="BUY", textcolor=color.white) hasTriggeredLong := true // 触发信号后标记为已触发 else if shortCondition and not hasTriggeredShort p2 = label.new(bar_index,(high+ (0.002 * high)), style=label.style_arrowdown, color=color.white, text="SELL", textcolor=color.white) hasTriggeredShort := true // 触发信号后标记为已触发
关键修改说明
- 状态变量控制:新增
hasTriggeredLong和hasTriggeredShort变量,确保信号仅触发一次,直到止损后重置 - 简化价格判断:用
ta.valuewhen()直接获取最近一次信号触发时的入场/止损价格,替代原有的多根K线冗余判断 - 信号触发逻辑:仅当满足突破条件且未触发过信号时,才生成标签并标记状态
内容的提问来源于stack exchange,提问作者Parshuram Gore
相关产品推荐
相关产品推荐

