Trading Strategy

RSI Strategy

A momentum oscillator that measures the speed and change of price movements to identify overbought or oversold conditions.

The Speed of Change

The Relative Strength Index measures the velocity of price movements. By adding a 200 EMA trend filter, this strategy transforms a simple oscillator into a robust system that only "fades" the trend when the risk-to-reward ratio is statistically in your favor, avoiding dangerous early entries in strong trends.

Momentum Type
4h Chart Timeframe
Beginner Complexity
Ranging Best Market

Signal Logic

Oversold (Buy)

Triggered when RSI crosses back above 30, provided price is above the 200 EMA trend filter.

Overbought (Sell)

Triggered when RSI crosses back below 70, provided price is below the 200 EMA trend filter.

Implementation

//@version=6
strategy("RSI Strategy", overlay=true, initial_capital=1000000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)

// ==========================================
// 🔹 INPUTS
// ==========================================
// Group: Trend Filter
grp_trend = "Trend Filter"
use_trend = input.bool(true, "Use Trend Filter (EMA 200)", group=grp_trend)
ema_len   = input.int(200, "Trend EMA Length", minval=1, group=grp_trend)

// Group: RSI Settings
grp_rsi   = "RSI Settings"
rsi_len   = input.int(14, "RSI Length", minval=1, group=grp_rsi)
rsi_ob    = input.int(70, "Overbought Level", minval=50, maxval=100, group=grp_rsi)
rsi_os    = input.int(30, "Oversold Level", minval=0, maxval=50, group=grp_rsi)

// Group: Risk Management (ATR)
grp_risk  = "Risk Management"
atr_len   = input.int(14, "ATR Length", minval=1, group=grp_risk)
sl_mult   = input.float(1.5, "Stop Loss (ATR Multiplier)", step=0.1, group=grp_risk)
tp_ratio  = input.float(2.0, "Risk:Reward Ratio", step=0.1, group=grp_risk)

// ==========================================
// 🔹 CALCULATIONS
// ==========================================
// Corrected: Using ta. namespace for standard calculations
rsi_val = ta.rsi(close, rsi_len)
ema_val = ta.ema(close, ema_len)
atr_val = ta.atr(atr_len)

// Trend Conditions
is_uptrend   = use_trend ? close > ema_val : true
is_downtrend = use_trend ? close < ema_val : true

// ==========================================
// 🔹 STRATEGY LOGIC
// ==========================================

// Long Entry:
// 1. Market is in Uptrend (Price > EMA)
// 2. RSI was Oversold (below 30) and now Crosses Over 30
// Using ta.crossover for explicit crossover logic
long_signal  = is_uptrend and ta.crossover(rsi_val, rsi_os)

// Short Entry:
// 1. Market is in Downtrend (Price < EMA)
// 2. RSI was Overbought (above 70) and now Crosses Under 70
short_signal = is_downtrend and ta.crossunder(rsi_val, rsi_ob)

// ==========================================
// 🔹 EXECUTION & RISK MANAGEMENT
// ==========================================

if long_signal
    strategy.entry("Long", strategy.long, comment="L | RSI Dip")

if short_signal
    strategy.entry("Short", strategy.short, comment="S | RSI Spike")

// Exit Logic
// We calculate the stop/limit prices relative to the average entry price.
// Note: As ATR fluctuates, these exit levels will adjust dynamically with volatility.
strategy.exit("Exit Long", "Long", stop=strategy.position_avg_price - (atr_val * sl_mult), limit=strategy.position_avg_price + (atr_val * sl_mult * tp_ratio), comment_loss="SL", comment_profit="TP")
strategy.exit("Exit Short", "Short", stop=strategy.position_avg_price + (atr_val * sl_mult), limit=strategy.position_avg_price - (atr_val * sl_mult * tp_ratio), comment_loss="SL", comment_profit="TP")

// ==========================================
// 🔹 VISUALS
// ==========================================
// Plot EMA
plot(use_trend ? ema_val : na, "Trend EMA", color=color.new(color.orange, 0), linewidth=2)

// Plot Signals
plotshape(long_signal, title="Long Signal", location=location.belowbar, color=color.green, style=shape.labelup, text="BUY", textcolor=color.white)
plotshape(short_signal, title="Short Signal", location=location.abovebar, color=color.red, style=shape.labeldown, text="SELL", textcolor=color.white)

// Background color to visualize trend context
bgcolor(use_trend ? (is_uptrend ? color.new(color.green, 95) : color.new(color.red, 95)) : na)