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

将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")

问题根源分析

  1. 核心逻辑偏离:自定义的setMinMax函数完全违背原指标的矩阵存储高低点逻辑,错误引入security调用日线数据,导致max、min、valid等关键变量无法正确计算,这是无信号的核心原因。
  2. 变量赋值错误:lastMax、lastMin的更新逻辑完全不符合原指标的触发条件,无法正确捕捉趋势转折点。
  3. 入场条件错误:额外加入RSI交叉50的条件,违背了最初设定的“Bull/Bear信号触发入场”的规则。
  4. 止损止盈逻辑错误:未使用原指标的趋势线作为止损,而是用最近5根K线低点,不符合策略规则。
  5. 状态管理混乱: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)

修正说明

  1. 还原核心逻辑:用数组替代v5的矩阵,完整复刻原指标的高低点存储、信号判断逻辑,确保Bull/Bear信号和原指标一致。
  2. 修正入场条件:直接用原指标的Bull/Bear信号作为入场触发条件,去掉多余的RSI判断,符合初始规则。
  3. 正确设置止损止盈:以趋势线sushiTrend作为止损位,按照1.5倍盈利因子计算止盈价格。
  4. 完善反转平仓:当趋势方向改变时,直接平掉相反方向的持仓,符合规则要求。
  5. 保留原指标可视化:还原原指标的趋势线、填充色和信号标记,方便对照验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:24:58