All resources
Tutorial · Derivatives 10 min read

Detect leverage build-ups and squeezes with open interest + funding.

Optiom Research · runnable code, tested against the live API

Open interest tells you how much leverage exists; funding tells you which side pays for it. Combined, they give you the four regimes that matter: leverage building long, building short, flushing, or quiet. This tutorial resamples raw OI snapshots to hourly, aligns funding on the same clock and flags crowded-long build-ups and squeezes.

Fetch, resample, flag

OI arrives as tick-level snapshots (every few seconds), so resample to hourly last-values. Funding updates on a slower clock, so forward-fill it onto the OI index. A crowded-long hour is OI up more than 5% in 24h with positive funding; a squeeze hour is OI down more than 5% in 24h — leverage leaving the system fast, willingly or not.

import pandas as pd
import requests

BASE = "https://www.getoptiom.com/api/tradinghub"
SYMBOL = "BTCUSDT"

oi = pd.DataFrame(requests.get(
    f"{BASE}/oi", params={"symbol": SYMBOL, "max_rows": 50_000}, timeout=60
).json()["oi"])
oi["dt"] = pd.to_datetime(oi["tMs"], unit="ms", utc=True)
oi_h = oi.set_index("dt")["oi"].resample("1h").last().dropna()

funding = pd.DataFrame(requests.get(
    f"{BASE}/funding", params={"symbol": SYMBOL, "max_rows": 20_000}, timeout=30
).json())
funding["dt"] = pd.to_datetime(funding["time"], unit="s", utc=True)
f_h = funding.set_index("dt")["value"].resample("1h").ffill()

# align funding onto the OI clock (funding updates slower; forward-fill)
df = pd.DataFrame({"oi": oi_h})
df["funding"] = f_h.reindex(df.index, method="ffill")
df = df.dropna()
df["oi_chg_24h_pct"] = df["oi"].pct_change(24) * 100

# setup: leverage builds (OI +5% in 24h) while funding is positive -> crowded longs
df["crowded_long"] = (df["oi_chg_24h_pct"] > 5) & (df["funding"] > 0)
# squeeze: that leverage gets flushed (OI -5% in 24h)
df["squeeze"] = df["oi_chg_24h_pct"] < -5

print(df.tail(6).round(4))
print(f"\nHours flagged crowded-long: {int(df['crowded_long'].sum())}")
print(f"Hours flagged squeeze:      {int(df['squeeze'].sum())}")
print("\nLatest squeeze windows:")
print(df[df["squeeze"]].tail(5)[["oi", "oi_chg_24h_pct", "funding"]].round(4))

Reading the four regimes

OI up + funding positive: longs piling in — fragile, fuel for a downside cascade. OI up + funding negative: shorts piling in — fuel for a short squeeze up. OI down fast after either: the flush is happening; these hours overlap heavily with the cascade hours from the liquidations tutorial. OI flat: nobody is committing, expect chop.

Practical notes

At 50,000 snapshots the OI window covers roughly two days; schedule the script hourly and persist the output to build your own longer history. The squeeze flags become actionable when combined with the levels from the depth heatmap: a flush into a strong bid wall is the highest-quality long setup this data offers.

Run it on your own data.

Create a free account for CSV exports, then move to API access as your workflow grows.