Parsing liquidation data from exchanges
Liquidation data is one of the most valuable on-chain and off-chain signals for traders. Sharp increase in long liquidations → potential continuation of decline. Cascade of short liquidations → possible short squeeze. Problem: exchanges provide this data differently, many limit historical depth, and REST and WebSocket APIs behave unpredictably under load.
Data sources: CeFi vs DeFi
Centralized exchanges
Binance — most liquid source. WebSocket endpoint wss://fstream.binance.com/ws/!forceOrder@arr streams all liquidations across all futures pairs in real-time. Event format:
{
"e": "forceOrder",
"E": 1704067200000,
"o": {
"s": "BTCUSDT",
"S": "SELL", // SELL = long liquidation
"o": "LIMIT",
"f": "IOC",
"q": "0.014", // quantity
"p": "41850.00", // price
"ap": "41800.00", // average price
"X": "FILLED",
"l": "0.014",
"z": "0.014",
"T": 1704067200000
}
}
Historical data available through REST only for last hour (/fapi/v1/forceOrders). For deeper history — need to continuously write data yourself from launch.
OKX — WebSocket channel liquidation-orders with instrument filter. Similar structure, different field names. REST history — 3 months through /api/v5/public/liquidation-orders.
Bybit — WebSocket topic liquidation.{symbol}. Historical data through /v5/market/recent-trade (liquidations come as special trade type).
Bitmex — WebSocket liquidation channel. One of oldest sources, data from 2014 through API.
Deribit — options and futures on BTC/ETH. WebSocket liquidations.{instrument}. Important for understanding options market.
Decentralized exchanges
DeFi perps liquidations are on-chain events, more reliable source:
GMX v2 — event PositionLiquidated (or OrderCancelled with reason LIQUIDATION) in EventEmitter contract on Arbitrum. All data on-chain, historical data through The Graph subgraph or direct parsing.
dYdX v4 — Cosmos-based chain, liquidations as on-chain transactions. Parsing through Cosmos RPC or Indexer API.
Hyperliquid — own L1, API with full liquidation history.
Aave v3, Compound v3 — lending liquidations through LiquidationCall / AbsorbCollateral events. Not perps, but important component of overall liquidation picture.
WebSocket collector implementation
import WebSocket from 'ws';
interface LiquidationEvent {
exchange: string;
symbol: string;
side: 'long' | 'short'; // which side was liquidated
price: number;
quantity: number;
quantity_usd: number;
timestamp: number;
raw: Record<string, unknown>;
}
class BinanceLiquidationCollector {
private ws: WebSocket;
private reconnectDelay = 1000;
async connect(onEvent: (event: LiquidationEvent) => Promise<void>) {
this.ws = new WebSocket('wss://fstream.binance.com/ws/!forceOrder@arr');
this.ws.on('message', async (data) => {
const raw = JSON.parse(data.toString());
const event = this.normalize(raw);
await onEvent(event);
});
this.ws.on('close', () => {
// Exponential backoff reconnect
setTimeout(() => {
this.reconnectDelay = Math.min(this.reconnectDelay * 2, 30000);
this.connect(onEvent);
}, this.reconnectDelay);
});
this.ws.on('open', () => {
this.reconnectDelay = 1000; // reset on success
});
}
private normalize(raw: any): LiquidationEvent {
return {
exchange: 'binance',
symbol: raw.o.s,
side: raw.o.S === 'SELL' ? 'long' : 'short',
price: parseFloat(raw.o.ap),
quantity: parseFloat(raw.o.q),
quantity_usd: parseFloat(raw.o.ap) * parseFloat(raw.o.q),
timestamp: raw.E,
raw,
};
}
}
For multi-exchange collector — one interface LiquidationCollector with per-exchange implementations. Normalization to unified format critical: each exchange has its own conventions for side, price, quantity.
Storage and aggregation
Liquidations are time-series data. TimescaleDB is optimal choice:
CREATE TABLE liquidations (
time TIMESTAMPTZ NOT NULL,
exchange TEXT NOT NULL,
symbol TEXT NOT NULL,
base_asset TEXT NOT NULL, -- BTC, ETH, SOL
side TEXT NOT NULL, -- 'long' | 'short'
price NUMERIC(20, 8),
quantity NUMERIC(20, 8),
quantity_usd NUMERIC(20, 2),
raw JSONB
);
SELECT create_hypertable('liquidations', 'time');
-- Index for fast queries by asset
CREATE INDEX ON liquidations (base_asset, time DESC);
Continuous aggregates for analytics:
-- Per-minute aggregate for each asset
CREATE MATERIALIZED VIEW liquidations_1m
WITH (timescaledb.continuous) AS
SELECT
time_bucket('1 minute', time) AS bucket,
base_asset,
exchange,
SUM(CASE WHEN side = 'long' THEN quantity_usd ELSE 0 END) AS long_liq_usd,
SUM(CASE WHEN side = 'short' THEN quantity_usd ELSE 0 END) AS short_liq_usd,
COUNT(*) AS count
FROM liquidations
GROUP BY bucket, base_asset, exchange;
Metrics and indicators
Useful derived metrics from raw liquidation data:
Cumulative liquidation volume — sum of liquidations over period. Sharp growth > 3 standard deviations from moving average — cascade signal.
Long/Short ratio of liquidations — if 80%+ liquidations of one side — directional signal.
Liquidation clusters — price levels with high liquidation concentration. Used as support/resistance levels (where exchange liquidation engines are).
import pandas as pd
import numpy as np
def detect_liquidation_cascade(
df: pd.DataFrame,
window_minutes: int = 5,
std_multiplier: float = 3.0,
) -> pd.Series:
"""
df: DataFrame with columns ['time', 'quantity_usd']
Returns bool Series: True where cascade liquidations
"""
rolling = df.set_index('time')['quantity_usd'].rolling(f'{window_minutes}T')
mean = rolling.mean()
std = rolling.std()
current = df.set_index('time')['quantity_usd']
return current > (mean + std_multiplier * std)
Limitations and edge cases
Exchanges don't always provide all data. Some exchanges aggregate small liquidations or introduce delay. Historical data may be revised.
Diffs in normalization. For Binance S: "SELL" means long position liquidation (forced sale). Other exchanges may have reverse logic — always verify side logic.
WebSocket message lag. Binance WS sometimes delivers events with 1-5 second lag under high market load — exactly when data is most important. Timestamp in raw event is liquidation time, not delivery time.
Cross-exchange deduplication. One large position may be liquidated through several orders that come as separate events.
Stack and timeline
| Component | Technology |
|---|---|
| Collectors | TypeScript/Node.js (one node for all WS) |
| Queue | Redis Streams / Kafka |
| DB | TimescaleDB |
| DeFi on-chain | viem + event subscription |
| API | FastAPI (Python) or Express |
| Dashboard | Grafana / custom React |
Collector for 5 exchanges + on-chain GMX/Aave + TimescaleDB storage + basic API: 3-4 weeks. Custom dashboard with liquidation heatmap and cascade detector — another 1-2 weeks.







