Mean Reversion Strategies
Bollinger Band Mean Reversion
Tags: mean_reversion, bbands, oversold, bounce
Functions: bollinger_bands
Description: Buys when price touches the lower Bollinger Band and bounces up, exits at the middle band.
Code:
ticker = context['ticker']
upper, middle, lower = bollinger_bands(close, 20, 2)
# Touch lower band and bounce
touch_lower = close <= lower
bounce = close > close.shift(1)
long_cond = (touch_lower) & (bounce)
# Exit at middle or upper band
exit_cond = close >= middle
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Bollinger Band Squeeze Breakout
Tags: volatility, bbands, squeeze, breakout
Functions: bollinger_bands, std
Description: Buys when price breaks above the upper Bollinger Band after the band width has contracted, capturing volatility expansion.
Code:
ticker = context['ticker']
upper, middle, lower = bollinger_bands(close, 20, 2)
# Band width
band_width = (upper - lower) / middle
bw_avg = ts_mean(band_width, 50)
# Squeeze: current width < 0.7x average
squeeze = band_width < bw_avg * 0.7
# Breakout above upper band
breakout = close > upper
long_cond = (squeeze.shift(1)) & (breakout)
exit_cond = close < middle
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Z-Score Mean Reversion
Tags: mean_reversion, zscore, statistical
Functions: ts_zscore
Description: Buys when the price Z-score falls below -2 (extreme undervaluation) and exits when it returns to 0.
Code:
ticker = context['ticker']
z_score = ts_zscore(close, 20)
long_cond = z_score < -2
exit_cond = z_score > 0
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
RSI Mean Reversion with Confirmation
Tags: mean_reversion, rsi, confirmation, turning_point
Functions: rsi
Description: Enters when RSI is below 30 and already turning upward, improving win rate over a simple threshold cross.
Code:
ticker = context['ticker']
rsi_val = rsi(close, 14)
# Oversold AND turning up
oversold = rsi_val < 30
turning_up = rsi_val > rsi_val.shift(1)
long_cond = (oversold) & (turning_up)
# Exit when RSI normalizes
exit_cond = rsi_val > 50
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Double Bottom RSI
Tags: mean_reversion, rsi, pattern, double_bottom
Functions: rsi, ts_mean
Description: Buys when RSI is below 30 and the second RSI trough is higher than the first (bullish RSI divergence).
Code:
ticker = context['ticker']
rsi_val = rsi(close, 14)
# Current RSI oversold
oversold = rsi_val < 30
# RSI making higher low (vs 5 bars ago)
higher_low = (rsi_val > rsi_val.shift(5)) & (close < close.shift(5))
long_cond = (oversold) & (higher_low)
exit_cond = rsi_val > 60
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Keltner Channel Reversion
Tags: mean_reversion, keltner, atr, channel
Functions: ema, atr
Description: Buys when price re-enters the Keltner Channel after breaking below the lower band.
Code:
ticker = context['ticker']
ema20 = ema(close, 20)
atr_val = atr(high, low, close, 14)
kc_upper = ema20 + atr_val * 2
kc_lower = ema20 - atr_val * 2
# Price was below lower band, now re-entering
was_below = close.shift(1) < kc_lower
re_enter = close > kc_lower
long_cond = (was_below) & (re_enter)
exit_cond = close > ema20
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Oversold Stochastic Mean Reversion
Tags: mean_reversion, stochastic, oversold
Functions: stoch
Description: Buys when Stochastic crosses above 20 after reaching an extreme oversold level below 10.
Code:
ticker = context['ticker']
slowk, slowd = stoch(high, low, close, 14, 3, 3)
# Was extremely oversold, now recovering
was_extreme = slowk.shift(1) < 10
recovering = slowk > 20
long_cond = (was_extreme) & (recovering)
exit_cond = slowk > 70
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Price-MA Distance Reversion
Tags: mean_reversion, ma, distance, deviation
Functions: sma
Description: Buys when price drops more than 5% below the 20-day MA, expecting a reversion back to the mean.
Code:
ticker = context['ticker']
ma20 = sma(close, 20)
# Distance from MA
distance_pct = (close - ma20) / ma20
# More than 5% below MA
oversold = distance_pct < -0.05
# Showing signs of recovery
recovering = close > close.shift(1)
long_cond = (oversold) & (recovering)
exit_cond = close > ma20
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))
Perpetual Mean Reversion Long/Short
Tags: mean_reversion, zscore, perpetual, long_short
Functions: ts_zscore
Description: Bidirectional Z-score mean reversion on futures: long when Z < -2 and short when Z > 2.
Code:
ticker = context['ticker']
z_score = ts_zscore(close, 20)
long_cond = z_score < -2
short_cond = z_score > 2
exit_long = z_score > 0
exit_short = z_score < 0
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(short_cond, entry(ticker, 'SHORT', Weight(1.0)))
emit(exit_long, exit_position(ticker))
emit(exit_short, exit_position(ticker))
Williams %R Extreme Reversion
Tags: mean_reversion, williams_r, extreme, oversold
Functions: williams_r
Description: Buys when Williams %R rebounds from an extreme oversold level below -90.
Code:
ticker = context['ticker']
wr = williams_r(high, low, close, 14)
# Extreme oversold (-90 or below) and bouncing
extreme_oversold = wr < -90
bouncing = wr > wr.shift(1)
long_cond = (extreme_oversold) & (bouncing)
exit_cond = wr > -20
emit(long_cond, entry(ticker, 'LONG', Weight(1.0)))
emit(exit_cond, exit_position(ticker))