Разработка ликвидности биржи (market making)
Ликвидность — это готовность рынка исполнить ордер без значительного изменения цены. Биржа без ликвидности мертва: широкий спред, глубокий impact, уход трейдеров к конкурентам. Market making — это искусство и инженерия одновременно: нужно постоянно держать двусторонние котировки, хеджировать риски и не потерять деньги на этом.
Что такое market making
Market maker выставляет одновременно bid (покупка) и ask (продажа) ордера. Его заработок — spread между ними. При торговле против него он берёт на себя inventory risk (позицию в активе).
Market Maker Book для BTC/USDT:
Ask $50,100 │ 0.5 BTC
Ask $50,050 │ 0.3 BTC
Mid $50,000 │
Bid $49,950 │ 0.3 BTC
Bid $49,900 │ 0.5 BTC
Spread = Ask_best - Bid_best = $50,050 - $49,950 = $100 (0.2%)
Архитектура market making бота
Базовая стратегия
class MarketMaker:
def __init__(self, symbol: str, config: MMConfig):
self.symbol = symbol
self.spread_bps = config.spread_bps # половина спреда в bps
self.order_size_base = config.order_size # базовый размер ордера
self.num_layers = config.num_layers # глубина котирования
self.layer_spacing_bps = config.layer_spacing # расстояние между уровнями
async def compute_quotes(self, mid_price: float) -> list[Quote]:
quotes = []
inventory_skew = self.calculate_inventory_skew()
for i in range(1, self.num_layers + 1):
# Сдвигаем котировки с учётом инвентаря
bid_offset_bps = self.spread_bps * i + inventory_skew
ask_offset_bps = self.spread_bps * i - inventory_skew
bid_price = mid_price * (1 - bid_offset_bps / 10000)
ask_price = mid_price * (1 + ask_offset_bps / 10000)
# Размер ордера уменьшается на дальних уровнях
size = self.order_size_base / i
quotes.append(Quote('buy', bid_price, size))
quotes.append(Quote('sell', ask_price, size))
return quotes
def calculate_inventory_skew(self) -> float:
"""
Если у нас накопился избыток BTC (long inventory) —
сдвигаем котировки вниз: более агрессивный ask, менее агрессивный bid.
Это побуждает рынок покупать у нас BTC, восстанавливая баланс.
"""
target_inventory = 0 # нейтральная позиция
current_inventory = self.get_current_inventory()
inventory_deviation = current_inventory - target_inventory
# Skew пропорционален отклонению от нейтрали
skew = inventory_deviation * self.inventory_skew_factor
return max(-self.max_skew_bps, min(self.max_skew_bps, skew))
Хеджирование (delta hedging)
Market maker на внутренней бирже хеджирует позицию на внешней. Если клиент купил у нас 1 BTC — мы покупаем 1 BTC на Binance для нейтрализации delta:
async def hedge_trade(self, trade: InternalTrade):
"""Хеджируем исполненную сделку на внешней бирже"""
hedge_side = 'buy' if trade.side == 'sell' else 'sell'
# trade.side = что сделал клиент. Если клиент купил — мы продали → нужно хеджировать покупкой
await self.hedge_exchange.market_order(
symbol=self.symbol,
side=hedge_side,
quantity=trade.quantity
)
Execution risk: между нашей сделкой с клиентом и хеджем на внешней бирже проходит время (1-100ms). За это время цена может сдвинуться. Это execution risk или hedging slippage — реальный риск P&L.
Inventory management
Ключевая метрика — inventory skew: насколько текущая позиция отклонилась от цели (обычно нейтральной).
def get_inventory_metrics(self) -> dict:
current_pos = self.get_position_btc() # положительный = long, отрицательный = short
pos_value_usd = current_pos * self.get_mid_price()
return {
"position_btc": current_pos,
"position_usd": pos_value_usd,
"max_inventory_usd": self.config.max_inventory_usd,
"utilization": abs(pos_value_usd) / self.config.max_inventory_usd,
"pnl_unrealized": self.calculate_unrealized_pnl(current_pos)
}
При превышении лимитов инвентаря: стратегия агрессивно сдвигает котировки для снижения позиции, в крайнем случае — принудительный market ордер на внешней бирже.
Spread определение
Компоненты спреда
Минимально разумный спред состоит из:
Spread = Cost of carry + Expected adverse selection + Profit margin
Cost of carry = funding_rate × holding_period
Adverse selection = вероятность торговать против informed trader
Profit margin = желаемый доход на объём
Adverse selection — самая сложная часть. Если трейдер торгует против вас с инсайдерской информацией (знает, что цена скоро вырастет), вы всегда будете на проигрышной стороне. Эмпирически: в криптовалюте adverse selection выше при высокой волатильности, перед крупными событиями (FED заседания, хэлвинги).
Динамический спред
def calculate_dynamic_spread(self) -> float:
base_spread = self.config.base_spread_bps
# Расширяем спред при высокой волатильности
volatility = self.get_realized_volatility_1h()
vol_multiplier = max(1.0, volatility / self.baseline_volatility)
# Расширяем перед важными событиями
event_factor = 1.5 if self.is_event_window() else 1.0
# Расширяем при низкой ликвидности на хедж-бирже
hedge_spread = self.get_hedge_exchange_spread()
hedge_factor = max(1.0, hedge_spread / self.baseline_hedge_spread)
return base_spread * vol_multiplier * event_factor * hedge_factor
Liquidity provider программа
Стимулирование внешних market makers
Биржа может привлекать внешних market makers через fee rebate программу:
| Tier | Maker объём/30d | Maker fee | Taker fee |
|---|---|---|---|
| Standard | < $1M | 0.10% | 0.15% |
| Market Maker 1 | $1M+ | -0.01% (rebate) | 0.10% |
| Market Maker 2 | $10M+ | -0.02% (rebate) | 0.08% |
| Market Maker 3 | $100M+ | -0.03% (rebate) | 0.06% |
Негативный maker fee (rebate) означает, что биржа платит market maker-у за каждый выставленный и исполненный ордер. Это стандартная практика для привлечения профессиональных liquidity providers.
Performance requirements
Market maker обязуется поддерживать минимальное качество ликвидности:
def check_mm_performance(self, mm_id: str, period_minutes: int = 60) -> MMScore:
quotes = self.db.get_mm_quotes(mm_id, period_minutes)
# Uptime: % времени, когда MM держал активные bid и ask
total_seconds = period_minutes * 60
active_seconds = sum(q.duration for q in quotes if q.has_both_sides)
uptime = active_seconds / total_seconds
# Spread quality: средний спред MM относительно best mid
avg_spread = statistics.mean(q.spread_bps for q in quotes)
# Depth: средний размер ордеров
avg_depth_usd = statistics.mean(q.total_depth_usd for q in quotes)
return MMScore(
uptime=uptime, # требование: >80%
avg_spread_bps=avg_spread, # требование: <50bps
avg_depth_usd=avg_depth_usd # требование: >$10,000
)
При несоблюдении требований — понижение тира или временное отключение rebate.
On-chain AMM liquidity
Для DEX или гибридных платформ ликвидность предоставляется через LP-позиции в AMM пулах. Разница в экономике:
| Параметр | CEX Market Making | AMM LP |
|---|---|---|
| Контроль над ценой | Полный | Алгоритмический |
| Impermanent loss | Нет (хеджируется) | Есть |
| Требования к инфраструктуре | Бот + API | Просто транзакция |
| Управление риском | Активное | Пассивное |
| Доходность | Выше (активная) | Ниже (пассивная) |
Для серьёзного рыночного объёма CEX market making несопоставимо эффективнее AMM LP. AMM хорошо работает как backstop ликвидность и для long-tail токенов без профессиональных MM.







