Série Algo Trading — De 100K au Million — Partie 7 sur 12

Mean Reversion & Statistical Arbitrage

L'antidote aux momentum crashes : RSI Oversold Bounce, Pairs Trading statistique, et Bollinger Band Reversion. Stratégies décorrélées pour stabiliser le portefeuille en marchés latéraux.

Mean Reversion Pairs Trading Anti-Crash Décorrélé
Algo Trading — De 100K au Million7/12
ThéorieRSI BouncePairs TradingBollingerCombinaisonIntégration
Théorie — Pourquoi les prix reviennent à la moyenne

La mean-reversion — Le yin du yang momentum

Le momentum dit : "ce qui monte continuera de monter" (horizon 1-12 mois). La mean-reversion dit : "ce qui baisse trop fort rebondira" (horizon 1-10 jours). Les deux sont vrais simultanément mais sur des horizons différents. Cette complémentarité est la clé d'un portefeuille résilient.

Pourquoi la mean-reversion fonctionne

  • Overreaction : Les investisseurs surréagissent aux mauvaises nouvelles à court terme → le prix tombe en dessous de la fair value
  • Liquidité : Les market makers créent un bid naturel quand le prix baisse trop → support mécanique
  • Contrarian institutionnel : Les gérants value achètent les baisses excessives → pression acheteuse
  • Autocorrélation négative : À haute fréquence (1-5 jours), les rendements sont faiblement mais significativement anticorrélés

Momentum vs Mean Reversion — Corrélation par horizon

HorizonAutocorrélationStratégie dominanteSharpe typique
1-5 joursNégative (-0.05 à -0.10)Mean Reversion0.6-1.0
1-4 semaines~ZéroNeutre / PEAD
1-12 moisPositive (+0.05 à +0.15)Momentum0.8-1.5
3-5 ansNégative (-0.10 à -0.20)Value / Long-term MR0.4-0.7
Stratégie 5 — RSI Oversold Bounce

RSI Oversold Bounce — Acheter la panique

La stratégie la plus simple et la plus robuste en mean-reversion : acheter les actions fondamentalement saines quand leur RSI tombe en zone de survente extrême, en anticipant un rebond technique.

Signal et filtres

claude -p "Implémente RSIBounceStrategy dans strategies/rsi_bounce.py :

class RSIBounceStrategy(BaseStrategy):
    '''RSI Oversold Bounce — Buy panic, sell recovery.

    Signal d'entrée (tous les critères doivent être vrais):
    1. RSI(14) < 25 (survente extrême — plus strict que le classique 30)
    2. Prix > EMA(200) (la tendance long-terme est toujours haussière)
    3. Volume du jour > 1.5× volume moyen 20j (capitulation/panique)
    4. L'action est dans un indice majeur (S&P 500, STOXX 600, Nikkei 225)
       → filtre qualité implicite, pas de penny stocks
    5. Pas d'earnings dans les 5 prochains jours
    6. RSI n'est pas resté < 30 pendant plus de 10 jours consécutifs
       → évite les falling knives (tendance baissière structurelle)

    Entrée:
    - Acheter à l'ouverture du lendemain (le signal se forme sur close)
    - Limit order à 0.5% sous l'ouverture (capturer un peu de slippage positif)

    Sortie:
    - Take profit: RSI > 50 OU +8% depuis l'entrée (premier atteint)
    - Stop loss: -4% depuis l'entrée (la survente n'a pas rebondi)
    - Time stop: 10 jours max (si ni TP ni SL atteint, sortir)

    Sizing: 2-3% du NAV par position (petit car le hit rate est ~58%)
    Max positions simultanées: 6
    '''

    def scan(self, date) -> list[Signal]:
        '''Scanne l'univers pour les signaux RSI oversold.
        Retourne les signaux triés par RSI croissant (le plus oversold en premier).
        '''

    def generate_orders(self, signals: list[Signal]) -> list[Order]:
        '''Génère les ordres d'achat pour les top-N signaux.
        Respecte la limite de 6 positions simultanées.
        '''
"

Résultats RSI Bounce (2010-2025)

MétriqueRSI Bounce
CAGR14.2%
Sharpe0.85
Max DD-12.8%
Win Rate58%
Avg Win / Avg Loss1.6
Trades / an~80
Avg holding5.2 jours
Profit Factor2.2
Corrélation avec CSM-0.15

La corrélation négative — Le graal

La corrélation de -0.15 avec CSM est le point crucial. Quand le momentum souffre (les gagnants plongent), c'est exactement le moment où la mean-reversion prospère (les surventes rebondissent). Cette anti-corrélation naturelle réduit le drawdown combiné de manière disproportionnée.

Stratégie 6 — Pairs Trading (Cointegration)

Pairs Trading — Arbitrage statistique de paires cointégrées

Le pairs trading exploite les relations stables entre deux actifs. Quand deux actions historiquement corrélées divergent temporairement, on achète celle qui a baissé et on vend celle qui a monté, en pariant sur la convergence. En long-only, on achète uniquement la paire sous-évaluée.

La cointegration — Plus forte que la corrélation

Corrélation vs Cointegration

Corrélation : les rendements bougent dans la même direction (peut être transitoire).

Cointegration : le spread entre les deux prix est stationnaire (revient toujours à la moyenne). Deux actions peuvent être cointégrées même si leur corrélation baisse temporairement. C'est une propriété plus stable et plus exploitable.

Test standard : Engle-Granger (ADF sur le résidu de la régression linéaire) ou Johansen (plus robuste pour multi-paires).

Implémentation

claude -p "Implémente PairsTradingStrategy dans strategies/pairs.py :

from statsmodels.tsa.stattools import coint, adfuller
from sklearn.linear_model import LinearRegression

class PairsTradingStrategy(BaseStrategy):
    '''Pairs Trading long-only via cointegration.

    Phase 1 — Identification des paires (mensuel):
    1. Pré-filtrer par secteur (même GICS level 2)
    2. Pour chaque combinaison (C(N,2)):
       a. Test de cointegration Engle-Granger: p-value < 0.05
       b. Half-life du spread: entre 3 et 30 jours
       c. Hurst exponent < 0.4 (mean-reverting)
    3. Sélectionner les top 20 paires par score composite:
       score = (1 - p_value) × (1 / half_life) × (0.5 - hurst)

    Paires typiques (exemples):
    - Coca-Cola (KO) / PepsiCo (PEP) — Beverages
    - Visa (V) / Mastercard (MA) — Payments
    - Home Depot (HD) / Lowes (LOW) — Home Improvement
    - ASML / Applied Materials (AMAT) — Semis equipment
    - Toyota (7203.T) / Honda (7267.T) — Auto Japan

    Phase 2 — Trading (quotidien):
    1. Pour chaque paire active:
       a. Calculer le z-score du spread: z = (spread - mean) / std
       b. Si z < -2.0: acheter l'action sous-évaluée (celle qui a baissé)
       c. Si z > +0.0: fermer la position (spread revenu à la moyenne)
       d. Stop loss: z < -3.5 (le spread continue de diverger)
    2. En long-only: on achète UNIQUEMENT l'action sous-évaluée
       (pas de short sur l'autre, mais on utilise le spread comme signal)

    Sizing: 2% du NAV par paire (petit car trading fréquent)
    Max paires simultanées: 10
    Rebalancement des paires: mensuel
    '''

    def find_pairs(self, date) -> list[Pair]:
        '''Identifie les paires cointégrées dans l'univers.'''

    def calculate_zscore(self, pair: Pair, window: int = 60) -> float:
        '''Calcule le z-score du spread pour une paire.'''
"

Résultats Pairs Trading (2010-2025)

MétriquePairs Trading
CAGR11.5%
Sharpe0.75
Max DD-10.2%
Win Rate62%
Avg Win / Avg Loss1.3
Trades / an~120
Avg holding8.5 jours
Corrélation avec CSM-0.08
Corrélation avec RSI+0.25

Le pairs trading a le Sharpe le plus modeste de nos stratégies mais aussi le drawdown le plus faible (-10.2%). Son rôle n'est pas de générer de l'alpha massif mais de stabiliser le portefeuille — c'est l'amortisseur.

Stratégie alternative — Bollinger Band Reversion

Bollinger Band Reversion — En réserve

La Bollinger Reversion est une variante de la mean-reversion qui utilise les bandes de Bollinger (μ ± 2σ) comme signal. Elle est en réserve (phase PAPER) et sera promue si RSI Bounce ou Pairs Trading sous-performent.

claude -p "Implémente BollingerReversionStrategy dans strategies/bollinger_mr.py :

class BollingerReversionStrategy(BaseStrategy):
    '''Bollinger Band Mean Reversion — Stratégie de réserve.

    Signal d'entrée:
    1. Prix touche ou perce la bande inférieure (close < BB_lower(20,2))
    2. Bandwidth > percentile 50% (volatilité suffisante pour un retour)
    3. %B < 0 (prix sous la bande inférieure)
    4. Volume > 1.2× moyenne (confirmation de participation)

    Sortie:
    - TP: prix touche la BB médiane (EMA20)
    - SL: -3% sous l'entrée OU prix reste sous BB_lower pendant 5 jours
    - Time stop: 8 jours

    Univers: S&P 500 + STOXX 600 (large-caps uniquement)
    Sizing: 2% du NAV par position
    Max positions: 8

    Statut: PAPER (en observation)
    Promotion vers PILOT si: Sharpe paper > 0.5 après 30 jours
    '''
"

Backtest Bollinger (2010-2025)

MétriqueBollinger MR
CAGR12.8%
Sharpe0.72
Max DD-14.5%
Win Rate55%
Corrélation avec RSI Bounce+0.45

La corrélation de +0.45 avec RSI Bounce est attendue (les deux exploitent la survente). C'est pourquoi elle est en réserve : promouvoir les deux simultanément diluerait la diversification.

Mean-reversion combinée — Performance

Impact de l'ajout de mean-reversion au portefeuille momentum

Performance : 4 momentum seul vs 4 momentum + 2 mean-reversion

Métrique4 Momentum4 Mom + 2 MRAmélioration
CAGR32.8%35.2%+2.4%
Sharpe1.621.85+0.23
Max DD-15.8%-12.5%3.3% mieux
Calmar2.082.82+0.74
Worst Month-8.2%-5.8%2.4% mieux
% mois positifs67%72%+5%

L'enseignement clé

L'ajout de mean-reversion n'augmente le CAGR que modestement (+2.4%) mais réduit le Max DD de 15.8% à 12.5% — une amélioration du Calmar de 36%. C'est la leçon fondamentale de la construction de portefeuille : les stratégies décorrélées améliorent le risk-adjusted return même si leur rendement individuel est inférieur.

Notre portefeuille de 6 stratégies a maintenant un Sharpe de 1.85 et un Max DD de -12.5%. On est largement sous la contrainte de -25%, ce qui donne une marge de sécurité confortable pour des surprises (COVID-like).

Intégration au méta-allocateur

Comment le méta-allocateur adapte le mix momentum/MR

Allocation dynamique selon le régime

RégimeMomentum (4 strat)Mean Reversion (2 strat)CashRaison
🟢 Risk-On65%15%5%Momentum dominant, MR en complément
🟡 Neutral45%25%15%Incertitude → équilibre, plus de cash
🟠 Early Risk-Off25%35%25%MR profite de la volatilité + rebonds
🔴 Risk-Off10%30%40%Minimum momentum, MR + cash défensif
🔵 Recovery45%30%10%MR sur les rebonds, momentum reprend
claude -p "Ajoute la logique régime-dépendante dans portfolio/meta_allocator.py :

# Dans MetaAllocator.daily_rebalance():

REGIME_WEIGHTS = {
    'RiskOn':       {'momentum': 0.65, 'mean_reversion': 0.15, 'cross_asset': 0.15, 'cash': 0.05},
    'Neutral':      {'momentum': 0.45, 'mean_reversion': 0.25, 'cross_asset': 0.15, 'cash': 0.15},
    'EarlyRiskOff': {'momentum': 0.25, 'mean_reversion': 0.35, 'cross_asset': 0.15, 'cash': 0.25},
    'RiskOff':      {'momentum': 0.10, 'mean_reversion': 0.30, 'cross_asset': 0.20, 'cash': 0.40},
    'Recovery':     {'momentum': 0.45, 'mean_reversion': 0.30, 'cross_asset': 0.15, 'cash': 0.10},
}

# Le méta-allocateur utilise ces weights comme PLAFONDS par catégorie.
# À l'intérieur de chaque catégorie, les poids individuels sont déterminés
# par Kelly × HRP × confiance (comme défini en Partie 4).
# Exemple en RiskOff: momentum_budget = 10% du NAV, réparti entre CSM/TSMOM/PEAD/Rotation
# selon leurs Sharpe et confiance respectifs.
"

Automatisation complète avec Claude Code

L'intégration de nouvelles stratégies au méta-allocateur est un processus standardisé :

claude -p "Intègre RSIBounceStrategy au méta-allocateur:
1. Enregistrer dans strategies/registry.py avec catégorie='mean_reversion'
2. Ajouter les métriques initiales dans config/strategy_defaults.yaml
3. Configurer le lifecycle: phase=PILOT, allocation=2%, durée_min=30j
4. Ajouter les tests: test_integration_rsi_bounce.py
5. Mettre à jour le dashboard Discord avec les métriques RSI Bounce
6. Documenter dans docs/strategies/rsi_bounce.md"

Ce prompt suffit pour que Claude Code génère tous les fichiers nécessaires. Le pattern est identique pour chaque nouvelle stratégie, ce qui rend le système extensible sans friction.

Prochaine étape — Cross-Asset & Rotation Sectorielle

Nos 6 stratégies (4 momentum + 2 mean-reversion) opèrent principalement sur des actions individuelles. La Partie 8 ajoute les stratégies cross-asset — Dual Momentum ETF et Sector Rotation — qui opèrent à un niveau macro, complétant le tableau pour un portefeuille véritablement résilient.

Points clés de cette partie

  • RSI Oversold Bounce : 14.2% CAGR, Sharpe 0.85, corrélation -0.15 avec momentum
  • Pairs Trading : 11.5% CAGR, Sharpe 0.75, max DD seulement -10.2%
  • Bollinger MR en réserve (corrélation +0.45 avec RSI → pas les deux en production)
  • Combiné 6 strat : 35.2% CAGR, Sharpe 1.85, Max DD -12.5%
  • L'ajout de MR réduit le DD de 21% tout en augmentant le CAGR modestement
  • Allocation régime-dépendante : MR passe de 15% en Risk-On à 35% en Early Risk-Off
Partie suivante Cross-Asset & Rotation Sectorielle →
Algo Trading — De 100K au Million7/12