多时间框架随机相对强弱指标交叉策略是一个基于Stochastic RSI(随机相对强弱指标)的复合交易系统,该策略采用5分钟和15分钟两个时间周期的数据进行交易信号生成和确认。这是一个完整的交易系统,包含明确的入场条件、止损控制以及分阶段获利方案。该策略特别关注市场的超买/超卖状态,通过捕捉价格动量的转变时机实现盈利。
该策略在5分钟图表上操作,但会参考15分钟图表的数据来确认交易信号,体现了多时间框架分析的深度。它对多头和空头交易采用了不同的参数设置,暗示其在设计上偏向适应整体看涨的市场环境。
该策略的核心原理基于Stochastic RSI指标的交叉信号,结合了多时间框架确认机制来过滤低质量信号。具体工作流程如下:
初始触发信号(5分钟时间框架):
高级确认(15分钟时间框架):
重复信号过滤:
仓位管理:
两阶段获利机制:
多时间框架确认机制:
超买/超卖条件的精确定位:
分阶段止盈策略:
自适应偏好设置:
完整的风险管理:
重复信号过滤:
参数敏感性:
止损点位可能较宽:
市场条件依赖性:
对多头偏向:
15分钟确认延迟:
动态止盈机制:
市场状态自适应:
多指标协同确认:
风险敞口优化:
多时间框架层级扩展:
交易时段过滤:
多时间框架随机相对强弱指标交叉策略是一个结构完善的交易系统,通过多时间框架分析和严格的信号确认流程提高交易质量。该策略的核心优势在于其全面的入场条件和风险管理系统,特别是两阶段止盈机制允许在保持部分头寸追踪趋势的同时锁定利润。
然而,该策略的效果高度依赖于参数设置和市场条件。在震荡市场中可能表现良好,但在强趋势或高波动环境下可能需要调整。建议交易者通过历史回测优化参数,并考虑添加市场状态检测和动态止盈机制等功能来增强其适应性。
该策略最适合具有编程知识的中级到高级交易者,他们能够理解并定制这些复杂的交易规则。通过适当的参数调整和风险管理,这个系统可以成为日内和短期交易者工具箱中的有价值组成部分,特别是那些专注于捕捉市场动量变化的交易者。
/*backtest
start: 2024-06-05 00:00:00
end: 2025-06-04 00:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"DOGE_USDT"}]
*/
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Archertoria
//@version=6
strategy("System 0530 - Stoch RSI Strategy v13 SL-Priority TP-Reversal",
overlay=true,
default_qty_type=strategy.percent_of_equity,
default_qty_value=100,
calc_on_order_fills=false,
process_orders_on_close=true,
margin_short=50)
// --- Original Indicator Input Parameters ---
g_stoch = "Stochastic RSI Parameters"
rsi_len = input.int(14, "RSI Period", minval=1, group=g_stoch)
stoch_rsi_len = input.int(14, "Stochastic of RSI Period (K Period for Stoch)", minval=1, group=g_stoch)
stoch_k_smooth = input.int(3, "Stochastic %K Smoothing (D Period for Stoch)", minval=1, group=g_stoch)
stoch_d_smooth = input.int(3, "Stochastic %D Smoothing (Smoothing for final D)", minval=1, group=g_stoch)
g_signal = "Signal Trigger and Confirmation Parameters"
stoch_5min_k_long_trigger = input.float(40.0, "5-min Stoch K Long Trigger Level (K must be ≤ this value)", minval=0, maxval=100, step=0.1, group=g_signal, tooltip="On the 5-minute chart, when the K line crosses above the D line, the K value at that time must be less than or equal to this setting to initiate a long signal wait.")
stoch_5min_k_short_trigger = input.float(70.0, "5-min Stoch K Short Trigger Level (K must be ≥ this value)", minval=0, maxval=100, step=0.1, group=g_signal, tooltip="On the 5-minute chart, when the K line crosses below the D line, the K value at that time must be greater than or equal to this setting to initiate a short signal wait.")
stoch_15min_long_entry_level = input.int(50, "15-min Stoch K Long Confirmation Threshold (K must be below this value)", minval=0, maxval=100, group=g_signal, tooltip="On the 15-minute chart, for final long confirmation, the 15-minute K line value must be below this setting.")
stoch_15min_short_entry_level = input.int(70, "15-min Stoch K Short Confirmation Threshold (K must be above this value)", minval=0, maxval=100, group=g_signal, tooltip="On the 15-minute chart, for final short confirmation, the 15-minute K line value must be above this setting.")
wait_window_5min_bars = input.int(7, "Number of 5-min bars to wait for 15-min signal", minval=1, group=g_signal, tooltip="After a 5-minute signal is issued, wait for 15-minute signal confirmation within the next N 5-minute bars.")
g_repeat_filter = "Duplicate Signal Filtering Settings"
use_signal_cooldown_filter = input.bool(true, title="Enable Duplicate Signal Filter", group=g_repeat_filter, tooltip="Filters out duplicate signals in the same direction within a short period.")
min_bars_between_signals = input.int(12, title="Minimum Bars Between Same-Direction Signals", minval=1, group=g_repeat_filter, tooltip="After a signal is issued, at least this many bars must pass before another signal in the same direction can be issued.")
// --- Take Profit Parameters ---
g_tp_params = "Take Profit Parameters"
extreme_long_tp_level = input.float(95.0, "Extreme Long TP Level (Stoch K >)", minval=50, maxval=100, step=0.1, group=g_tp_params, tooltip="Direct TP for longs if 5-min OR 15-min Stoch K exceeds this.")
extreme_short_tp_level = input.float(5.0, "Extreme Short TP Level (Stoch K <)", minval=0, maxval=50, step=0.1, group=g_tp_params, tooltip="Direct TP for shorts if 5-min OR 15-min Stoch K is below this.")
// --- Strategy Specific Input Parameters ---
g_strategy = "Strategy Parameters"
leverage_multiplier = input.float(1.0, "Leverage Multiplier (Affects theoretical position size only)", minval=1.0, step=0.1, group=g_strategy, tooltip="Note: TradingView strategies do not directly simulate margin account liquidation. This leverage is used to calculate theoretical position size. Actual leverage effects must be realized with a broker that supports leverage.")
// --- Function: Calculate Stochastic RSI ---
getStochasticRSI(src, rsiLen, stochLen, kSmooth, dSmooth) =>
rsi_val = ta.rsi(src, rsiLen)
stoch_rsi_k_raw = ta.stoch(rsi_val, rsi_val, rsi_val, stochLen) // Stoch of RSI
stoch_rsi_k = ta.sma(stoch_rsi_k_raw, kSmooth)
stoch_rsi_d = ta.sma(stoch_rsi_k, dSmooth)
[stoch_rsi_k, stoch_rsi_d]
// --- Helper Function to get only K-series for Stochastic RSI (RE-ADDED for 15-min prev K) ---
getStochKSeriesOnly(src, rsiLen, stochLen, kSmooth, dSmooth) =>
rsi_val = ta.rsi(src, rsiLen)
stoch_rsi_k_raw = ta.stoch(rsi_val, rsi_val, rsi_val, stochLen)
stoch_rsi_k = ta.sma(stoch_rsi_k_raw, kSmooth)
stoch_rsi_k // Return only the K series
// --- Time Series Data Fetching and Stochastic RSI Calculation ---
[stoch_k_15min_val, stoch_d_15min_val] = request.security(syminfo.tickerid, "15", getStochasticRSI(close, rsi_len, stoch_rsi_len, stoch_k_smooth, stoch_d_smooth), lookahead=barmerge.lookahead_off)
// RE-ADDED: K value of the PREVIOUS 15-minute bar's Stochastic RSI
stoch_k_15min_prev_tf_bar = request.security(syminfo.tickerid, "15", nz(getStochKSeriesOnly(close, rsi_len, stoch_rsi_len, stoch_k_smooth, stoch_d_smooth)[1]), lookahead=barmerge.lookahead_off)
[stoch_k_5min_val, stoch_d_5min_val] = getStochasticRSI(close, rsi_len, stoch_rsi_len, stoch_k_smooth, stoch_d_smooth)
// --- Signal Logic State Variables ---
var bool waiting_for_15m_long_confirm = false
var bool waiting_for_15m_short_confirm = false
var int bars_elapsed_in_wait_state = 0
var int last_long_signal_bar_idx = -min_bars_between_signals
var int last_short_signal_bar_idx = -min_bars_between_signals
// --- Variables to store SL reference points from ENTRY bar ---
var float entry_bar_low_for_sl = na
var float entry_bar_high_for_sl = na
// --- Take Profit Logic State Variables ---
var bool first_tp_long_taken = false
var bool first_tp_short_taken = false
// RE-ADDED: State variables for pending TP confirmation on 15-min reversal
var bool pending_long_tp_on_15m_reversal = false
var bool pending_short_tp_on_15m_reversal = false
// --- Detect 5-minute Stochastic RSI crossover events for ENTRY ---
bool stoch_5min_crossed_up_prev_bar = ta.crossover(stoch_k_5min_val[1], stoch_d_5min_val[1])
bool stoch_5min_crossed_down_prev_bar = ta.crossunder(stoch_k_5min_val[1], stoch_d_5min_val[1])
bool condition_5min_k_level_for_long_trigger = stoch_k_5min_val[1] <= stoch_5min_k_long_trigger
bool condition_5min_k_level_for_short_trigger = stoch_k_5min_val[1] >= stoch_5min_k_short_trigger
// --- Specific 5-minute Stochastic RSI crossover for Take Profit (current bar) ---
bool stoch_5min_k_cross_under_d_tp = ta.crossunder(stoch_k_5min_val, stoch_d_5min_val) // For Long TP trigger
bool stoch_5min_k_cross_over_d_tp = ta.crossover(stoch_k_5min_val, stoch_d_5min_val) // For Short TP trigger
// --- RE-ADDED: 15-minute Reversal Confirmation for Take Profit ---
bool confirm_15m_reversal_for_long_tp = stoch_k_15min_val < stoch_k_15min_prev_tf_bar
bool confirm_15m_reversal_for_short_tp = stoch_k_15min_val > stoch_k_15min_prev_tf_bar
// --- Manage waiting state and tolerance period for ENTRY ---
if (strategy.position_size == 0)
if (stoch_5min_crossed_up_prev_bar and condition_5min_k_level_for_long_trigger)
can_trigger_new_long = not use_signal_cooldown_filter or (bar_index - last_long_signal_bar_idx >= min_bars_between_signals)
if (can_trigger_new_long)
waiting_for_15m_long_confirm := true
waiting_for_15m_short_confirm := false
bars_elapsed_in_wait_state := 1
else if (stoch_5min_crossed_down_prev_bar and condition_5min_k_level_for_short_trigger)
can_trigger_new_short = not use_signal_cooldown_filter or (bar_index - last_short_signal_bar_idx >= min_bars_between_signals)
if (can_trigger_new_short)
waiting_for_15m_short_confirm := true
waiting_for_15m_long_confirm := false
bars_elapsed_in_wait_state := 1
else if (waiting_for_15m_long_confirm or waiting_for_15m_short_confirm)
bars_elapsed_in_wait_state += 1
if (bars_elapsed_in_wait_state > wait_window_5min_bars)
waiting_for_15m_long_confirm := false
waiting_for_15m_short_confirm := false
bars_elapsed_in_wait_state := 0
else
waiting_for_15m_long_confirm := false
waiting_for_15m_short_confirm := false
bars_elapsed_in_wait_state := 0
// --- 15-minute Stochastic RSI confirmation conditions for ENTRY (Strict Crossover) ---
bool confirm_15min_long_stoch_kd_cond = stoch_k_15min_val > stoch_d_15min_val // K must be strictly greater than D
bool confirm_15min_short_stoch_kd_cond = stoch_k_15min_val < stoch_d_15min_val // K must be strictly less than D
bool filter_15min_stoch_level_long = stoch_k_15min_val < stoch_15min_long_entry_level
bool filter_15min_stoch_level_short = stoch_k_15min_val > stoch_15min_short_entry_level
// --- Main Signal Determination (for strategy logic) ---
entry_long_signal = false
entry_short_signal = false
if (strategy.position_size == 0)
if (waiting_for_15m_long_confirm and bars_elapsed_in_wait_state <= wait_window_5min_bars)
if (confirm_15min_long_stoch_kd_cond and filter_15min_stoch_level_long)
can_confirm_new_long = not use_signal_cooldown_filter or (bar_index - last_long_signal_bar_idx >= min_bars_between_signals)
if (can_confirm_new_long)
entry_long_signal := true
if (waiting_for_15m_short_confirm and bars_elapsed_in_wait_state <= wait_window_5min_bars)
if (confirm_15min_short_stoch_kd_cond and filter_15min_stoch_level_short)
can_confirm_new_short = not use_signal_cooldown_filter or (bar_index - last_short_signal_bar_idx >= min_bars_between_signals)
if (can_confirm_new_short)
entry_short_signal := true
// --- Strategy Execution Logic ---
// Reset SL ref and TP flags if position just closed
if (strategy.position_size == 0 and strategy.position_size[1] != 0)
first_tp_long_taken := false
first_tp_short_taken := false
entry_bar_low_for_sl := na
entry_bar_high_for_sl := na
pending_long_tp_on_15m_reversal := false // Reset pending TP flag
pending_short_tp_on_15m_reversal := false // Reset pending TP flag
if (entry_long_signal)
strategy.entry("LE", strategy.long, comment="Long Entry")
last_long_signal_bar_idx := bar_index
waiting_for_15m_long_confirm := false
bars_elapsed_in_wait_state := 0
first_tp_long_taken := false
entry_bar_low_for_sl := low
entry_bar_high_for_sl := na
pending_long_tp_on_15m_reversal := false // Reset for new trade
pending_short_tp_on_15m_reversal := false
if (entry_short_signal)
strategy.entry("SE", strategy.short, comment="Short Entry")
last_short_signal_bar_idx := bar_index
waiting_for_15m_short_confirm := false
bars_elapsed_in_wait_state := 0
first_tp_short_taken := false
entry_bar_high_for_sl := high
entry_bar_low_for_sl := na
pending_short_tp_on_15m_reversal := false // Reset for new trade
pending_long_tp_on_15m_reversal := false
// --- Stop Loss Logic (PRIORITY 1) ---
// Check and execute SL first. If SL triggers, position size becomes 0, preventing TP logic below from executing on the same bar.
bool sl_triggered_this_bar = false
if (strategy.position_size > 0) // If in a long trade
if (not na(entry_bar_low_for_sl) and close < entry_bar_low_for_sl)
strategy.close(id="LE", comment="SL Long")
sl_triggered_this_bar := true
pending_long_tp_on_15m_reversal := false // Ensure pending TP is cancelled if SL hits
if (strategy.position_size < 0) // If in a short trade
if (not na(entry_bar_high_for_sl) and close > entry_bar_high_for_sl)
strategy.close(id="SE", comment="SL Short")
sl_triggered_this_bar := true
pending_short_tp_on_15m_reversal := false // Ensure pending TP is cancelled if SL hits
// --- Take Profit Logic (PRIORITY 2 - only if SL did not trigger on this bar) ---
if (not sl_triggered_this_bar) // Only proceed with TP if SL hasn't already closed the position on this bar
if (strategy.position_size > 0) // --- LONG TP LOGIC ---
extreme_long_tp_condition = stoch_k_5min_val > extreme_long_tp_level or stoch_k_15min_val > extreme_long_tp_level
if (extreme_long_tp_condition)
if (not first_tp_long_taken)
strategy.close(id="LE", comment="TP1 Long", qty_percent=50)
first_tp_long_taken := true
else
strategy.close(id="LE", comment="TP2 Long")
pending_long_tp_on_15m_reversal := false // Reset pending state as this TP takes precedence
else
// Conditional TP logic (5-min trigger + 15-min reversal)
if (stoch_5min_k_cross_under_d_tp and not pending_long_tp_on_15m_reversal) // Set pending state
pending_long_tp_on_15m_reversal := true
if (pending_long_tp_on_15m_reversal and confirm_15m_reversal_for_long_tp) // Check for confirmation
if (not first_tp_long_taken)
strategy.close(id="LE", comment="TP1 Long", qty_percent=50)
first_tp_long_taken := true
else
strategy.close(id="LE", comment="TP2 Long")
pending_long_tp_on_15m_reversal := false // Reset after TP
if (strategy.position_size < 0) // --- SHORT TP LOGIC ---
extreme_short_tp_condition = stoch_k_5min_val < extreme_short_tp_level or stoch_k_15min_val < extreme_short_tp_level
if (extreme_short_tp_condition)
if (not first_tp_short_taken)
strategy.close(id="SE", comment="TP1 Short", qty_percent=50)
first_tp_short_taken := true
else
strategy.close(id="SE", comment="TP2 Short")
pending_short_tp_on_15m_reversal := false // Reset pending state
else
// Conditional TP logic (5-min trigger + 15-min reversal)
if (stoch_5min_k_cross_over_d_tp and not pending_short_tp_on_15m_reversal) // Set pending state
pending_short_tp_on_15m_reversal := true
if (pending_short_tp_on_15m_reversal and confirm_15m_reversal_for_short_tp) // Check for confirmation
if (not first_tp_short_taken)
strategy.close(id="SE", comment="TP1 Short", qty_percent=50)
first_tp_short_taken := true
else
strategy.close(id="SE", comment="TP2 Short")
pending_short_tp_on_15m_reversal := false // Reset after TP