Arbitrage statistique dans le crypto — Trading de paires et retour à la moyenne

L'arbitrage statistique exploite les écarts temporaires par rapport aux prix d'équilibre. Lorsque deux actifs qui évoluent normalement ensemble divergent, un trader d'arbitrage statistique achète le sous-performant et vend à découvert le surperformant, en pariant sur une convergence. Dans le crypto, cette stratégie est particulièrement puissante car les actifs sont corrélés mais pas parfaitement, créant ainsi des opportunités profitables.

Exemple : La corrélation entre BTC et ETH est de 0,85. Lorsque ETH sous-performe BTC de 3 % sur une période d'une heure (ce qui est inhabituel), un trader d'arbitrage statistique vend à découvert BTC et prend une position longue sur ETH. Historiquement, ils convergent en 4 à 8 heures, verrouillant un profit d'environ 1 à 1,5 %.

Bases du trading de paires

Sélection des paires

Toutes les paires ne fonctionnent pas. Vous avez besoin :

Python — Sélection de paires
import pandas as pd
from scipy.stats import pearsonr
def find_cointegrated_pairs(symbols, data):
candidates = []
for i, sym1 in enumerate(symbols):
for sym2 in symbols[i+1:]:
# Calculer la corrélation
corr, p_value = pearsonr(data[sym1], data[sym2])
if corr > 0.75:
# Tester la coïntégration (test Engle-Granger)
residuals = data[sym1] - (data[sym2] * corr)
adf_stat = adf_test(residuals) # stationnarité
if adf_stat < 0.05: # stationnaire
candidates.append((sym1, sym2, corr))
return candidates

Analyse de coïntégration

Qu'est-ce que la coïntégration ?

Deux séries non stationnaires sont cointégrées si leur combinaison linéaire est stationnaire. En termes simples : elles évoluent ensemble dans le temps, et les écarts par rapport à cette relation finissent par se résorber.

Pour BTC et ETH :

Trouver le ratio de couverture

Utilisez une régression des moindres carrés ordinaires pour trouver le ratio optimal :

Python — Calcul du ratio de couverture
from sklearn.linear_model import LinearRegression
def get_hedge_ratio(price1, price2):
# Régression de price1 sur price2 pour trouver bêta (ratio de couverture)
X = price2.reshape(-1, 1)
y = price1
model = LinearRegression().fit(X, y)
hedge_ratio = model.coef_[0]
intercept = model.intercept_
return hedge_ratio, intercept
# Écart = price1 - (hedge_ratio × price2) + intercept
beta, alpha = get_hedge_ratio(btc_prices, eth_prices)
spread = btc - (beta * eth)

Stratégies de retour à la moyenne

Utilisation des scores Z

Standardisez l'écart pour détecter les extrêmes. Lorsque le z-score > 2, l'écart est anormalement large (opportunité de trading) :

Python — Trading de retour à la moyenne
def mean_reversion_signal(spread, lookback=20):
# Calculer la moyenne mobile et l'écart-type
mean = spread.rolling(window=lookback).mean()
std = spread.rolling(window=lookback).std()
# Z-score : nombre d'écarts-types par rapport à la moyenne
z_score = (spread - mean) / std
# Signaux de trading
if z_score[-1] > 2.0:
return "LONG_SPREAD" # écart trop large, acheter le sous-performant
elif z_score[-1] < -2.0:
return "SHORT_SPREAD" # écart trop étroit, vendre à découvert le sous-performant
else:
return "NEUTRAL"

Règles de sortie

Fermer lorsque l'écart revient à la moyenne (z-score → 0) ou seuil de perte (stop au renversement du z-score) :

Python — Logique de sortie
def check_exit(entry_z_score, current_z_score, entry_price):
# Prendre profit : l'écart a convergé à mi-chemin vers la moyenne
if abs(current_z_score) < abs(entry_z_score) * 0.5:
return SORTIE, objectif_de_profit
# Stop loss : le z-score s'est déplacé dans la mauvaise direction de >1
si (entry_z_score > 0 et current_z_score < entry_z_score + 1.0):
retour SORTIE, stop_loss
sinon si (entry_z_score < 0 et current_z_score > entry_z_score - 1.0):
retour SORTIE, stop_loss
retour MAINTAINIR, None

Backtesting des stratégies de stat arb

Métriques clés pour le stat arb :

Python — Backtest de stratégie de paires
def backtest_pairs_strategy(price1, price2, hedge_ratio):
spread = price1 - (hedge_ratio * price2)
mean = spread.rolling(20).mean()
std = spread.rolling(20).std()
z_score = (spread - mean) / std
trades = []
position = None
pour i dans range(len(z_score)):
si position est None:
si z_score[i] > 2.0:
position = {"entry": spread[i], "z_entry": z_score[i], "idx": i}
sinon:
exit_reason = check_exit(position["z_entry"], z_score[i], spread[i])[1]
si exit_reason:
pnl = position["entry"] - spread[i]
trades.append({"pnl": pnl, "reason": exit_reason})
position = None
retour pd.DataFrame(trades)

Ajouter l'intelligence Smart Money

Améliorez le trading de paires en filtrant les trades avec confirmation Smart Money :

Python — Stratégie de paires filtrée
def smart_money_pairs_strategy(symbol1, symbol2, z_score):
# Vérifier la confirmation Smart Money au niveau de la paire
sm1 = get_smart_money_signal(symbol1)
sm2 = get_smart_money_signal(symbol2)
# Si l'un est HAUSSier fort et l'autre BAISSIer fort = forte divergence
# Moment idéal pour trader le spread
divergence_score = abs(sm1["composite"] - sm2["composite"])
si z_score > 2.0 et divergence_score > 0.3 et sm1["confidence"] != "VETO":
retour "TRADE" # Signal de haute confiance
sinon:
retour "SKIP" # Attendre un alignement

Boostez le stat arb avec les signaux Smart Money de paires

Filtrez les trades de retour à la moyenne avec le consensus des baleines et les données de dérivés. Notre API confirme la validité de la divergence des paires avec une amélioration de précision de 62%.

Commencez à trader des paires →