pairs-cointegration / README.md
README.md
Raw

Pairs Trading — Cointegration Dashboard

Dashboard interactif de pairs trading basé sur la cointégration statistique. Test, signaux et backtest sur n'importe quelle paire d'actifs financiers.

Construit avec Python, Streamlit et Plotly.


Qu'est-ce que le Pairs Trading ?

Le pairs trading est une stratégie market-neutral : plutôt que de parier sur la hausse ou la baisse du marché, on parie sur la convergence de l'écart entre deux actifs liés.

L'idée repose sur la cointégration : deux actifs du même secteur (ex: Visa et Mastercard) ont tendance à évoluer ensemble sur le long terme. Quand leur écart (le spread) s'éloigne anormalement de sa moyenne, on anticipe qu'il va y revenir — c'est là qu'on entre en position.

Concrètement :

  • Si le spread est anormalement bas → on achète A et on vend B
  • Si le spread est anormalement haut → on vend A et on achète B
  • Quand le spread revient à la normale → on ferme la position et on encaisse le profit

Parce qu'on achète un actif et on en vend un autre simultanément, les risques liés à la direction du marché se compensent — la stratégie est théoriquement immunisée contre les crashs.


Fonctionnalités

  • Test de cointégration Engle-Granger sur n'importe quelle paire de tickers
  • Génération de signaux basée sur le z-score rolling du spread
  • Backtest historique avec calcul des métriques de performance (Sharpe, Max DD, Win Rate, Profit Factor...)
  • Dashboard interactif Streamlit avec graphiques Plotly
  • Paramètres ajustables : période, seuils d'entrée/sortie, fenêtre rolling, coûts de transaction
  • Paires suggérées pré-chargées en un clic (V/MA, MCD/YUM, PG/CL...)

Stack technique

Outil Usage
yfinance Récupération des données historiques
pandas / numpy Manipulation et calculs sur les séries temporelles
statsmodels Test de cointégration Engle-Granger (ADF)
plotly Graphiques interactifs
streamlit Dashboard web

Installation & Lancement

Prérequis

  • Python 3.11 ou plus

Étapes

# 1. Cloner le repo
git clone https://github.com/<votre-username>/pairs-trading-cointegration.git
cd pairs-trading-cointegration

# 2. Installer les dépendances
pip install -r requirements.txt

# 3. Lancer le dashboard
streamlit run app.py

Le dashboard s'ouvre automatiquement dans votre navigateur (par défaut http://localhost:8501).


Utilisation

  1. Choisissez une paire : entrez deux tickers manuellement (ex: V / MA) ou cliquez sur une paire suggérée
  2. Réglez les paramètres dans la sidebar :
    • Période de données (3y, 5y, 10y, 15y, 20y, max)
    • Seuils d'entrée / sortie du z-score
    • Fenêtre rolling
    • Coûts de transaction
  3. Cliquez sur Analyser : le dashboard affiche le test de cointégration, les graphiques, le backtest et le log des trades

N'hésitez pas à tester différentes paires et à jouer avec les paramètres pour voir comment ils impactent les performances.


Méthodologie

Le pipeline complet : Data → Cointégration → Signaux → Backtest

1. Régression linéaire (OLS)

On modélise la relation entre les deux prix :

OLS regression

  • α : intercept de la régression
  • β : coefficient de hedge (hedge ratio) — combien d'unités de B couvrent une unité de A
  • ε(t) : résidus de la régression

2. Test de cointégration (Engle-Granger / ADF)

On teste si les résidus ε(t) sont stationnaires via le test Augmented Dickey-Fuller :

ADF test

  • H₀ : γ = 0 → racine unitaire → non cointégré
  • H₁ : γ < 0 → stationnarité → cointégré
  • Si p-value < 0.05, on rejette H₀ → la paire est cointégrée

3. Spread

Spread

Si la paire est cointégrée, ce spread est stationnaire et oscille autour d'une moyenne stable.

4. Z-Score rolling

Z-score

Où μ(t) et σ(t) sont la moyenne et l'écart-type glissants sur une fenêtre de 60 jours par défaut.

5. Règles de trading

Condition Action
z < -2.0 Long spread : acheter A, shorter B
z > +2.0 Short spread : shorter A, acheter B
` z
` z

6. P&L quotidien

PnL quotidien

Frais

c est le taux de frais de transaction (défaut : 0.1%).

7. Courbe d'equity

Equity

8. Métriques de performance

Prix normalisés (base 100) :

Prix normalisés

Rendement total :

Rendement total

Sharpe Ratio (annualisé) :

Sharpe

Max Drawdown :

Max Drawdown

Win Rate :

Win Rate

Profit Factor :

Profit Factor


Résultats

À vous de jouer. Lancez le dashboard et testez différentes paires pour découvrir lesquelles sont cointégrées et comment la stratégie performe. Les paires suggérées (V/MA, MCD/YUM, PG/CL) sont de bons points de départ.

Screenshots à venir.


Limites du projet

Ce projet est volontairement simplifié pour rester pédagogique. Plusieurs limitations importantes existent et seraient à corriger pour une utilisation réelle :

Limites méthodologiques

  • Overfitting des paramètres : les seuils (entry = 2.0, exit = 0.5, stop loss = 3.5) et la fenêtre rolling (60 jours) sont fixés arbitrairement. Optimiser ces paramètres sur les données historiques peut donner d'excellents résultats a posteriori, mais sans garantie qu'ils tiennent à l'avenir.
  • Look-ahead bias : le coefficient β est calculé sur l'ensemble de la période (in-sample), pas en rolling. Une vraie stratégie devrait recalculer β uniquement sur les données disponibles à chaque instant t.
  • Cointégration instable : la relation de cointégration n'est pas stable dans le temps. Une paire cointégrée sur 10 ans peut ne plus l'être sur les 2 dernières années (cf. KO/PEP). En production, il faudrait re-tester la cointégration régulièrement.
  • Hypothèse de linéarité : la régression OLS suppose une relation linéaire entre les deux actifs. Cette hypothèse peut être trop forte selon les périodes ou les régimes de marché.

Limites de modélisation

  • Coûts de transaction simplifiés : on applique un coût proportionnel uniforme. En réalité, il faudrait modéliser le bid-ask spread, le slippage (impact de marché) et les frais d'emprunt pour le short selling.
  • Position sizing fixe : le backtest trade toujours 1 action de A + β actions de B, sans gestion dynamique du capital ni effet de levier réaliste.
  • Pas de short borrowing fees : shorter une action coûte de l'argent en pratique (frais d'emprunt). Ce n'est pas modélisé.
  • Données journalières uniquement : la stratégie pourrait être plus performante en intraday, mais ça demande des données et une infrastructure différentes.

Limites statistiques

  • Multiple testing : si on teste des centaines de paires, certaines passeront le test de cointégration par pur hasard (faux positifs). C'est pour ça qu'il faut toujours combiner le test statistique avec une logique économique (même secteur, même business model).
  • Régimes de marché : la stratégie ne s'adapte pas aux changements de régime (crise, taux, inflation). Un modèle plus sophistiqué utiliserait du regime-switching ou des modèles d'état.

Pour aller plus loin

Améliorations possibles dans une v2 :

  • β recalculé en rolling (Kalman filter par exemple)
  • Optimisation des paramètres en walk-forward (out-of-sample)
  • Capital initial paramétrable et position sizing dynamique
  • Test d'autres méthodes de cointégration (Johansen, multi-actifs)
  • Comparaison à un benchmark (SPY, taux sans risque)

Structure du projet

pairs-trading-cointegration/
├── app.py                  # Point d'entrée Streamlit
├── requirements.txt
├── README.md
├── src/
│   ├── data.py             # Récupération des données (yfinance)
│   ├── cointegration.py    # Tests statistiques (Engle-Granger, ADF)
│   ├── signals.py          # Génération des signaux (z-score)
│   ├── backtest.py         # Simulation des trades & métriques
│   └── visualization.py    # Graphiques Plotly
└── tests/
    └── test_cointegration.py

Disclaimer

Ce projet est réalisé à but éducatif uniquement. Il ne constitue pas un conseil en investissement. Les performances passées ne préjugent pas des performances futures.