7 days Pro+ free · no cardStart my free trial

Liquidation heatmaps

How forced liquidations are collected and rendered, and how the heatmap differs from the feed.

What the heatmap shows

The full-screen liquidation heatmap is a time-by-price intensity grid drawn behind a live candlestick chart, both on one shared USD price axis so a single pan or zoom moves them together. The horizontal axis is time, the vertical axis is price, and each cell is a price bin within a time bucket. The default layer is an estimated liquidation surface: it projects newly opened leveraged notional onto discrete liquidation levels anchored at the entry price, carries those levels forward until price crosses them, and removes the band the market swept. Because it is a modeled projection rather than an observed record, the legend on this layer is labeled as relative intensity, not dollars.

Price (USD)Time (UTC)Colorbarrelative intensity, not dollarsHeat gridcell = price bin × columnCandlessame price axis — one panmoves bothhover reads the whole columnOne cellone level, one columnHover readoutlevel value and column total
Both layers are pinned to the same USD price axis, so one pan or zoom moves them together. A row is one price bin — fifty dollars for BTC, five for ETH, fifty cents for SOL — and a column is one render stride, which widens with the lookback. The colorbar is labeled as relative intensity because the estimated layer is a modeled projection, not a conserved dollar total. Hovering resolves exactly one cell and reads its whole column.

From open interest to a liquidation level

Every column of the estimated surface starts from one number per venue: how much that venue's open interest grew since the previous column on the same bucket grid. Only increases count; a decrease deposits nothing. That newly opened notional is anchored at the price the venue reported for that bucket, which the model treats as the entry price of the cohort that just opened. A venue seen for the first time, or reappearing after a gap in coverage, only re-establishes its baseline and deposits nothing at all, because the entry prices of positions opened before the gap are not observable and are never invented.

The opened notional is then split into a long and a short share. Without an account-ratio input the split follows the funding rate through a linear signal that is clamped, and the resulting long share is always held between 30 and 70 percent, so a split is never fully one-sided. Each side is distributed across a leverage ladder of 49 rungs running from 5x to 125x in 2.5x steps, weighted by a log-normal curve peaked at 45x. This ladder is a stated modeling assumption, not a measurement: per-position leverage on centralized venues is not observable.

For every rung the model looks up the venue's maintenance margin rate at a representative position size of ten thousand dollars rather than at the full cohort notional. Using the cohort notional would trip each venue's high-notional bracket and collapse all rungs onto one liquidation price. The level price is then a fixed function of entry and leverage: entry times one minus one over leverage plus the maintenance rate for longs, and entry times one plus one over leverage minus the maintenance rate for shorts. Since entry is fixed, the level does not move when price moves.

What keeps a band alive, and what removes it

Projected levels are folded into a running surface, and exactly three things happen per column, in that order. Existing bands are carried forward unchanged — there is no time decay, so an untouched band looks the same hours later as when it opened. New levels landing in a bin that already holds a band are summed into it, which is why repeated opening at one price brightens a single line instead of drawing a second one. Last, every bin the price crossed during that column is dropped, including anything deposited there in the same column.

The crossed interval is not the close-to-close move. It spans the lowest and highest mark observed inside the bucket, extended to include the previous column's open-interest-weighted mark, so a wick that reaches a level still removes it. Two guards reject implausible intervals instead of deleting real bands: a jump from the previous mark into the candle larger than half the price is read as a coverage gap, and a single bucket whose high-to-low range exceeds 80 percent of the price is read as a data glitch. In both cases that column sweeps nothing.

A band below the notional floor is discarded as numerical noise. The live standing read sets that floor to zero, so only strictly positive bands survive, while the persisted writer path drops anything under one dollar. The practical consequence is that columns differ from their neighbors only because a line appeared or a line was cut. Reading a price row from left to right therefore tells you when a level was first opened and where the market crossed it — never how strongly it faded, because it does not fade.

Where the data comes from

Three different data sets feed the liquidation views, and they do not all cover the same venues. The aggregated multi-exchange view fans out to Binance, Bybit, OKX, Hyperliquid, Bitget, Gate.io, HTX, MEXC, dYdX and Kraken for open interest, funding and price. The persisted standing heat surface is built from a smaller stored set: Binance, Bybit, OKX, Deribit, Bitget and Hyperliquid. Realized liquidation events come from the exchange WebSocket feed registry, which currently registers Binance and Bybit. The live fan-out set and the persisted set are not subsets of each other, so their totals will not reconcile exactly.

Why the colorbar carries no dollar labels

A cell's color encodes the accumulated opened flow that projects a level in that bin over the loaded window. That quantity is bounded by the open interest that opened it, but it is neither the current book nor a conserved dollar total for the window, so a dollar-labeled ramp would invite readers to add cells together into a number that means nothing. The legend on this layer is therefore captioned as relative intensity and its ticks are printed on a zero-to-one-hundred scale, where one hundred is the current color ceiling rather than a fixed amount of money.

That ceiling is the 99.9th percentile of the loaded grid, not its maximum, so one very large cell cannot push everything else into the dark end while the remaining magnets flatten into a single bright tone. The grid handed to the GPU stores each cell divided by that ceiling, because the texture format is a half float and raw dollar values above roughly sixty-five thousand would overflow it. Linear and symlog scaling are unchanged by that division; the log mode spans four decades below the ceiling. The legend places its ticks with the same function the shader uses, so a label sits where its color is actually painted.

Controls and color scale

On the heatmap route you pick the asset (BTC, ETH or SOL), the lookback window, and whether to show the density heatmap or a Liquidation Levels view that replaces the grid with discrete anchored lines, an open-levels profile and a cumulative delta pane. The display panel offers four colormaps — viridis, inferno, magma and cividis, of which viridis and cividis are marked color-vision-deficiency safe — three scale modes (linear, log, symlog) and a sensitivity slider; the shipped defaults are viridis, linear and a 0.85 exponent. A realized overlay can be switched on as a second translucent layer at 1m, 1h or 1d resolution.

lowhighviridisdefaultcolour-vision safeinfernomagmacividiscolour-vision safe
The four ramps the display panel offers, sampled from the lookup tables the renderer uploads. Two of them are marked as safe for the most common colour-vision deficiencies; viridis is the shipped default.

The numbers under the cursor

Hovering resolves a price level and a time column. The reference price used to decide direction is the close of the candle containing the column's bucket start, not the candle under the pointer, so a level cannot flip between the long and the short side while the cursor moves inside one column. A level above that reference reads as short-side, one below it as long-side, and a level in the same bin as the reference is neutral and reports both sides together. Column times are formatted in UTC so the readout agrees with the time axis rather than the viewer's local zone.

Two figures are shown. The on-this-level number is the directional value of the hovered cell — exactly the quantity the color paints, so the number and the shade cannot disagree. The cumulative number sums the same side from the reference bin, exclusive, to the hovered level, inclusive, answering how much sits between current price and that level. In standing mode a third, smaller line reports the current standing open interest projecting a level in that bin. It comes from a separate profile built only from the newest column, is bounded by total open interest, and is deliberately shown as fine print because it answers a different question.

The Liquidation Levels view in detail

The Levels view replaces the density grid with individual lines. Each line is one cohort — a venue, a leverage rung, a side, and the column it opened on — held at its exact projected price instead of snapped to a bin. Cohorts that opened on different columns never merge, so the left edges of the line field trail the price path in a staircase. A line ends where a later column's traded range covers its own price, and the view retains both the entry tick and the hit tick, which is what allows it to draw a finite segment rather than a full-width line.

Granularity filters by position size. The cut points are recomputed on every request as tertiles of that request's own line-notional distribution, so they follow the asset and the window instead of being fixed dollar thresholds. Large keeps lines at or above the lower cut, Whale at or above the upper cut, and All applies no filter. The delta-over-volume control is a second, two-sided filter: its two handles select a sub-band of the observed notional range, so it can isolate mid-sized lines that a one-sided filter cannot reach. Measure switches the cumulative pane between counting lines and summing their notional.

Three panels frame the map. The right-hand profile folds every open line into price bands and is built from the full kept set, so it stays complete even when the drawn line field is capped; it is always folded by notional regardless of the measure setting. The bottom pane is cumulative: a line is added at the column it opened on and subtracted at the column it was hit on, so the series falls back as price sweeps levels out instead of only climbing. A fourth panel states the long-versus-short imbalance of that profile. The line payload itself stops at six thousand lines, keeping the largest by notional and flagging the response, while the reported open counts remain the full totals.

The realized overlay, and when a read calls itself truncated

The realized overlay is a second, translucent layer drawn over the estimated field with its own color table and alpha. Its resolution control offers 1m, 1h and 1d, and picking a resolution also switches the overlay on, so the control is never a silent no-op. The resolution applies to the overlay alone. Each resolution is backed by a continuous aggregate that keeps only a trailing window materialized: roughly three hours at 1m, eight days at 1h and thirty days at 1d. A request wider than its tier's window quietly omits the older buckets, so the read reports itself truncated instead of presenting a short grid as complete.

The 1d tier also has a lower bound. Its buckets start at midnight UTC while the read filter is relative to now, so a 24-hour request can return nothing early in the day; anything under 48 hours is therefore flagged as well. Hitting the repository row cap raises the same flag. The response carries a coverage object listing the exchanges that actually contributed plus a note stating that realized liquidations are a lower bound, because exchange feeds cap how often they emit and only wired venues are counted. A second clause tells the reader whether to narrow or widen the window.

The estimated grid is bounded differently. Because the widest selectable window is seven days while the hourly tier keeps eight, the window itself can never truncate the estimated read; only its row caps can. In the interface the grid status switches from live to partial with a warning marker and an explanatory title, the Levels view adds a note that only the top lines are drawn while the counts stay full, and the overlay's coverage box repeats the lower-bound note verbatim. Nothing is dropped without being said.

Estimated layermodeled projectionRealized layerobserved printsInputOpen interest, 6 stored venuesLiquidation prints, wired feedsMethodLeverage ladder, one level per rungSummed into 1m / 1h / 1d bucketsLifetimeCarried until price crossesFixed once writtenUnitRelative intensity, 0–100US dollars, a lower boundSame grid, different question — do not read one as a check on the other.
The estimated layer turns each column's open-interest increase into levels across a leverage ladder, carries them until price crosses them, and reports a relative intensity. The realized layer sums actual liquidation prints into the same grid and reports dollars, but only as a lower bound: exchange feeds cap how often they emit and only wired venues are counted. They share the axis, not the unit — so they can be compared in position, never added together.

Liquidations page versus the heatmap

The two routes are different products. The Liquidations page is a tabbed dashboard: realized liquidations over time plus estimated clusters, a multi-exchange map, a liquidation estimator, and a launcher that deep-links to the full-screen heatmap. That launcher exists because the true time-by-price grid is a dedicated WebGL route sharing the advanced chart engine and cannot be embedded in a tab panel. The two are gated on different entitlement domains — the dashboard on order flow, the heatmap on derivatives — and the multi-exchange aggregate behind the dashboard is BTC-only, with its risk readout labeled BTC regardless of the asset selected on the heatmap.

The four tabs of the liquidations dashboard

The first tab, Liquidations and Levels, pairs a bar chart of realized long-versus-short liquidations per bucket with a card of estimated clusters per leverage tier. Its interval control changes both the bucket size and how many buckets are requested: 168 buckets at one hour, 84 at four hours, 30 at one day. The clusters card is explicitly labeled indicative and prints its own assumptions — Binance USDT-margined open interest, an assumed even long-short split, and a fixed retail leverage distribution — so it is never mistaken for exchange data. The asset selector on this page offers BTC and ETH only.

The second tab is the multi-exchange map: estimated liquidation volume per price bin aggregated from a live fan-out, with a per-exchange breakdown, a cluster table and a real-events overlay. It shares the same per-asset price-bin width as the persisted grid — fifty dollars for BTC, five for ETH, half a dollar for SOL, with a price-proportional fallback for unseeded assets — so both surfaces land on the same price lattice. The third tab is a separate estimator for BTC and ETH that computes bands at 3x, 5x, 10x, 25x, 50x and 100x from Binance futures price and open interest, with a leverage proxy from Bybit, behind a thirty-second cache.

The fourth tab renders no heatmap at all. The time-by-price grid is a full-screen WebGL route that shares the advanced chart engine and cannot be mounted inside a tab panel, so this tab is a launcher that carries the selected asset into a deep link. Only the active tab's content is mounted, so switching tabs does not start the other tabs' polling loops. The shareable part of that link is the asset and the lookback; resolution, mode and the realized toggle stay session-local, and a legacy resolution parameter is stripped from older links.

Column stride, row caps and refresh cadence

A wider window does not produce more columns. The read derives a column stride from the lookback — 60 seconds up to four hours, 300 seconds up to a day, 900 seconds up to four days, and 1800 seconds beyond — sized so that no allowed window exceeds roughly four hundred columns. The standing and Levels reads floor that stride at their five-minute base, which is why short windows keep their familiar resolution while long ones widen. Downsampling picks the newest column inside each stride window and never sums columns, because the surface is carried forward and summing would count the same standing band repeatedly.

Three caps bound the payload, and each one is reported rather than hidden. The standing grid stops at five hundred thousand rows and, when exceeded, drops whole oldest columns so the grid stays rectangular and the newest column — the one the current-book profile is built from — survives. The Levels payload stops at six thousand lines. The realized events query defaults to one thousand rows with a hard ceiling of ten thousand, and a read that reaches the ceiling is marked as an under-count.

Refresh is polled and gated on tab visibility, so a background tab does not keep fetching. The heat grid and the Levels view refresh every 120 seconds, the liquidations dashboard's event series every 60 seconds, and the estimator every 30 seconds. Changing the asset, window, granularity or measure discards the stale model before refetching, so a control never labels one dataset with another's settings while the request is in flight.

Documented limits

Lookback is a fixed allowlist on the server — 1h, 4h, 12h, 24h and 7d — and anything else is rejected rather than silently defaulted. The dropdown offers four of those five; 1h is reachable only through the API. The estimated and standing surfaces are persisted only at the hourly cadence, so other timeframes are rejected; only the realized overlay is materialized at 1m, 1h and 1d. Each realized tier keeps a limited trailing window (roughly 3 hours at 1m, 8 days at 1h, 30 days at 1d), and the 1d tier needs at least a 48-hour lookback to return complete buckets. Requests outside those bounds come back flagged as truncated, and the interface shows a partial-data warning. The realized events query has a default row cap of 1,000 and a hard cap of 10,000; hitting the cap is surfaced as an under-count note.

LayerResolutionKept forReads outside the window
Realized1mabout 3 hoursflagged as truncated
Realized1habout 8 daysflagged as truncated
Realized1dabout 30 daysneeds a 48-hour request
Estimatedhourly onlypersisted per columnrow caps only
The realized overlay reads three continuous-aggregate tiers with different retention. The 1d tier additionally needs at least a 48-hour request, because its buckets start at midnight UTC while the filter is relative to now. The estimated surface has no resolution choice at all: its writer persists a column every sixty seconds under the hourly label, and since the widest selectable window is seven days while the hourly tier keeps eight, only row caps — never the window — can truncate it.