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

Pine Script三条件交易策略无执行问题求助

Pine Script策略协同条件问题解决

问题描述

我编写了如下Pine Script策略,预期实现以下逻辑:

  • 条件1:处于指定交易时段内
  • 条件2:MA(移动平均线)交叉
  • 条件3:仅当条件2触发后的x根K线内,RSI穿越指定区间时才执行交易;若RSI在x根K线后穿越,或在条件2触发前穿越,信号均无效。

但目前无法让所有条件协同生效:要么未等待条件3就执行交易,要么完全无交易执行。已多日寻找解决方案,恳请帮助。

原代码:

//@version=5
strategy("MS + RSI cross", overlay=true)

// User Inputs
// Group SMA
sma_group = "SMA"
sma1_length = input.int(10, title="SMA 1 Length", group=sma_group)
sma2_length = input.int(35, title="SMA 2 Length", group=sma_group)

// Group RSI
rsi_group = "RSI"
rsi_length = input.int(8, title="RSI Length", group=rsi_group)
rsi_source = input.source(close, title="RSI Source", group=rsi_group)
rsi_upper_band = input.float(55, title="RSI Upper Band", group=rsi_group)
rsi_lower_band = input.float(45, title="RSI Lower Band", group=rsi_group)
rsi_confirmation_window = input.int(3, title="RSI Confirmation Window", group=rsi_group)

// Group Trading Hours
trading_hours_group = "TRADING TIME"
start_trading_hour = input.int(9, title="Start Trading Hour", group=trading_hours_group)
stop_trading_hour = input.int(21, title="Stop Trading Hour", group=trading_hours_group)

// Group SL/TP
sl_tp_group = "SL & TP"
sl_points = input.int(300, title="SL (points)", group=sl_tp_group)
tp_points = input.int(450, title="TP (points)", group=sl_tp_group)

// Calculating moving averages
sma1 = ta.sma(close, sma1_length)
sma2 = ta.sma(close, sma2_length)

// Calculating RSI
rsi_value = ta.rsi(rsi_source, rsi_length)

// Trading Conditions
in_trading_hours = hour >= start_trading_hour and hour <= stop_trading_hour

// Long conditions
long_sma_cross = ta.crossover(sma1, sma2) and in_trading_hours
long_rsi_cross = false
bars_since_long_sma_cross = ta.barssince(long_sma_cross)
if bars_since_long_sma_cross > 0 and bars_since_long_sma_cross <= rsi_confirmation_window
long_rsi_cross := ta.crossover(rsi_value, rsi_upper_band)

// Visualize the rsi cross for debugging
bgcolor(ta.crossover(rsi_value, rsi_upper_band) ? color.new(#37b027, 81): na)

// Short conditions
short_sma_cross = ta.crossunder(sma1, sma2) and in_trading_hours
short_rsi_cross = false
bars_since_short_sma_cross = ta.barssince(short_sma_cross)
if bars_since_short_sma_cross > 0 and bars_since_short_sma_cross <= rsi_confirmation_window
    short_rsi_cross := ta.crossunder(rsi_value, rsi_lower_band)

// Visualize the rsi cross for debugging    
bgcolor(ta.crossunder(rsi_value, rsi_lower_band) ? color.new(#c74949, 76): na)

// Entry and Exit Logic
if (long_sma_cross and long_rsi_cross)
    strategy.entry("Long", strategy.long)
    strategy.exit("Exit Long", "Long", stop=close - sl_points  * syminfo.mintick, limit=close + tp_points * syminfo.mintick)

if (short_sma_cross and short_rsi_cross)
    strategy.entry("Short", strategy.short)
    strategy.exit("Exit Short", "Short", stop=close + sl_points * syminfo.mintick, limit=close - tp_points * syminfo.mintick)

// Plotting
plot(sma1, color=color.rgb(243, 135, 33), title="SMA 1")
plot(sma2, color=color.rgb(235, 213, 213), title="SMA 2")
plotshape(long_sma_cross and long_rsi_cross, style=shape.labelup, location=location.belowbar, color=color.green, size=size.small, title="Long Signal")
plotshape(short_sma_cross and short_rsi_cross, style=shape.labeldown, location=location.abovebar, color=color.red, size=size.small, title="Short Signal")

问题根源

原代码核心错误在于入场条件逻辑冲突:要求long_sma_cross(MA交叉)和long_rsi_cross(RSI穿越)在同一根K线触发,但实际需求是MA交叉后,RSI在后续x根K线内穿越,两个条件不可能同时满足。此外,long_rsi_cross仅判断当前K线是否满足RSI穿越,没有持续记录窗口内是否出现过有效信号。

修改后的完整代码

//@version=5
strategy("MS + RSI cross", overlay=true)

// User Inputs
// Group SMA
sma_group = "SMA"
sma1_length = input.int(10, title="SMA 1 Length", group=sma_group)
sma2_length = input.int(35, title="SMA 2 Length", group=sma_group)

// Group RSI
rsi_group = "RSI"
rsi_length = input.int(8, title="RSI Length", group=rsi_group)
rsi_source = input.source(close, title="RSI Source", group=rsi_group)
rsi_upper_band = input.float(55, title="RSI Upper Band", group=rsi_group)
rsi_lower_band = input.float(45, title="RSI Lower Band", group=rsi_group)
rsi_confirmation_window = input.int(3, title="RSI Confirmation Window", group=rsi_group)

// Group Trading Hours
trading_hours_group = "TRADING TIME"
start_trading_hour = input.int(9, title="Start Trading Hour", group=trading_hours_group)
stop_trading_hour = input.int(21, title="Stop Trading Hour", group=trading_hours_group)

// Group SL/TP
sl_tp_group = "SL & TP"
sl_points = input.int(300, title="SL (points)", group=sl_tp_group)
tp_points = input.int(450, title="TP (points)", group=sl_tp_group)

// Calculating moving averages
sma1 = ta.sma(close, sma1_length)
sma2 = ta.sma(close, sma2_length)

// Calculating RSI
rsi_value = ta.rsi(rsi_source, rsi_length)

// Trading Conditions
in_trading_hours = hour >= start_trading_hour and hour <= stop_trading_hour

// Long conditions
long_sma_cross = ta.crossover(sma1, sma2) and in_trading_hours
// 持续记录MA交叉窗口内是否出现过RSI上穿信号
var bool long_rsi_confirm = false
bars_since_long_sma_cross = ta.barssince(long_sma_cross)

// 重置确认标记:新MA交叉触发或超出窗口时重置
if long_sma_cross or bars_since_long_sma_cross > rsi_confirmation_window
    long_rsi_confirm := false
// 窗口内检测到RSI上穿,标记确认
if bars_since_long_sma_cross >= 0 and bars_since_long_sma_cross <= rsi_confirmation_window
    if ta.crossover(rsi_value, rsi_upper_band)
        long_rsi_confirm := true

// Short conditions
short_sma_cross = ta.crossunder(sma1, sma2) and in_trading_hours
// 持续记录MA交叉窗口内是否出现过RSI下穿信号
var bool short_rsi_confirm = false
bars_since_short_sma_cross = ta.barssince(short_sma_cross)

// 重置确认标记:新MA交叉触发或超出窗口时重置
if short_sma_cross or bars_since_short_sma_cross > rsi_confirmation_window
    short_rsi_confirm := false
// 窗口内检测到RSI下穿,标记确认
if bars_since_short_sma_cross >= 0 and bars_since_short_sma_cross <= rsi_confirmation_window
    if ta.crossunder(rsi_value, rsi_lower_band)
        short_rsi_confirm := true

// Entry and Exit Logic
// 确认标记为真且在交易时段内时入场
if long_rsi_confirm and in_trading_hours
    strategy.entry("Long", strategy.long)
    strategy.exit("Exit Long", "Long", stop=close - sl_points * syminfo.mintick, limit=close + tp_points * syminfo.mintick)

if short_rsi_confirm and in_trading_hours
    strategy.entry("Short", strategy.short)
    strategy.exit("Exit Short", "Short", stop=close + sl_points * syminfo.mintick, limit=close - tp_points * syminfo.mintick)

// Plotting
plot(sma1, color=color.rgb(243, 135, 33), title="SMA 1")
plot(sma2, color=color.rgb(235, 213, 213), title="SMA 2")
plotshape(long_rsi_confirm, style=shape.labelup, location=location.belowbar, color=color.green, size=size.small, title="Long Signal")
plotshape(short_rsi_confirm, style=shape.labeldown, location=location.abovebar, color=color.red, size=size.small, title="Short Signal")

// Debug visualization
bgcolor(ta.crossover(rsi_value, rsi_upper_band) ? color.new(#37b027, 81): na)
bgcolor(ta.crossunder(rsi_value, rsi_lower_band) ? color.new(#c74949, 76): na)

关键修改点说明

  1. 新增状态标记变量:用var bool定义long_rsi_confirm和short_rsi_confirm,持续记录MA交叉窗口内是否出现过有效RSI穿越信号。
  2. 重置逻辑:新MA交叉触发或超出确认窗口时,重置状态标记,避免旧信号干扰后续交易。
  3. 入场条件调整:将入场条件改为判断状态标记为真,而非要求MA交叉和RSI穿越在同一K线,符合“MA交叉后x根K线内RSI穿越”的需求。
  4. 交易时段校验:入场时再次校验in_trading_hours,确保交易仅在指定时段内执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:20:57