Arbitraje estadístico en cripto — Trading de pares y reversión a la media

El arbitraje estadístico aprovecha las desviaciones temporales de los precios de equilibrio. Cuando dos activos que normalmente se mueven juntos divergen, un trader de arbitraje estadístico compra el de menor rendimiento y vende en corto el de mayor rendimiento, apostando por la convergencia. En cripto, esto es especialmente potente porque los activos están correlacionados pero no perfectamente, creando oportunidades rentables.

Ejemplo: La correlación entre BTC y ETH es 0.85. Cuando ETH tiene un rendimiento inferior al de BTC en un 3% durante un período de 1 hora (inusual), un trader de arbitraje estadístico vende en corto BTC y compra ETH. Históricamente, convergen en 4-8 horas, obteniendo un beneficio de ~1-1.5%.

Conceptos básicos del trading de pares

Selección de pares

No todos los pares funcionan. Necesitas:

Python — Selección de pares
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:]:
# Calcula la correlación
corr, p_value = pearsonr(data[sym1], data[sym2])
if corr > 0.75:
# Prueba de cointegración (test de Engle-Granger)
residuals = data[sym1] - (data[sym2] * corr)
adf_stat = adf_test(residuals) # estacionariedad
if adf_stat < 0.05: # estacionario
candidates.append((sym1, sym2, corr))
return candidates

Análisis de cointegración

¿Qué es la cointegración?

Dos series no estacionarias están cointegradas si su combinación lineal es estacionaria. En términos simples: se mueven juntas con el tiempo, y las desviaciones de esa relación eventualmente revierten.

Para BTC y ETH:

Encontrar la ratio de cobertura

Usa regresión por mínimos cuadrados para encontrar la ratio óptima:

Python — Cálculo de la ratio de cobertura
from sklearn.linear_model import LinearRegression
def get_hedge_ratio(price1, price2):
# Regresa price1 sobre price2 para encontrar beta (ratio de cobertura)
X = price2.reshape(-1, 1)
y = price1
model = LinearRegression().fit(X, y)
hedge_ratio = model.coef_[0]
intercept = model.intercept_
return hedge_ratio, intercept
# Spread = price1 - (hedge_ratio × price2) + intercept
beta, alpha = get_hedge_ratio(btc_prices, eth_prices)
spread = btc - (beta * eth)

Estrategias de reversión a la media

Usando Z-Scores

Estandariza el spread para detectar extremos. Cuando z-score > 2, el spread es inusualmente amplio (oportunidad de trading):

Python — Trading de reversión a la media
def mean_reversion_signal(spread, lookback=20):
# Calcula la media móvil y la desviación estándar
mean = spread.rolling(window=lookback).mean()
std = spread.rolling(window=lookback).std()
# Z-score: cuántas desviaciones estándar de la media
z_score = (spread - mean) / std
# Señales de trading
if z_score[-1] > 2.0:
return "LONG_SPREAD" # spread demasiado amplio, compra el de menor rendimiento
elif z_score[-1] < -2.0:
return "SHORT_SPREAD" # spread demasiado estrecho, vende en corto el de menor rendimiento
else:
return "NEUTRAL"

Reglas de salida

Cierra cuando el spread vuelve a la media (z-score → 0) o umbral de pérdida (stop en reversión de z-score):

Python — Lógica de salida
def check_exit(entry_z_score, current_z_score, entry_price):
# Toma de ganancias: el spread converge a la mitad del camino hacia la media
if abs(current_z_score) < abs(entry_z_score) * 0.5:
return SALIR, objetivo_de_ganancias
# Stop loss: z-score se movió en la dirección incorrecta por >1
si (entry_z_score > 0 y current_z_score < entry_z_score + 1.0):
devolver SALIR, stop_loss
elif (entry_z_score < 0 y current_z_score > entry_z_score - 1.0):
devolver SALIR, stop_loss
devolver MANTENER, None

Backtesting de Estrategias de Arbitraje Estadístico

Métricas clave para arbitraje estadístico:

Python — Estrategia de pares de backtest
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
for i in range(len(z_score)):
si position es None:
si z_score[i] > 2.0:
position = {"entry": spread[i], "z_entry": z_score[i], "idx": i}
else:
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
devolver pd.DataFrame(trades)

Añadiendo Inteligencia de Smart Money

Mejora el trading de pares filtrando operaciones con confirmación de Smart Money:

Python — Estrategia de pares filtrada
def smart_money_pairs_strategy(symbol1, symbol2, z_score):
# Verificar confirmación de Smart Money a nivel de par
sm1 = get_smart_money_signal(symbol1)
sm2 = get_smart_money_signal(symbol2)
# Si uno es MUY alcista y el otro MUY bajista = fuerte divergencia
# Buen momento para operar el spread
divergence_score = abs(sm1["composite"] - sm2["composite"])
si z_score > 2.0 y divergence_score > 0.3 y sm1["confidence"] != "VETO":
devolver "TRADE" # Señal de alta confianza
else:
devolver "SKIP" # Esperar alineación

Potencia el arbitraje estadístico con señales de pares de Smart Money

Filtra operaciones de reversión a la media con consenso de ballenas y datos de derivados. Nuestra API confirma la validez de la divergencia de pares con un 62% de mejora en precisión.

Empezar a Operar Pares →