# 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 ```bash # 1. Cloner le repo git clone https://github.com//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| < 0.5` | **Exit** : fermer la position | | `|z| > 3.5` | **Stop loss** : couper les pertes | ### 6. P&L quotidien

PnL quotidien

Frais

Où **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.