Інтеграція з провайдерами ліквідності
Liquidity provider (LP) інтеграція — це підключення зовнішніх джерел ліквідності до вашої торговельної платформи. Замість того щоб чекати органічних маркет-мейкерів або будувати власний MM-бот з нуля, платформа підключається до професійних LP, які надають двосторонні котировки по API.
Типи провайдерів ліквідності
Prime Brokers
Інституціональні LP: Cumberland (DRW), Wintermute, Jump Crypto, B2C2, Galaxy Digital. Надають конкурентні котировки на великі обсяги через FIX або REST/WebSocket API.
Вимоги: KYB, мінімальний місячний обсяг ($1M+), правовий договір, іноді депозит.
Aggregated Liquidity APIs
B2Broker, FXCM Crypto, Leverate — провайдери агрегованої ліквідності доступні без інституціональних вимог. Підходять для малих/середніх бірж.
DEX/AMM як источник ліквідності
Для крипто-платформ: агрегація ліквідності з Uniswap, Curve, Balancer через 0x Protocol API або 1inch Fusion. Корисно для long-tail токенів.
API інтеграція
REST API інтеграція (приклад B2Broker)
import httpx
from decimal import Decimal
import asyncio
class B2BrokerLPClient:
def __init__(self, api_key: str, api_secret: str, base_url: str):
self.api_key = api_key
self.api_secret = api_secret
self.base_url = base_url
self.client = httpx.AsyncClient()
async def get_quote(
self,
symbol: str,
side: str,
quantity: Decimal
) -> LPQuote:
payload = {
'symbol': symbol,
'side': side.upper(),
'quantity': str(quantity)
}
headers = self._sign_request(payload)
response = await self.client.post(
f"{self.base_url}/v1/quote",
json=payload,
headers=headers
)
data = response.json()
return LPQuote(
provider='b2broker',
symbol=symbol,
side=side,
price=Decimal(str(data['price'])),
quantity=Decimal(str(data['quantity'])),
quote_id=data['quoteId'],
expires_in_ms=data['expiresIn']
)
async def execute_quote(self, quote_id: str) -> LPExecution:
response = await self.client.post(
f"{self.base_url}/v1/execute",
json={'quoteId': quote_id},
headers=self._sign_request({'quoteId': quote_id})
)
data = response.json()
return LPExecution(
execution_id=data['executionId'],
fill_price=Decimal(str(data['fillPrice'])),
fill_quantity=Decimal(str(data['fillQuantity'])),
status=data['status']
)
WebSocket трансляція котировок
Для реалтайм ринкових даних від LP:
class LPWebSocketFeed:
async def subscribe(self, symbols: list[str]):
async with websockets.connect(self.ws_url) as ws:
# Авторизація
await ws.send(json.dumps({
'type': 'auth',
'apiKey': self.api_key,
'signature': self.generate_signature()
}))
# Підписка на котировки
await ws.send(json.dumps({
'type': 'subscribe',
'channels': ['quotes'],
'symbols': symbols
}))
async for message in ws:
data = json.loads(message)
if data['type'] == 'quote':
await self.on_quote(LPQuote(
provider=self.provider_name,
symbol=data['symbol'],
bid=Decimal(data['bid']),
ask=Decimal(data['ask']),
bid_size=Decimal(data['bidSize']),
ask_size=Decimal(data['askSize']),
timestamp=data['timestamp']
))
Агрегація кількох провайдерів
class LiquidityAggregator:
def __init__(self, providers: list[BaseLPClient]):
self.providers = providers
self.quotes: dict[str, list[LPQuote]] = {}
def on_quote_update(self, quote: LPQuote):
"""Оновлюємо котировку від конкретного провайдера"""
symbol = quote.symbol
if symbol not in self.quotes:
self.quotes[symbol] = []
# Убираємо стару котировку цього провайдера
self.quotes[symbol] = [
q for q in self.quotes[symbol]
if q.provider != quote.provider
]
self.quotes[symbol].append(quote)
def get_best_bid_ask(self, symbol: str) -> BestBidAsk:
quotes = self.quotes.get(symbol, [])
valid = [q for q in quotes if not q.is_stale()]
if not valid:
return None
best_bid = max(valid, key=lambda q: q.bid)
best_ask = min(valid, key=lambda q: q.ask)
return BestBidAsk(
bid=best_bid.bid,
bid_size=best_bid.bid_size,
bid_provider=best_bid.provider,
ask=best_ask.ask,
ask_size=best_ask.ask_size,
ask_provider=best_ask.provider,
spread_bps=int((best_ask.ask - best_bid.bid) / best_bid.bid * 10000)
)
Smart Order Routing (SOR)
SOR вибирає оптимального провайдера для кожного конкретного ордера:
class SmartOrderRouter:
def route(self, order: ClientOrder, aggregator: LiquidityAggregator) -> RoutingPlan:
available = aggregator.get_all_quotes(order.symbol)
if order.type == 'market':
return self.route_market(order, available)
elif order.type == 'limit':
return self.route_limit(order, available)
def route_market(self, order: ClientOrder, quotes: list[LPQuote]) -> RoutingPlan:
"""TWAP-стиль: виконуємо через найкращого провайдера, дробимо при нехватці обсягу"""
remaining = order.quantity
plan = []
# Сортуємо по ціні (краща спочатку)
sorted_quotes = sorted(
quotes,
key=lambda q: q.ask if order.side == 'buy' else -q.bid
)
for quote in sorted_quotes:
if remaining <= 0:
break
fill_qty = min(remaining, quote.ask_size if order.side == 'buy' else quote.bid_size)
plan.append(RoutingLeg(
provider=quote.provider,
quantity=fill_qty,
expected_price=quote.ask if order.side == 'buy' else quote.bid
))
remaining -= fill_qty
if remaining > 0:
raise InsufficientLiquidity(f"Could not route full order, {remaining} remaining")
return RoutingPlan(legs=plan, total_quantity=order.quantity)
Failover та Resilience
LP можуть відключитися, розширити спреди, ввести обмеження. Resilient інтеграція це ongoing engineering: провайдери оновлюють API, змінюють умови, мають outage. Моніторинг якості fills показує реальну якість ліквідності.







