Mean Reversion Algorithm Development
Mean reversion is a trading concept: asset price after deviation from historical average tends to return. This is opposite to momentum trading. Algorithm opens position against short-term move, betting on return to average.
When Mean Reversion Works
Strategy is effective in specific market conditions:
- Range-bound/sideways — price oscillates around defined level
- High-frequency moves — short-term deviations that market makers return to center
- Overextended moves — movement significantly exceeds ATR, likely pullback
- Fundamentally stable assets — assets with strong demand at specific levels
Strategy performs poorly in trends: shorting a deviation up may catch trend continuation.
Mean Reversion Indicators
Bollinger Bands: classic tool. Price touches lower band (−2σ) → buy. Touches upper (+2σ) → sell. Exit on return to middle (SMA 20).
RSI (Relative Strength Index): RSI < 30 → oversold → potential buy. RSI > 70 → overbought → potential sell.
Z-score from rolling mean:
def zscore_signal(prices, window=20):
rolling_mean = prices.rolling(window).mean()
rolling_std = prices.rolling(window).std()
z = (prices - rolling_mean) / rolling_std
return z
Buy signal at Z < -2, sell at Z > +2, close at |Z| < 0.5.
Mean Reversion Index (MRI): custom indicator based on distance from EMA and historical ATR:
MRI = (Price - EMA(n)) / ATR(n)
Trend Filter
Without trend filter, mean reversion algorithm is destructive on trending markets. Add filters:
- ADX < 25: trade only when trend is weak (ADX — trend strength indicator)
- Price in range: price between EMA(50) and EMA(200) — flat zone
- Choppiness Index > 61.8: market in chaos rather than trend
Entry and Exit Logic
Entry: open position on reaching threshold Z-score + reversal candle confirmation (pin bar, hammer, engulfing).
Exit:
- Profit target: return to rolling mean (Z-score = 0)
- Stop-loss: further deviation expansion to Z = ±3.5 (or fixed % of ATR)
- Time-based exit: if after N candles position not closed in profit — close it
Partial take profit: close 50% at Z = ±1.0, remainder at Z = 0.
Parameter Optimization
Parameters (window for mean/std, entry Z-score, exit Z-score) optimized via walk-forward analysis on historical data. Important to avoid overfitting: test on several independent periods.
Stack: Python (pandas, numpy, ta-lib), CCXT for exchange connection, PostgreSQL for signal and trade storage. Parameters configured via YAML file without code changes.







