Розроблення індикатора Open Interest
Open Interest (OI) — це суммарна кількість відкритих позицій по фьючерсних контрактах. На відміну від обсягу (який рахує кожну сделку), OI показує скільки позицій залишаються відкритими. Ріст OI = нові гроші входять на ринок. Падіння OI = позиції закриваються. Це один з небагатьох дійсно ведучих індикаторів.
Інтерпретація Open Interest
| Ціна | OI | Інтерпретація |
|---|---|---|
| Росте | Росте | Сильний восходящий тренд (нові лонги відкриваються) |
| Росте | Падає | Слабий ріст (шорти закриваються, не нові лонги) |
| Падає | Росте | Сильний нисходящий тренд (нові шорти) |
| Падає | Падає | Слабке падіння (лонги закриваються, не нові шорти) |
Високий OI + різкий рух = риск великої liquidation cascade. Саме так відбуваються найжорстокіші дампи: накопичені шорти або лонги ліквідуються ланцюговою реакцією.
Отримання даних OI
Binance Futures API
import httpx
from decimal import Decimal
import asyncio
class OpenInterestCollector:
BINANCE_FUTURES = "https://fapi.binance.com"
BYBIT_API = "https://api.bybit.com"
async def get_binance_oi(self, symbol: str) -> dict:
"""Поточний OI та історичні дані"""
async with httpx.AsyncClient() as client:
# Поточний OI
current = await client.get(
f"{self.BINANCE_FUTURES}/fapi/v1/openInterest",
params={"symbol": symbol}
)
current_data = current.json()
# Історичний OI (до 500 точок по 5-хвилинних інтервалах)
history = await client.get(
f"{self.BINANCE_FUTURES}/futures/data/openInterestHist",
params={
"symbol": symbol,
"period": "5m",
"limit": 500
}
)
history_data = history.json()
return {
"current_oi": float(current_data["openInterest"]),
"current_oi_usd": float(current_data["openInterest"]) * self.get_price(symbol),
"history": [
{
"time": h["timestamp"],
"oi": float(h["sumOpenInterest"]),
"oi_usd": float(h["sumOpenInterestValue"])
}
for h in history_data
]
}
async def get_aggregated_oi(self, symbol: str) -> dict:
"""Агрегуємо OI зі всіх бірж для єдиного погляду"""
tasks = [
self.get_binance_oi(symbol),
self.get_bybit_oi(symbol),
self.get_okx_oi(symbol),
]
results = await asyncio.gather(*tasks, return_exceptions=True)
total_oi_usd = sum(
r.get("current_oi_usd", 0)
for r in results
if not isinstance(r, Exception)
)
return {
"total_oi_usd": total_oi_usd,
"by_exchange": {
"binance": results[0].get("current_oi_usd", 0) if not isinstance(results[0], Exception) else 0,
"bybit": results[1].get("current_oi_usd", 0) if not isinstance(results[1], Exception) else 0,
"okx": results[2].get("current_oi_usd", 0) if not isinstance(results[2], Exception) else 0,
}
}
OI Change Rate індикатор
Швидкість зміни OI часто важливіша за абсолютне значення:
def calculate_oi_change_rate(oi_history: list[dict], window: int = 12) -> list[dict]:
"""
OI Change Rate: % зміна OI за останні N періодів.
Аномальний ріст → потенціальна liquidation подія.
"""
result = []
for i in range(window, len(oi_history)):
current_oi = oi_history[i]['oi_usd']
past_oi = oi_history[i - window]['oi_usd']
change_rate = (current_oi - past_oi) / past_oi * 100
# Позначка аномалії: зміна > 2 стандартних відхилення
all_changes = [
(oi_history[j]['oi_usd'] - oi_history[j-window]['oi_usd']) / oi_history[j-window]['oi_usd'] * 100
for j in range(window, i+1)
]
mean_change = sum(all_changes) / len(all_changes)
std_change = (sum((x - mean_change)**2 for x in all_changes) / len(all_changes)) ** 0.5
z_score = (change_rate - mean_change) / std_change if std_change > 0 else 0
result.append({
'time': oi_history[i]['time'],
'oi': current_oi,
'change_rate': change_rate,
'z_score': z_score,
'is_anomaly': abs(z_score) > 2.0
})
return result
Liquidation Heatmap
Комбінування OI з цінними рівнями дозволяє будувати liquidation heatmap — карту рівнів, де сконцентровані liquidation ордери:
def estimate_liquidation_levels(
open_positions: list[dict], # дані про позиції (середній leverage, сторона)
current_price: float
) -> dict:
"""
Оцінюємо цінові рівні ліквідацій.
Джерело даних: біржи іноді публікують агреговані дані про рівні позицій.
"""
long_liquidations = {}
short_liquidations = {}
for position in open_positions:
if position['side'] == 'long':
liq_price = position['avg_entry'] * (1 - 1/position['leverage'] + 0.005)
bucket = round(liq_price / 100) * 100 # групуємо по $100
long_liquidations[bucket] = long_liquidations.get(bucket, 0) + position['size_usd']
else:
liq_price = position['avg_entry'] * (1 + 1/position['leverage'] - 0.005)
bucket = round(liq_price / 100) * 100
short_liquidations[bucket] = short_liquidations.get(bucket, 0) + position['size_usd']
return {
"long_liquidation_levels": long_liquidations, # нижче поточної ціни
"short_liquidation_levels": short_liquidations, # вище поточної ціни
"largest_long_liq": max(long_liquidations.items(), key=lambda x: x[1]) if long_liquidations else None,
"largest_short_liq": max(short_liquidations.items(), key=lambda x: x[1]) if short_liquidations else None
}
Коресиляція OI з ціною: практичні паттерни
Long squeeze: OI високий, переважно лонги → різке падіння ціни → лонги ліквідуються → ще більше падіння. Сигнал: перед рухом OI аномально високий, Funding Rate позитивний.
Short squeeze: протилежне. Багато шортів, ціна різко росте, шорти ліквідуються — ракета вгору.
OI накопичення у боковику: OI росте при флэтовій ціні → ринок накопичує позиції → буде рух (direction невідомий заранее, але буде вибухове).
Моніторинг OI разом з Funding Rate та ціною дає значно повнішу картину рыночного стану, ніж тільки технічний аналіз. Професійні трейдери використовують ці дані як ключові inputs при прийнятті рішень.







