Разработка модели прогнозирования ликвидности
Ликвидность крипторынка — не константа. Она резко падает в периоды рыночного стресса, в нерабочие часы, при аномальных событиях. Модель прогнозирования ликвидности позволяет алгоритмическим системам адаптировать стратегию: изменять размер ордеров, расширять спреды, откладывать исполнение.
Метрики ликвидности
Bid-Ask Spread: простейшая метрика ликвидности. Узкий спред = высокая ликвидность.
Relative Spread = (Ask - Bid) / Mid × 100%
Market Depth: суммарный объём в стакане на N% от mid-price. Глубокий стакан выдержит крупный ордер без сильного slippage.
Amihud Illiquidity Ratio: измеряет ценовое движение на единицу объёма:
def amihud_ratio(returns, volumes, window=24):
"""
Высокое значение = большое движение цены при малом объёме = низкая ликвидность
"""
illiquidity = np.abs(returns) / (volumes + 1e-8)
return illiquidity.rolling(window).mean()
Kyle's Lambda (price impact): регрессия изменения цены на order flow:
def kyles_lambda(price_changes, order_flow, window=100):
"""
λ = Cov(ΔP, OF) / Var(OF)
Высокое λ = большой price impact = низкая ликвидность
"""
lambdas = []
for i in range(window, len(price_changes)):
dp = price_changes[i-window:i]
of = order_flow[i-window:i]
cov = np.cov(dp, of)[0, 1]
var = np.var(of)
lambdas.append(cov / max(var, 1e-10))
return lambdas
Факторы ликвидности
Временны́е паттерны:
- Суточный цикл: 14:00–22:00 UTC (перекрытие европейской и американской сессий) — максимальная ликвидность
- Выходные дни — ниже ликвидность на 20–30%
- Праздники — особенно низкая ликвидность
Market regime:
- High volatility periods → маркет-мейкеры расширяют спреды или уходят
- Trending market → ликвидность асимметрична (хуже на стороне тренда)
Cross-asset effects:
- При падении BTC ликвидность всего рынка ухудшается
- Стрессовые события (hack, regulatory) → резкое ухудшение
Модель прогнозирования
import lightgbm as lgb
import pandas as pd
import numpy as np
def create_liquidity_features(df, spread_col='spread', depth_col='depth_1pct'):
features = pd.DataFrame(index=df.index)
# Временны́е features
features['hour'] = df.index.hour
features['day_of_week'] = df.index.dayofweek
features['is_weekend'] = (features['day_of_week'] >= 5).astype(int)
features['hour_sin'] = np.sin(2 * np.pi * features['hour'] / 24)
features['hour_cos'] = np.cos(2 * np.pi * features['hour'] / 24)
# Lagged ликвидность
for lag in [1, 4, 12, 24, 48]:
features[f'spread_lag_{lag}'] = df[spread_col].shift(lag)
if depth_col in df.columns:
features[f'depth_lag_{lag}'] = df[depth_col].shift(lag)
# Rolling statistics
for window in [12, 24, 72]:
features[f'spread_ma_{window}'] = df[spread_col].rolling(window).mean()
features[f'spread_std_{window}'] = df[spread_col].rolling(window).std()
# Волатильность (прокси ликвидности)
returns = df['close'].pct_change() if 'close' in df.columns else pd.Series(index=df.index)
for window in [12, 24]:
features[f'vol_{window}h'] = returns.rolling(window).std()
# Объём
if 'volume' in df.columns:
features['vol_ratio'] = df['volume'] / df['volume'].rolling(24).mean()
# Amihud ratio
if 'close' in df.columns and 'volume' in df.columns:
features['amihud'] = amihud_ratio(returns, df['volume'])
return features.dropna()
def train_liquidity_model(liquidity_df, target_col='spread', horizon=4):
"""
Предсказываем спред/ликвидность через horizon периодов
"""
X = create_liquidity_features(liquidity_df)
y = liquidity_df[target_col].shift(-horizon) # future spread
# Walk-forward split
split_idx = int(len(X) * 0.8)
X_train, X_test = X.iloc[:split_idx], X.iloc[split_idx:]
y_train, y_test = y.iloc[:split_idx], y.iloc[split_idx:]
# Убираем NaN из target
valid_mask = y_train.notna()
model = lgb.LGBMRegressor(
n_estimators=500,
learning_rate=0.05,
num_leaves=31,
early_stopping_rounds=50
)
model.fit(
X_train[valid_mask], y_train[valid_mask],
eval_set=[(X_test, y_test.fillna(method='ffill'))],
callbacks=[lgb.early_stopping(50), lgb.log_evaluation(100)]
)
return model
Оценка market impact
Перед исполнением крупного ордера — прогноз его влияния на цену:
def estimate_market_impact(order_size_usd, current_depth,
current_spread, lambda_estimate):
"""
Simplified Almgren-Chriss model для market impact
"""
# Временны́й impact (исчезает быстро)
temporary_impact = lambda_estimate * np.sqrt(order_size_usd)
# Постоянный impact (market information)
permanent_impact = 0.5 * temporary_impact # обычно 50% от temporary
# Spread cost
spread_cost = current_spread / 2 * order_size_usd
total_cost = (temporary_impact + permanent_impact + spread_cost)
total_cost_bps = total_cost / order_size_usd * 10000 # в basis points
return {
'total_impact_usd': total_cost,
'total_impact_bps': total_cost_bps,
'temporary': temporary_impact,
'permanent': permanent_impact,
'spread_cost': spread_cost,
'optimal_execution': total_cost_bps > 10 # нужен TWAP/VWAP
}
Liquidity forecasting в production
Realtime обновление: прогноз ликвидности пересчитывается каждые 15 минут на следующие 4 часа.
Integration с исполнением: перед запуском крупного ордера — проверяем прогноз ликвидности. Если прогнозируется снижение (например, через 2 часа приближается конец рабочего дня в США) — ускоряем исполнение сейчас.
Adaptive spreads для маркет-мейкинга: при прогнозе ухудшения ликвидности — автоматически расширяем котируемый спред.
Разрабатываем модель прогнозирования ликвидности с временны́ми features, lagged spread/depth, market regime учётом, market impact estimation (Almgren-Chriss) и integration с execution алгоритмами.







