Сбор (скрапинг) данных 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.







