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
É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
- Choisissez une paire : entrez deux tickers manuellement (ex:
V / MA) ou cliquez sur une paire suggérée
- 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
- 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 :
- α : 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 :
- 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
Si la paire est cointégrée, ce spread est stationnaire et oscille autour d'une moyenne stable.
4. Z-Score rolling
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
Où c est le taux de frais de transaction (défaut : 0.1%).
7. Courbe d'equity
Prix normalisés (base 100) :
Rendement total :
Sharpe Ratio (annualisé) :
Max Drawdown :
Win Rate :
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.