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.
VolatilityType
4h ChartTimeframe
IntermediateComplexity
RangingBest 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=6strategy("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)