Парсинг даних з криптобірж
Біржі публічно не публікують історичні дані в зручному форматі — кожна надає REST API з різними обмеженнями та форматами, WebSocket для real-time потоків, і майже всі ставлять rate limits, які потрібно поважати щоб не отримати бан IP або API ключа. Задача парсингу даних з множини бірж зводиться до нормалізації різнорідних API в єдину схему при дотриманні rate limit політик.
Структура біржевих даних
Основні типи даних з біржи:
Order book (стакан): снапшот поточних bid/ask ордерів з обсягами. Корисний для аналізу ліквідності та spread. REST — снапшот, WebSocket — incremental updates (diff).
Trades (сделки): історія виконаних сделок. Кожна сделка: timestamp, price, amount, side (buy/sell). Основа для побудови OHLCV свічок.
OHLCV (свічи): агреговані дані за період. Більшість бірж надають напрямо через REST.
Funding rates (для perpetual контрактів): ставка фінансування, впливає на вартість утримання позиції. Для арбітражних стратегій між спотом та фьючерсами.
CCXT: унифікований доступ
CCXT (CryptoCurrency eXchange Trading) — Python/JavaScript/PHP бібліотека з унифікованим API до 100+ бірж. Правильне рішення для більшості задач — не писати біржові коннектори вручну.
import ccxt
import asyncio
async def fetch_ohlcv_all_exchanges(symbol: str, timeframe: str):
exchanges = [
ccxt.binance({'enableRateLimit': True}),
ccxt.coinbase({'enableRateLimit': True}),
ccxt.kraken({'enableRateLimit': True}),
ccxt.bybit({'enableRateLimit': True}),
]
results = {}
for exchange in exchanges:
try:
ohlcv = await exchange.fetch_ohlcv(symbol, timeframe, limit=500)
results[exchange.id] = [
{
'timestamp': candle[0],
'open': candle[1],
'high': candle[2],
'low': candle[3],
'close': candle[4],
'volume': candle[5],
}
for candle in ohlcv
]
except ccxt.RateLimitExceeded:
await asyncio.sleep(exchange.rateLimit / 1000)
except ccxt.NetworkError as e:
logger.error(f"{exchange.id}: network error: {e}")
return results
enableRateLimit: True активує вбудований rate limiter CCXT — автоматично throttle запити згідно задокументованих лімітів біржи.
Історичні дані: bulk download
Більшість бірж повертають максимум 500–1000 свічок за запит. Для завантаження довгої історії — ітеративні запити з пагінацією по часу:
async def download_full_history(
exchange: ccxt.Exchange,
symbol: str,
timeframe: str,
since_ms: int
) -> list:
all_candles = []
current_since = since_ms
while True:
candles = await exchange.fetch_ohlcv(
symbol, timeframe,
since=current_since,
limit=1000
)
if not candles:
break
all_candles.extend(candles)
last_timestamp = candles[-1][0]
if last_timestamp <= current_since:
break # захист від бесконечного циклу
current_since = last_timestamp + exchange.parse_timeframe(timeframe) * 1000
# Поважаємо rate limit
await asyncio.sleep(exchange.rateLimit / 1000)
return all_candles
Для Binance історичні дані доступні через Binance Data Vision (data.binance.vision) — bulk CSV файли за кожен день/місяць без rate limits. На порядки швидше ніж API. Аналоги: Bybit Public Data, OKX Market Data.
WebSocket для real-time даних
import websockets
import json
async def stream_binance_trades(symbol: str, callback):
uri = f"wss://stream.binance.com:9443/ws/{symbol.lower()}@trade"
async with websockets.connect(uri) as ws:
while True:
try:
msg = await asyncio.wait_for(ws.recv(), timeout=30)
data = json.loads(msg)
await callback({
'exchange': 'binance',
'symbol': symbol,
'timestamp': data['T'],
'price': float(data['p']),
'amount': float(data['q']),
'side': 'sell' if data['m'] else 'buy',
'trade_id': data['t'],
})
except asyncio.TimeoutError:
await ws.ping() # keepalive
Для production: автоматичний reconnect при розриві з'єднання, відстеження sequence numbers (Binance використовує u та U поля для gap detection в order book updates).
Зберігання та нормалізація
Для часових рядів — TimescaleDB (PostgreSQL розширення) або ClickHouse для аналітичних запитів. TimescaleDB автоматично розбиває таблиці по часу (hypertables), підтримує сжатие та materialized views для агрегацій:
CREATE TABLE trades (
time TIMESTAMPTZ NOT NULL,
exchange TEXT NOT NULL,
symbol TEXT NOT NULL,
price DOUBLE PRECISION NOT NULL,
amount DOUBLE PRECISION NOT NULL,
side TEXT NOT NULL,
trade_id TEXT
);
SELECT create_hypertable('trades', 'time');
CREATE INDEX ON trades (exchange, symbol, time DESC);
Нормалізація символів між біржами — типова проблема: BTC/USDT, BTCUSDT, BTC-USDT, XBT/USD — одна й та сама пара на різних біржах. CCXT вирішує це своєю маппінг-схемою (exchange.load_markets() повертає unified market IDs).
Rate limits та anti-ban
Біржі банять по IP при перевищенні rate limits. Стратегії:
- Ротація API ключів (кілька ключів одного аккаунту або кілька аккаунтів)
- Кешування — не запитувати одні дані кілька разів
- Пріоритизація WebSocket замість REST для real-time даних
- Exponential backoff при отриманні 429
Для масштабового сбору даних з десятків бірж одночасно — residential proxy rotation, але це грей-зона по ToS більшості бірж. Краще використовувати офіційні bulk data endpoints де вони існують.
Розробка парсера з підтримкою 5–10 бірж, нормалізацією в єдину схему, real-time WebSocket потоками та зберіганням в TimescaleDB — 3–4 тижні.







