Pine Script多时间框架策略无报错却无交易执行问题求助
多时间框架趋势跟踪策略无交易执行问题排查
我基于ATR指标与Hull移动均线开发了一款多时间框架(当前时间框架+另外两个时间框架)的趋势跟踪策略脚本。脚本运行无报错,但始终未按设定条件执行任何交易。请帮忙排查代码是否存在问题?
//@version=5 strategy('Multi-Timeframe Trend Following Strategy', overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10, calc_on_every_tick=true) // User Inputs current_tf = input.timeframe('', title='Current Timeframe') primary_tf = input.timeframe('360', title='Primary Timeframe') secondary_tf = input.timeframe('60', title='Secondary Timeframe') exit_tf_options = input.string('Current Timeframe', title='Exit Timeframe', options=['Current Timeframe', 'Primary Timeframe', 'Secondary Timeframe']) atrLength = input.int(21, title='ATR Length') atrMultiplier = input.float(3, title='ATR Multiplier') hullLength = input.int(21, title='Hull MA Length') fractalLength = input.int(2, title='Fractal Length') sensitivity = input.float(0.8, title='Sensitivity [0,1]', minval=0, maxval=1) showSignals = input.bool(true, title='Reveal Long/Short Signals?') showBarColor = input.bool(true, title='Show Bar-Color according to signals?') // Function to calculate the signal logic f_signal_logic(_src) => sf = sensitivity avg = 0. src = sf * _src + (1 - sf) * nz(avg[1], _src) atr = ta.atr(atrLength) up = src - atrMultiplier * atr up1 = nz(up[1], up) up := close[1] > up1 ? math.max(up, up1) : up dn = src + atrMultiplier * atr dn1 = nz(dn[1], dn) dn := close[1] < dn1 ? math.min(dn, dn) : dn trend = 1 trend := nz(trend[1], trend) trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend [trend, up, dn] [trend_cur, up_cur, dn_cur] = request.security(syminfo.tickerid, current_tf, f_signal_logic(hl2)) [trend_primary, up_primary, dn_primary] = request.security(syminfo.tickerid, primary_tf, f_signal_logic(hl2)) [trend_secondary, up_secondary, dn_secondary] = request.security(syminfo.tickerid, secondary_tf, f_signal_logic(hl2)) long_signal_current = trend_cur == 1 and trend_cur[1] == -1 short_signal_current = trend_cur == -1 and trend_cur[1] == 1 long_signal_primary = trend_primary == 1 and trend_primary[1] == -1 short_signal_primary = trend_primary == -1 and trend_primary[1] == 1 long_signal_secondary = trend_secondary == 1 and trend_secondary[1] == -1 short_signal_secondary = trend_secondary == -1 and trend_secondary[1] == 1 // Debugging signals to make sure they are being generated plotshape(series=long_signal_current, location=location.belowbar, color=color.green, style=shape.labelup, text='Buy Current TF') plotshape(series=short_signal_current, location=location.abovebar, color=color.red, style=shape.labeldown, text='Sell Current TF') plotshape(series=long_signal_primary, location=location.belowbar, color=color.blue, style=shape.labelup, text='Buy Primary TF') plotshape(series=short_signal_primary, location=location.abovebar, color=color.orange, style=shape.labeldown, text='Sell Primary TF') plotshape(series=long_signal_secondary, location=location.belowbar, color=color.purple, style=shape.labelup, text='Buy Secondary TF') plotshape(series=short_signal_secondary, location=location.abovebar, color=color.yellow, style=shape.labeldown, text='Sell Secondary TF') longCondition = long_signal_current and long_signal_primary and long_signal_secondary shortCondition = short_signal_current and short_signal_primary and short_signal_secondary // Exit signals based on selected timeframe var bool exit_long_signal = na var bool exit_short_signal = na if exit_tf_options == 'Current Timeframe' exit_long_signal := trend_cur == -1 and trend_cur[1] == 1 exit_short_signal := trend_cur == 1 and trend_cur[1] == -1 else if exit_tf_options == 'Primary Timeframe' exit_long_signal := trend_primary == -1 and trend_primary[1] == 1 exit_short_signal := trend_primary == 1 and trend_primary[1] == -1 else if exit_tf_options == 'Secondary Timeframe' exit_long_signal := trend_secondary == -1 and trend_secondary[1] == 1 exit_short_signal := trend_secondary == 1 and trend_secondary[1] == -1 // Debugging prints var table debug_table = table.new(position.top_right, 1, 10, border_width=1) if barstate.islast table.cell(debug_table, 0, 0, text_color=color.white, bgcolor=color.red, text="Long Condition: " + str.tostring(longCondition)) table.cell(debug_table, 0, 1, text_color=color.white, bgcolor=color.red, text="Short Condition: " + str.tostring(shortCondition)) table.cell(debug_table, 0, 2, text_color=color.white, bgcolor=color.red, text="Exit Long Signal: " + str.tostring(exit_long_signal)) table.cell(debug_table, 0, 3, text_color=color.white, bgcolor=color.red, text="Exit Short Signal: " + str.tostring(exit_short_signal)) // Entry conditions long_condition = longCondition short_condition = shortCondition // Exit conditions exit_long_condition = exit_long_signal exit_short_condition = exit_short_signal // Execute trades if (long_condition) strategy.entry('Long', strategy.long) if (exit_long_condition) strategy.close('Long') if (short_condition) strategy.entry('Short', strategy.short) if (exit_short_condition) strategy.close('Short') // Plotting for visual confirmation plotshape(series=long_condition and showSignals ? low : na, location=location.belowbar, color=color.new(color.green, 0), style=shape.labelup, text='Buy') plotshape(series=short_condition and showSignals ? high : na, location=location.abovebar, color=color.new(color.red, 0), style=shape.labeldown, text='Sell') bgcolor(long_condition and showBarColor ? color.new(color.green, 90) : na) bgcolor(short_condition and showBarColor ? color.new(color.red, 90) : na) // Debugging plots to verify signal generation plot(series=long_signal_current ? 1 : na, color=color.green, title='Long Signal Current TF') plot(series=short_signal_current ? 1 : na, color=color.red, title='Short Signal Current TF') plot(series=long_signal_primary ? 1 : na, color=color.blue, title='Long Signal Primary TF') plot(series=short_signal_primary ? 1 : na, color=color.orange, title='Short Signal Primary TF') plot(series=long_signal_secondary ? 1 : na, color=color.purple, title='Long Signal Secondary TF') plot(series=short_signal_secondary ? 1 : na, color=color.yellow, title='Short Signal Secondary TF')
核心问题排查
1. 信号逻辑函数f_signal_logic存在多处错误
- 未实现Hull移动均线:代码声明了
hullLength参数,但函数完全没有计算Hull MA,直接用hl2做错误的平滑处理,趋势判断逻辑和设计初衷完全不符。 - 平滑变量
avg初始化错误:avg = 0.是局部变量,每次调用函数都会重置,导致src = sf * _src + (1 - sf) * nz(avg[1], _src)等价于src = _src,平滑逻辑完全失效。 - 下行轨道
dn更新逻辑错误:dn := close[1] < dn1 ? math.min(dn, dn) : dn中math.min(dn, dn)等于原值,导致下行轨道永远不会更新,趋势反转判断完全错误。
2. 多时间框架开仓条件过于严苛
longCondition = long_signal_current and long_signal_primary and long_signal_secondary要求三个时间框架同时在同一根K线出现趋势反转信号,这种情况在实盘中几乎不可能发生,直接导致无法触发开仓。
3. 当前时间框架输入配置错误
current_tf = input.timeframe('', title='Current Timeframe')设置为空输入,request.security无法正确识别当前图表时间框架,导致trend_cur的信号数据异常。
修复方案
1. 修正信号逻辑函数,加入Hull MA计算
// Function to calculate the signal logic f_signal_logic(_src) => // 计算Hull移动均线 hull_ma = ta.wma(2 * ta.wma(_src, math.round(hullLength / 2)) - ta.wma(_src, hullLength), math.round(math.sqrt(hullLength))) sf = sensitivity // 使用var声明avg,保留上一根K线的平滑值 var float avg = na avg := na(avg) ? hull_ma : sf * hull_ma + (1 - sf) * avg src = avg atr = ta.atr(atrLength) up = src - atrMultiplier * atr up1 = nz(up[1], up) up := close[1] > up1 ? math.max(up, up1) : up dn = src + atrMultiplier * atr dn1 = nz(dn[1], dn) // 修正下行轨道更新逻辑 dn := close[1] < dn1 ? math.min(dn, dn1) : dn trend = 1 trend := nz(trend[1], trend) trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend [trend, up, dn]
2. 调整开仓条件,降低触发门槛
改为要求三个时间框架趋势方向一致,同时当前时间框架出现反转信号:
// 多头开仓:三个时间框架均为多头趋势,且当前时间框架出现反转信号 longCondition = trend_cur == 1 and trend_primary == 1 and trend_secondary == 1 and long_signal_current // 空头开仓:三个时间框架均为空头趋势,且当前时间框架出现反转信号 shortCondition = trend_cur == -1 and trend_primary == -1 and trend_secondary == -1 and short_signal_current
3. 修正当前时间框架输入
默认使用图表当前周期,避免空输入导致的异常:
current_tf = input.timeframe(timeframe.period, title='Current Timeframe')
额外调试建议
- 观察
plotshape绘制的单时间框架信号是否正常生成,确认每个时间框架的趋势逻辑修复生效。 - 查看右上角调试表格的
Long Condition和Short Condition值,确认开仓条件是否能被触发。
内容的提问来源于stack exchange,提问作者Olivia Moore
相关产品推荐
相关产品推荐

