MarketTrace
M1PositioningM2Order BookM3LiquidationsM4Funding
Methodology · v1.0.0 · updated 2026-05-12

Cross-exchange liquidations

How the liquidations tape is sourced, normalised, sized and read: WS feeds, schema, side semantics, adaptive bucketing, cluster detection, freshness rules.

See the live widget at /perpetuals/liquidations.

Data sources

Three exchange WebSocket feeds, one normalised Redis stream per asset. Every executed liquidation print lands in the tape — we do not estimate liquidation pressure from open interest, do not infer stop zones, do not synthesise prints.

Each daemon writes events into a per-asset Redis Streamprod:liq:<asset>:events capped at MAXLEN ≈ 10 000 (≈ 4 hours of cascade-heavy tape, often the full 24 h on quiet days). The backend reads from one stream per asset for both REST and WebSocket surfaces; there is no separate pubsub channel — the stream itself is the broadcast surface.

Event schema

Per-event fields are identical across the three sources. The two timestamps are deliberately kept distinct:

Side semantics

Liquidation streams encode the side from the perspective of the exchange's closing order, which is the opposite of the trader's position. We normalise to the position that lost:

Tape colour follows this: red dot = long blew up (price dropped); green dot = short blew up (price rose).

Size scaling

Each dot's radius in viewBox-px is clamp(√(usd / $10 000) × 2, 4, 22). The sqrt damps linear-by-area scaling so a $1 M event reads as ~3.16× a $100 K event — not 10× — and a single cascade print can't blot out everything around it. The lower clamp keeps a readable hit zone on sub-$10 K dust; the upper clamp keeps the biggest cascade from overflowing the panel.

r = clamp(sqrt(usd / 10_000) * 2, 4, 22)   // viewBox-px

# Reference values (vs the size legend)
$10 K   → r ≈ 4
$100 K  → r ≈ 6.3
$1 M    → r = 20
$10 M+  → r = 22 (clamped)

Adaptive rendering

Raw scatter only scales to the ~15-minute regime. Past that, hundreds of small prints in a single second smear into a uniform glow, and cascade structure disappears. We switch render modes by window:

Hit-testing, top-N annotations and tooltips run against the rendered (bucketed) events; cluster detection, cumulative pane and rate sub-pane scan raw events since those signals are about per-event density and side flow, not hover targets.

Cluster detection

Price-cluster bands are detected on the raw events of the active window:

reference_price = current mid (latest event price)
bin_width       = reference_price * 0.001    // 0.1 %
bin events by round((price - reference) / bin_width)

for each bin:
  if Σ usd ≥ 15 % of window total AND distinct events ≥ 3:
    flag as cluster
    cluster_price = volume-weighted mean of bin's prices

keep top 3 clusters by Σ usd

Each cluster gets a dashed horizontal line + badge $X cluster · N× @ price. The volume-weighted mean (rather than the nominal bin midpoint) keeps the line sitting at the depth where the dollars actually concentrated.

Top-N inline annotations

Up to three of the largest dots in the window get an inline $amount · time · venue|N× label so the eye lands on the biggest cascade immediately. The $50 K floor avoids labelling dust. Label anchors flip based on which half of the plot the dot is in, so the text never spills past the right axis or under the left edge.

Liquidation rate sub-pane

Under the cumulative pane, a mirrored bar chart shows Σ usdper time bucket split by side: shorts extend UP from the baseline (green), longs DOWN (red). Bucket size follows the scatter's adaptive thresholds (30 s at ≤ 15 m, 1 min at 1–4 h, 5 min at 24 h) so the columns visually align with the dots above.

Feed health

A per-(asset, exchange) status hash prod:liq:status:<asset>:<exchange> is refreshed every 5 s with a 60 s TTL. The backend converts that into three states:

The latency p50 / p99 numbers in the health tooltip are sampled from the daemon's rolling 200-event ring buffer of producer_ts_ms − ts_ms.

Empty-time bands

Contiguous spans of the window with no liquidations at all get a subtle background tint. Without this, a 24 h view with 6 h of local data reads as a broken renderer rather than as “there were no cascades in that stretch”. The threshold is gap ≥ 5 % of window — short enough to flag a quiet 30 m on a 24 h view, long enough to avoid striping the chart with micro-bands during quiet seconds.

Caching

Limitations

Versioning

Methodology version v1.0.0 · updated 2026-05-12. Material changes (new venues, formula tweaks, threshold changes) bump the version and update dateModified in the structured data above.