将Sushi Trend指标转为TradingView策略无入场信号问题排查
Sushi Trend 指标转策略无信号问题解决
问题说明
无编程基础,尝试将TradingView上的Sushi Trend [HG]指标转换为策略,设定规则:
- 出现Bull信号时做多,止损设在趋势线,盈利因子为1.5
- 出现Bear信号时做空,止损设在趋势线,盈利因子为1.5
- 持仓时趋势反转则平仓
自行编写的v4版本策略代码可正常编译并加载到图表,但策略测试器无有效入场信号,寻求问题解决。
原始指标代码(v5)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © HoanGhetti //@version=5 indicator("Sushi Trend [HG]", overlay = true) factor = input.int(defval = 5, title = 'Engulfing Factor') bullC = input.color(defval = color.green, title = 'Bull') bearC = input.color(defval = color.red, title = 'Bear') var stMatrix = matrix.new<float>(4, factor) setMinMax(float value, int row, bool set = false) => bool result = na for i = 0 to factor - 1 if set int j = factor + i stMatrix.set(0, i, high[i]) stMatrix.set(1, i, low[i]) stMatrix.set(2, i, high[j]) stMatrix.set(3, i, low[j]) if value == stMatrix.get(row, i) result := true break result setMinMax(na, na, true) bool max = setMinMax(stMatrix.max(), 0) bool min = setMinMax(stMatrix.min(), 1) bool valid = min and max and (stMatrix.min() == stMatrix.get(1, factor - 1) or stMatrix.max() == stMatrix.get(0, factor - 1)) bool sushi = valid and ta.barssince(valid[1]) >= factor and barstate.isconfirmed float lastMax = fixnan(ta.change(sushi) and sushi and max ? stMatrix.max() : na) float lastMin = fixnan(ta.change(sushi) and sushi ? stMatrix.min() : na) var int direction = na if ta.crossover(close, lastMax) direction := 1 if ta.crossunder(close, lastMin) direction := 0 float sushiTrend = switch direction 1 => lastMin 0 => lastMax color dirColor = direction == 1 ? bullC : bearC stPlot = plot(sushiTrend, title = 'Sushi Trend', color = not ta.change(direction) ? dirColor : na, linewidth = 3, style = plot.style_linebr) hlPlot = plot(hl2, display = display.none, editable = false) fill(stPlot, hlPlot, color.new(dirColor, 90)) plotshape(ta.change(direction) and direction == 1 ? sushiTrend : na, title = 'Bull', style = shape.labelup, color = dirColor, location = location.absolute, text = 'Bull', textcolor = color.white, size = size.tiny) plotshape(ta.change(direction) and direction == 0 ? sushiTrend : na, title = 'Bear', style = shape.labeldown, color = dirColor, location = location.absolute, text = 'Bear', textcolor = color.white, size = size.tiny)
自行编写的策略代码(v4)
//@version=4 strategy("Sushi Trend Strategy", overlay = true) factor = input(5, title="Engulfing Factor") bullC = color.new(color.green, 90) bearC = color.new(color.red, 90) var float lastMax = na var float lastMin = na var int direction = na var int barsSinceValid = 0 var bool directionChanged = false setMinMax(value, rowHigh, rowLow, set) => var bool result = na for i = 0 to factor - 1 if set j = factor + i high_i = security(syminfo.tickerid, "D", value[i]) low_i = security(syminfo.tickerid, "D", value[j]) result := true result setMinMax(high, 0, factor, true) max = setMinMax(high, 0, factor, false) min = setMinMax(low, 1, factor, false) valid = min and max and (min == low[factor - 1] or max == high[factor - 1]) sushi = valid and barsSinceValid >= factor lastMax := na(lastMax) ? (directionChanged and sushi ? high : na) : high lastMin := na(lastMin) ? (directionChanged and sushi ? low : na) : low if crossover(close, lastMax) direction := 1 directionChanged := true if crossunder(close, lastMin) direction := 0 directionChanged := true sushiTrend = direction == 1 ? lastMin : direction == 0 ? lastMax : na dirColor = direction == 1 ? bullC : bearC plot(sushiTrend, title="Sushi Trend", color=dirColor, linewidth=3) // RSI calculation (You can adjust the parameters accordingly) rsiLength = input(14, title="RSI Length") rsiValue = rsi(close, rsiLength) // Trading conditions longCondition = crossover(rsiValue, 50) and direction == 1 shortCondition = crossunder(rsiValue, 50) and direction == 0 strategy.entry("Long", strategy.long, when=longCondition) strategy.entry("Short", strategy.short, when=shortCondition) // Exit conditions (You can adjust the stop loss and take profit logic accordingly) stopLossLevel = lowest(low, 5) // Using the lowest low of the last 5 bars as a simple example, adjust as needed takeProfitLevel = close + 1.5 * (close - stopLossLevel) strategy.exit("Take Profit/Stop Loss", from_entry="Long", loss=stopLossLevel, profit=takeProfitLevel) // Reverse position if trend changes reverseCondition = directionChanged and ((direction == 0 and crossover(close, sushiTrend)) or (direction == 1 and crossunder(close, sushiTrend))) strategy.close("Long", when=reverseCondition) strategy.close("Short", when=reverseCondition) // Update barsSinceValid barsSinceValid := sushi ? 0 : barsSinceValid + 1 directionChanged := false // Debugging Plots plot(barsSinceValid, title="Bars Since Valid") plot(directionChanged ? 1 : na, color=color.red, style=plot.style_histogram, title="Direction Changed")
问题根源分析
- 核心逻辑偏离:自定义的
setMinMax函数完全违背原指标的矩阵存储高低点逻辑,错误引入security调用日线数据,导致max、min、valid等关键变量无法正确计算,这是无信号的核心原因。 - 变量赋值错误:
lastMax、lastMin的更新逻辑完全不符合原指标的触发条件,无法正确捕捉趋势转折点。 - 入场条件错误:额外加入RSI交叉50的条件,违背了最初设定的“Bull/Bear信号触发入场”的规则。
- 止损止盈逻辑错误:未使用原指标的趋势线作为止损,而是用最近5根K线低点,不符合策略规则。
- 状态管理混乱:
directionChanged的重置时机错误,导致趋势反转信号无法正确识别。
修正后的策略代码(v4)
//@version=4 strategy("Sushi Trend Strategy [Fixed]", overlay=true, default_qty_type=strategy.cash, default_qty_value=10000, commission_type=strategy.commission.percent, commission_value=0.1) // 复制原指标核心参数 factor = input(5, title="Engulfing Factor") bullC = color.green bearC = color.red // 模拟v5的矩阵逻辑:用数组替代矩阵存储高低点 var float[] highArr1 = array.new_float(factor) var float[] lowArr1 = array.new_float(factor) var float[] highArr2 = array.new_float(factor) var float[] lowArr2 = array.new_float(factor) // 实现原指标的setMinMax逻辑 setMinMax(set) => if set // 填充数组:对应原矩阵的4行数据 for i = 0 to factor - 1 int j = factor + i array.set(highArr1, i, high[i]) array.set(lowArr1, i, low[i]) array.set(highArr2, i, high[j]) array.set(lowArr2, i, low[j]) // 执行数据填充 setMinMax(true) // 计算原指标的max/min/valid/sushi信号 float maxVal = math.max(array.max(highArr1), array.max(highArr2)) float minVal = math.min(array.min(lowArr1), array.min(lowArr2)) bool maxCheck = array.includes(highArr1, maxVal) bool minCheck = array.includes(lowArr1, minVal) bool valid = minCheck and maxCheck and (minVal == array.get(lowArr1, factor-1) or maxVal == array.get(highArr1, factor-1)) bool sushi = valid and barssince(valid[1]) >= factor and barstate.isconfirmed // 更新lastMax和lastMin:对应原指标逻辑 float lastMax = na float lastMin = na lastMax := change(sushi) and sushi and maxCheck ? maxVal : lastMax[1] lastMin := change(sushi) and sushi ? minVal : lastMin[1] // 确定趋势方向 var int direction = na if crossover(close, lastMax) direction := 1 if crossunder(close, lastMin) direction := 0 // 计算趋势线 float sushiTrend = direction == 1 ? lastMin : direction == 0 ? lastMax : na // 绘制趋势线(和原指标一致) plot(sushiTrend, title="Sushi Trend", color=not change(direction) ? (direction == 1 ? bullC : bearC) : na, linewidth=3, style=plot.style_linebr) hlPlot = plot(hl2, display=display.none) fill(plot1=sushiTrend, plot2=hlPlot, color=color.new(direction == 1 ? bullC : bearC, 90)) // 识别Bull/Bear信号(对应原指标的plotshape触发条件) bool bullSignal = change(direction) and direction == 1 bool bearSignal = change(direction) and direction == 0 // 绘制信号标记 plotshape(bullSignal ? sushiTrend : na, title="Bull", style=shape.labelup, color=bullC, location=location.absolute, text="Bull", textcolor=color.white, size=size.tiny) plotshape(bearSignal ? sushiTrend : na, title="Bear", style=shape.labeldown, color=bearC, location=location.absolute, text="Bear", textcolor=color.white, size=size.tiny) // 交易逻辑:严格遵循设定规则 // 入场条件:Bull信号做多,Bear信号做空 strategy.entry("Long", strategy.long, when=bullSignal) strategy.entry("Short", strategy.short, when=bearSignal) // 止损止盈计算:止损在趋势线,盈利因子1.5 if strategy.position_size > 0 longStop = sushiTrend longProfit = close + 1.5 * (close - longStop) strategy.exit("Long Exit", "Long", loss=longStop, profit=longProfit) if strategy.position_size < 0 shortStop = sushiTrend shortProfit = close - 1.5 * (shortStop - close) strategy.exit("Short Exit", "Short", loss=shortStop, profit=shortProfit) // 趋势反转平仓 bool reverseLong = change(direction) and direction == 0 bool reverseShort = change(direction) and direction == 1 strategy.close("Long", when=reverseLong) strategy.close("Short", when=reverseShort)
修正说明
- 还原核心逻辑:用数组替代v5的矩阵,完整复刻原指标的高低点存储、信号判断逻辑,确保Bull/Bear信号和原指标一致。
- 修正入场条件:直接用原指标的Bull/Bear信号作为入场触发条件,去掉多余的RSI判断,符合初始规则。
- 正确设置止损止盈:以趋势线
sushiTrend作为止损位,按照1.5倍盈利因子计算止盈价格。 - 完善反转平仓:当趋势方向改变时,直接平掉相反方向的持仓,符合规则要求。
- 保留原指标可视化:还原原指标的趋势线、填充色和信号标记,方便对照验证。
内容的提问来源于stack exchange,提问作者helioendo
相关产品推荐
相关产品推荐

