Разработка алгоритма парной торговли (pairs trading)
Pairs trading — частный случай статистического арбитража: мы торгуем одной парой активов, открывая одновременно длинную позицию в одном и короткую в другом. Стратегия рыночно-нейтральна: прибыль не зависит от общего направления рынка, только от сужения/расширения спреда между двумя активами.
Выбор пар
Не все пары подходят для торговли. Требования:
Коинтеграция — статистически значимая (p-value < 0.05 по тесту Engle-Granger или Johansen). Ребалансировать и проверять каждые 2–4 недели: коинтеграция может исчезнуть.
Экономический смысл — пара должна иметь фундаментальную связь:
- BTC spot vs BTC perpetual futures
- ETH vs stETH (Lido staked ETH)
- Binance Coin (BNB) vs аналогичные биржевые токены
- Конкурирующие Layer-1: SOL vs AVAX, DOT vs ATOM
- Корзина DeFi-токенов (UNI, AAVE, CRV) против DeFi индекса
Ликвидность: оба актива должны иметь достаточный объём для исполнения без значительного slippage.
Half-life: период полувозврата к среднему. 3–30 дней — приемлемый диапазон. Слишком короткий — не успеем войти, слишком длинный — капитал заморожен надолго.
Механика сделки
Пример: BTC/USDT spot и BTCUSDT perpetual futures
Спред = BTC_PERP - BTC_SPOT
Basis = PERP_price - SPOT_price (обычно положительный из-за funding)
Если basis аномально высок (Z-score > 2): продаём PERP, покупаем SPOT. Ждём сужения. Profit = изменение basis.
Размер позиций: для рыночной нейтральности стоимость обеих позиций должна быть одинаковой (или взвешенной на hedge ratio β).
def calculate_position_sizes(capital, hedge_ratio, price_x, price_y):
# Dollar-neutral
position_value = capital / 2
qty_y = position_value / price_y # продаём Y
qty_x = qty_y * hedge_ratio # покупаем X
return qty_x, qty_y
Динамический hedge ratio
Фиксированный hedge ratio устаревает. Используем скользящее окно OLS или Kalman Filter для непрерывного обновления.
Важно: резкое изменение hedge ratio может означать структурный сдвиг в отношениях между активами. Мониторим стабильность β.
Риски парной торговли
Divergence risk: спред продолжает расширяться вместо сужения. Фундаментальная причина: один из активов меняется структурно (делистинг, hack, regulatory action). Stop-loss по Z-score = 3 или 4.
Funding risk: для perpetual позиций funding rate может съедать прибыль. Особенно при высоком положительном funding на PERP (вы платите как holder PERP short).
Liquidity risk: при неожиданном движении рынка закрыть обе ноги одновременно может быть затруднительно.
Correlation breakdown: особенно актуально для крипты — в периоды market-wide движений (BTC dump/pump) корреляции ломаются.
P&L расчёт и backtesting
def backtest_pairs(spread, z_scores, entry_z=2.0, exit_z=0.5, stop_z=3.5):
position = 0 # 1 = long spread, -1 = short spread
pnl = []
for i, (spread_val, z) in enumerate(zip(spread, z_scores)):
if position == 0:
if z > entry_z:
position = -1 # short spread
entry_spread = spread_val
elif z < -entry_z:
position = 1 # long spread
entry_spread = spread_val
elif position == 1:
current_pnl = spread_val - entry_spread
if z > -exit_z or z < -stop_z:
pnl.append(current_pnl)
position = 0
elif position == -1:
current_pnl = entry_spread - spread_val
if z < exit_z or z > stop_z:
pnl.append(current_pnl)
position = 0
return pnl
Мониторинг активных позиций
Каждые N минут пересчитываем Z-score и hedge ratio. Дашборд показывает:
- Текущий Z-score и его историю
- P&L текущей позиции
- Unrealized PnL по каждой ноге
- Funding payments (для perpetual)
- Time in position vs expected half-life
Алерт при приближении к stop-loss уровню или при резком изменении hedge ratio (>20% от предыдущего значения).
Стек: Python (statsmodels, numpy, pykalman), CCXT для исполнения ордеров, PostgreSQL для истории торгов, Grafana для мониторинга. Алгоритм работает как daemon-процесс с configurable параметрами через config-файл или UI.







