איסוף נתוני Open Interest מבורסות קריפטו: מדריך מלא
איסוף (גירוד) נתוני Open Interest מבורסות קריפטו הוא בעיה שלא ניתן לפתור באמצעות בקשת REST פשוטה. כל בורסה מחזירה OI ביחידות משלה: Binance בחוזים (BTC), Bybit בדולרים, OKX בחוזים עם דיוק חלקי. ללא נורמליזציה, OI מצטבר הוא חסר תועלת. אנו עוזרים לסוחרים ואנליסטים להפוך איסוף זה לאוטומטי תוך 1–2 שבועות, תוך התחשבות במגבלות קצב, עדיפות סמלים וסכימת אחסון אחידה. הניסיון של הצוות שלנו — מעל 50 פרויקטים של אנליטיקת DeFi — מראה שללא איסוף אוטומטי מרובה-בורסות, תמונת השוק מעוותת.
Open Interest הוא הנפח הכולל של פוזיציות פתוחות בחוזים עתידיים/אופציות (ויקיפדיה). זהו אינדיקטור מפתח לאנליטיקת נגזרים: עלייה חדה ב-OI במהלך ירידת מחיר מאותתת על שורטים חדשים; עלייה ב-OI במהלך עליית מחיר מאותתת על לונגים שמתווספים.
מדוע איסוף OI ממספר בורסות הוא משימה מורכבת?
ניתוח נתונים מכל בורסה דורש טיפול בפורמטים שונים, מגבלות קצב, והצורך לאחד את הכל. לאחר קריסת FTX, התברר שהסתמכות על פלטפורמה אחת מעוותת מדדים. רק איסוף מרובה-בורסות מספק תמונה אובייקטיבית.
מקורות נתונים והמאפיינים שלהם
בורסות נגזרים מרכזיות מפרסמות OI באמצעות REST ו-WebSocket APIs:
| בורסה | נקודת קצה | מאפיינים |
|---|---|---|
| Binance | GET /fapi/v1/openInterest (perp), /futures/data/openInterestHist (היסטוריה) |
היסטוריה רק ל-30 יום, גרנולריות 5 דקות/15 דקות/שעה |
| Bybit | GET /v5/market/open-interest |
פרמטר intervalTime: 5min, 15min, 30min, 1h, 4h, 1d |
| OKX | GET /api/v5/rubric/open-interest |
תומך בחוזים עתידיים, swap, אופציות |
| dYdX v4 | GraphQL API או Indexer REST | On-chain, נתונים ציבוריים ללא מפתחות |
| GMX v2 | On-chain דרך חוזה Reader |
אין API מרכזי |
כיצד לעקוף מגבלות קצב בעת איסוף OI?
לכל בורסה יש מגבלות קצב API. Binance fapi: 2400 weight/דקה, openInterest = 1 weight. Bybit: 600 בקשות/5 שניות. עם מספר גדול של סמלים (50+ זוגות), סקירה כל דקה פוגעת בקלות במגבלות.
אסטרטגיות:
- עדיפות סמלים: BTC ו-ETH כל דקה, 20 המובילים לפי נפח כל 5 דקות, אחרים כל 15–30 דקות.
- רוטציית IP: אם נפח הנתונים דורש יותר ממופע אחד של קולקטור, כל אחד משתמש ב-IP נפרד. השתמשו בפרוקסי מגורים או VPS שונים לבורסות שונות.
- WebSocket של הבורסה לעדכון מחירים: קבלו מחיר מ-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 ארכיטקטורת קולקטור
החלטה מרכזית: סקירה תקופתית מול WebSocket. רוב הבורסות מספקות OI רק דרך REST (OI אינו אות בתדר גבוה כמו מחיר). הגישה האופטימלית היא סקירה תקופתית מתוזמנת כל 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 ביחידות שונות. ללא המרה למכנה משותף, אגרגציה בלתי אפשרית. אנו משתמשים בדנומינציה בדולרים כסטנדרט.
- Binance BTCUSDT perp — ב-BTC (מספר חוזים × 1 BTC לחוזה)
- Bybit BTCUSDT — בדולרים (מטבע בסיס × מחיר)
- OKX BTC-USDT-SWAP — בחוזים (חוזה אחד = 0.01 BTC)
- CME Bitcoin Futures — בחוזים (חוזה אחד = 5 BTC)
כדי לקבל אגרגט השוואתי, אנו ממירים הכל לדולרים:
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 הוא אופטימלי לנתוני OI מסוג time-series. אנו מבטיחים ש-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% בשעה — פתיחת פוזיציה משמעותית; ירידת OI >10% בשעה — ליקווידציות או סגירה המונית.
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 בשילוב עם נתונים אחרים נותן תמונה מלאה יותר:
- יחס לונג/שורט — זמין ב-Binance (
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), Bybit. - שיעור מימון — עלות החזקת פוזיציית perpetual. מימון חיובי גבוה + OI גבוה = לונג מחומם יתר על המידה.
- מימון משוקלל OI — מימון ממוצע בכל הבורסות משוקלל לפי ה-OI שלהן.
תהליך ומה מקבלים
- אנליטיקה — אנו מנתחים את הדרישות שלכם, בוחרים בורסות וסמלים.
- עיצוב — אנו מפתחים ארכיטקטורת קולקטור, סכימת אחסון. עלות הפיתוח מחושבת באופן אישי לפי מספר הבורסות ותדירות האיסוף.
- יישום — אנו כותבים קוד, מגדירים מגבלות קצב ונורמליזציה.
- בדיקות — אנו מוודאים נכונות נתונים על מקרים היסטוריים ואמיתיים.
- פריסה — אנו פורסים את הפתרון בסביבה שלכם, דשבורד מוכן. הזמן שנחסך באיסוף נתונים ידני מקזז במהירות את ההשקעה.
פיתוח קולקטור ל-5–7 בורסות עם נורמליזציה, אחסון ואגרגטים בסיסיים: 1–2 שבועות. צינור אנליטיקה מלא עם התראות, API ודשבורד: 3–4 שבועות.
הפתרון הסופי כולל:
- קוד מקור של קולקטור Python אסינכרוני
- מיגרציות SQL ל-TimescaleDB
- דשבורד Grafana עם ויזואליזציה של OI, שיעור מימון, יחס לונג/שורט
- תיעוד ארכיטקטורה ותפעול
- הדרכת צוות וחודש תמיכה
הזמינו קולקטור מותאם אישית לצרכים שלכם. צרו קשר להערכה ראשונית של הפרויקט שלכם. קבלו פתרון סוהר עם אמינות מובטחת ונורמליזציה נכונה.
השוואת גישות: סקירת REST מול WebSocket
| קריטריון | סקירת REST | WebSocket |
|---|---|---|
| תדירות עדכון | 1–5 דקות | זמן אמת |
| עומס API | גבוה (תלוי במספר הסמלים) | נמוך (נתונים מגיעים דרך מינוי) |
| תמיכה ב-OI | כל הבורסות | לא כל הבורסות מספקות OI דרך WebSocket |
סקירת REST מתאימה יותר לאיסוף OI, מכיוון שרוב הבורסות אינן משדרות מדד זה בזמן אמת.
משאבים נוספים: Open Interest (ויקיפדיה), TimescaleDB.







