Trading Strategy

Bollinger Bands

A volatility-based strategy using standard deviation bands to identify mean reversion opportunities and market volatility.

Statistical Mean Reversion

Bollinger Bands use standard deviation to measure market volatility. This implementation combines standard bands with an RSI filter to avoid "walking the bands" during hyper-trends, focusing on reversals only when momentum is overextended and aligned with the 200 EMA baseline.

Volatility Type
4h Chart Timeframe
Intermediate Complexity
Ranging Best Market

Signal Logic

Long Signal

Triggered when price touches the lower band, RSI < 50, and price is above the 200 EMA filter.

Short Signal

Triggered when price touches the upper band, RSI > 50, and price is below the 200 EMA filter.

Implementation

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

// ==========================================
// 🔹 INPUTS
// ==========================================
grp_bb   = "Bollinger Bands"
bb_len   = input.int(20, "Length", minval=1, group=grp_bb)
bb_mult  = input.float(2.0, "Multiplier", minval=0.1, step=0.1, group=grp_bb)

grp_rsi  = "RSI Momentum"
rsi_len  = input.int(14, "Length", minval=1, group=grp_rsi)
rsi_ob   = input.int(70, "Overbought", group=grp_rsi)
rsi_os   = input.int(30, "Oversold", group=grp_rsi)

grp_flt  = "Trend Filter"
use_ema  = input.bool(true, "Filter with 200 EMA?", group=grp_flt)
ema_len  = input.int(200, "EMA Length", minval=1, group=grp_flt)

grp_risk = "Risk Management (ATR)"
atr_len  = input.int(14, "ATR Length", group=grp_risk)
sl_mult  = input.float(1.5, "Stop Loss ATR Multiplier", step=0.1, group=grp_risk)
tp_mult  = input.float(2.0, "Take Profit ATR Multiplier", step=0.1, group=grp_risk)

// --- Indicators ---
// Bollinger Bands
[middle, upper, lower] = ta.bb(close, bb_len, bb_mult)

// RSI
rsi = ta.rsi(close, rsi_len)

// EMA Trend Filter
emaTrend = ta.ema(close, ema_len)
atr = ta.atr(atr_len)

// --- Plotting ---
plot(upper, "Upper Band", color=color.new(color.red, 50))
plot(lower, "Lower Band", color=color.new(color.green, 50))
plot(middle, "Basis", color=color.new(color.gray, 0))
plot(use_ema ? emaTrend : na, "Trend EMA", color=color.orange, linewidth=2)

// --- Strategy Logic ---

// Trend Context
isUptrend   = use_ema ? close > emaTrend : true
isDowntrend = use_ema ? close < emaTrend : true

// 1. Long Entry
// Price crosses under Lower Band + RSI Oversold + We are in an Uptrend
longCondition = ta.crossover(close, lower) and rsi < 50 and isUptrend

// 2. Short Entry
// Price crosses over Upper Band + RSI Overbought + We are in a Downtrend
shortCondition = ta.crossunder(close, upper) and rsi > 50 and isDowntrend

// --- Execution ---

if (longCondition)
    // Dynamic Stop Loss and Take Profit based on Volatility (ATR)
    float sl_price_l = close - (atr * sl_mult)
    float tp_price_l = close + (atr * tp_mult)
    strategy.entry("Long", strategy.long, comment="Trend Buy")
    strategy.exit("Exit Long", "Long", stop=sl_price_l, limit=tp_price_l)

if (shortCondition)
    float sl_price_s = close + (atr * sl_mult)
    float tp_price_s = close - (atr * tp_mult)
    strategy.entry("Short", strategy.short, comment="Trend Sell")
    strategy.exit("Exit Short", "Short", stop=sl_price_s, limit=tp_price_s)