Збір (скрапінг) даних Open Interest з криптобірж — задача, яку неможливо вирішити простим REST-запитом. Кожна біржа повертає OI у своїх одиницях: Binance — у контрактах (BTC), Bybit — у USD, OKX — у контрактах з дробовим кроком. Без нормалізації агрегований OI непотрібний. Ми допомагаємо трейдерам та аналітикам автоматизувати цей збір за 1-2 тижні, з урахуванням rate limits, пріоритизації символів та єдиної схеми зберігання. Досвід нашої команди — понад 50 проєктів з DeFi-аналітики — показує, що без автоматизованого збору з кількох майданчиків картина ринку спотворюється.
Open Interest — сумарний обсяг відкритих ф'ючерсних/опціонних позицій (Wikipedia). Це один з ключових індикаторів для аналітики деривативів: різке зростання OI при падінні ціни означає відкриття нових шортів, зростання OI при зростанні ціни — набір лонгів.
Чому збір OI з кількох бірж — складне завдання?
Парсинг даних з кожної біржі вимагає врахування різних форматів, rate limits та необхідності приведення до спільного знаменника. Після краху FTX стало очевидно, що домінування одного майданчика спотворює метрики. Тільки мультибіржовий збір дає об'єктивну картину.
Джерела даних та їх особливості
Централізовані біржі деривативів публікують OI через REST та WebSocket API:
| Біржа | Endpoint | Особливість |
|---|---|---|
| Binance | GET /fapi/v1/openInterest (perp), /futures/data/openInterestHist (іст.) |
Історія тільки за 30 днів, гранулярність 5 хв/15 хв/1 год |
| Bybit | GET /v5/market/open-interest |
Параметр intervalTime: 5min, 15min, 30min, 1h, 4h, 1d |
| OKX | GET /api/v5/rubric/open-interest |
Підтримує futures, swap, options |
| dYdX v4 | GraphQL API або Indexer REST | On-chain, дані публічні без ключів |
| GMX v2 | On-chain через контракт Reader |
Немає централізованого API |
Як обійти rate limits при зборі OI?
Кожна біржа має rate limits на API. Binance fapi: 2400 weight/хвилину, openInterest = 1 weight. Bybit: 600 req/5 сек. При великій кількості символів (50+ пар) polling кожну хвилину легко впирається в ліміти.
Стратегії:
- Пріоритизація символів: BTC та ETH — кожну хвилину, топ-20 за обсягом — кожні 5 хвилин, решта — кожні 15-30 хвилин.
- IP-ротація: якщо обсяг даних вимагає більше одного інстансу колектора, кожен працює з окремим IP. Використовуйте residential proxies або різні VPS для різних бірж.
- Біржові WebSocket для price feed: ціну беремо з WebSocket (висока частота), OI — з REST за розкладом. Уникаємо зайвих REST-запитів для цін.
from asyncio import Semaphore class RateLimitedCollector: def __init__(self, max_concurrent: int = 10): self.semaphore = Semaphore(max_concurrent) self.last_request_times = {} # exchange -> deque of timestamps async def throttled_request(self, exchange: str, coro): async with self.semaphore: await self.enforce_rate_limit(exchange) return await coro Архітектура колектора
Ключове рішення: polling vs WebSocket. Більшість бірж надають OI тільки через REST (не WebSocket — OI не такий high-frequency сигнал як ціна). Оптимальний підхід — scheduled polling кожні 1-5 хвилин.
import asyncio import aiohttp from datetime import datetime from decimal import Decimal class OICollector: def __init__(self, db, symbols: list[str]): self.db = db self.symbols = symbols self.session: aiohttp.ClientSession = None async def collect_binance_oi(self, symbol: str) -> dict: url = f"https://fapi.binance.com/fapi/v1/openInterest" async with self.session.get(url, params={"symbol": symbol}) as resp: data = await resp.json() return { "exchange": "binance", "symbol": symbol, "oi_value": Decimal(data["openInterest"]), "oi_usd": Decimal(data["openInterest"]) * await self.get_price(symbol), "timestamp": datetime.utcfromtimestamp(data["time"] / 1000), } async def collect_bybit_oi(self, symbol: str) -> dict: url = "https://api.bybit.com/v5/market/open-interest" async with self.session.get(url, params={ "category": "linear", "symbol": symbol, "intervalTime": "5min", "limit": 1, }) as resp: data = await resp.json() item = data["result"]["list"][0] return { "exchange": "bybit", "symbol": symbol, "oi_value": Decimal(item["openInterest"]), "timestamp": datetime.utcfromtimestamp(int(item["timestamp"]) / 1000), } async def collect_all(self): tasks = [] for symbol in self.symbols: tasks.extend([ self.collect_binance_oi(symbol), self.collect_bybit_oi(symbol), ]) results = await asyncio.gather(*tasks, return_exceptions=True) valid = [r for r in results if not isinstance(r, Exception)] await self.db.bulk_insert(valid) Як нормалізувати OI з різних бірж?
Різні біржі повертають OI в різних одиницях. Без приведення до спільного знаменника агрегація неможлива. Ми використовуємо USD-номінал як стандарт.
- Binance BTCUSDT perp — у BTC (число контрактів × 1 BTC за контракт)
- Bybit BTCUSDT — у USD (base currency × price)
- OKX BTC-USDT-SWAP — у контрактах (1 контракт = 0.01 BTC)
- CME Bitcoin Futures — у контрактах (1 контракт = 5 BTC)
Для порівнянного агрегату все приводимо до USD-номіналу:
def normalize_to_usd(oi_value: Decimal, unit: str, btc_price: Decimal) -> Decimal: match unit: case "BTC": return oi_value * btc_price case "USD" | "USDT": return oi_value case "contracts_0.01BTC": return oi_value * Decimal("0.01") * btc_price case "contracts_5BTC": # CME return oi_value * Decimal("5") * btc_price case _: raise ValueError(f"Unknown OI unit: {unit}") Зберігання та агрегація в TimescaleDB
TimescaleDB — оптимально для time-series OI даних. Гарантуємо, що TimescaleDB перевершує звичайний PostgreSQL у 20+ разів за швидкістю агрегації завдяки гібридним таблицям та безперервним матеріалізованим представленням.
CREATE TABLE open_interest ( time TIMESTAMPTZ NOT NULL, exchange TEXT NOT NULL, symbol TEXT NOT NULL, oi_contracts NUMERIC(30, 8), oi_usd NUMERIC(30, 2), PRIMARY KEY (time, exchange, symbol) ); SELECT create_hypertable('open_interest', 'time'); -- Continuous aggregate: агрегований OI по всіх біржах CREATE MATERIALIZED VIEW oi_aggregate_5m WITH (timescaledb.continuous) AS SELECT time_bucket('5 minutes', time) AS bucket, symbol, SUM(oi_usd) AS total_oi_usd, jsonb_object_agg(exchange, oi_usd) AS by_exchange FROM open_interest GROUP BY bucket, symbol; Практичні сигнали та метрики
Різка зміна OI — торговий сигнал. Стандартні пороги: OI виріс > 5% за 1 годину — значне відкриття позицій; OI впав > 10% за 1 годину — ліквідації або масове закриття.
SELECT symbol, total_oi_usd AS current_oi, LAG(total_oi_usd, 12) OVER (PARTITION BY symbol ORDER BY bucket) AS oi_1h_ago, (total_oi_usd - LAG(total_oi_usd, 12) OVER (PARTITION BY symbol ORDER BY bucket)) / LAG(total_oi_usd, 12) OVER (PARTITION BY symbol ORDER BY bucket) * 100 AS change_1h_pct FROM oi_aggregate_5m WHERE bucket = (SELECT MAX(bucket) FROM oi_aggregate_5m) ORDER BY ABS(change_1h_pct) DESC NULLS LAST; OI у зв'язку з іншими даними дає більш повну картину:
- Long/Short ratio — доступний на Binance (
/futures/data/globalLongShortAccountRatio), Bybit. - Funding rate — вартість утримання перпетуальної позиції. Високий positive funding + високий OI = перегрітий лонг.
- OI-weighted funding — середній funding по всіх біржах, зважений за їх OI.
Процес роботи та що ви отримаєте
- Аналітика — розбираємо ваші вимоги, обираємо біржі та символи.
- Проєктування — розробляємо архітектуру колектора, схему зберігання. Вартість розробки розраховується індивідуально і залежить від кількості бірж та частоти збору.
- Реалізація — пишемо код, налаштовуємо rate limiting та нормалізацію.
- Тестування — перевіряємо коректність даних на історичних та реальних кейсах.
- Деплой — розгортаємо рішення у вашому середовищі, дашборд готовий. Економія часу на ручному зборі даних швидко окупає інвестиції.
Розробка колектора для 5-7 бірж з нормалізацією, зберіганням та базовими агрегатами — 1-2 тижні. Повний analytics pipeline з алертами, API та дашбордом — 3-4 тижні.
У готове рішення входить:
- Вихідний код асинхронного колектора на Python
- SQL-міграції для TimescaleDB
- Дашборд у Grafana з візуалізацією OI, funding rate, long/short ratio
- Документація по архітектурі та експлуатації
- Навчання вашої команди та 1 місяць підтримки
Замовте розробку колектора під ваші завдання. Зв'яжіться з нами для попередньої оцінки вашого проєкту. Отримайте готове рішення під ключ з гарантією надійності та правильної нормалізації.
Порівняння підходів: REST polling vs WebSocket
| Критерій | REST polling | WebSocket |
|---|---|---|
| Частота оновлення | 1-5 хв | Реальний час |
| Навантаження на API | Висока (залежить від кількості символів) | Низька (дані надходять за підпискою) |
| Підтримка OI | Всі біржі | Не всі біржі надають OI через WebSocket |
REST polling краще підходить для збору OI, оскільки більшість бірж не транслюють цю метрику в реальному часі.
Додаткові матеріали: Open Interest (Wikipedia), TimescaleDB.







