📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← Makalelere geri dön
July 29, 2026
5 dakikalık okuma

Liquidation cascades as a trading signal: reading forced, pre-announced flow

Liquidation cascades as a trading signal: reading forced, pre-announced flow
#liquidations
#cascade
#trading signal
#defi
#perpetuals
#order book
#market microstructure
#crypto

Most market flow is a secret until it prints. A discretionary seller decides to sell when they decide; you learn their intent from the tape, after the fact. Leveraged liquidations are the exception, and the exception is enormous. A liquidation is forced — the position holder has no say in whether it happens — and it is pre-announced — the exact price at which it fires is a deterministic function of parameters that are, on-chain, fully public, and off-chain, statistically estimable. Every leveraged long is a standing market-sell order resting at a price it is broadcasting to anyone who cares to compute it.

That reframes the whole thing. The companion article on Aave and Compound liquidation mechanics treats liquidations from the liquidator's side — the infrastructure race to be the one who repays the bad debt and collects the bonus. This article takes the trader's side of the same object: not "how do I win the liquidation," but "the aggregate of everyone else's liquidation prices is a map of future forced flow, and I can trade against that map." We build two versions of the map — an exact one on-chain, a fuzzy one on CEX perps — quantify when a chain of liquidations turns self-reinforcing, and state, carefully, what the resulting flow does to price.

The on-chain liquidation depth chart

On a money market, a position's liquidation price is not estimated. It is derived. Recall the health factor from the mechanics primer: a position is liquidatable when

HF=iCiPiLTijDjPj<1HF = \frac{\sum_i C_i \, P_i \, LT_i}{\sum_j D_j \, P_j} < 1

with CiC_i the collateral amounts, PiP_i their oracle prices, LTiLT_i the liquidation thresholds, and DjPjD_j P_j the debt values. We will not re-derive this; we invert it. Take the common case — a single volatile collateral CC (say WETH) financing stable debt DD (USDC). Setting HF=1HF = 1 and solving for the collateral price gives the position's trigger price:

Pliq=DCLTP_{\text{liq}} = \frac{D}{C \cdot LT}

That single number is what the borrower has advertised. It says: if WETH touches PliqP_{\text{liq}} on the oracle, this position becomes forced supply. And the size of that supply is knowable too — at the trigger, a liquidator repays closeFactor×D\text{closeFactor} \times D of debt and seizes collateral worth repay×(1+bonus)\text{repay} \times (1 + \text{bonus}), so roughly

QforcedcloseFactorD(1+bonus)Q_{\text{forced}} \approx \text{closeFactor} \cdot D \cdot (1 + \text{bonus})

of collateral value hits the market (or gets hedged) when the position fires.

Take the concrete position from the mechanics primer: 10 WETH deposited at $3,000, 20,000 USDC borrowed, liquidation threshold LT=0.83LT = 0.83, bonus 5%. Its trigger is P_{\text{liq}} = 20{,}000 / (10 \times 0.83) = \2{,}410,andata50, and at a 50% close factor it parks 0.5 \times 20{,}000 \times 1.05 = $10{,}500offorcedWETHsupplyatthatprice.Oneborrower,onebaronthechart.Dothisforeveryborrowerintheprotocol,buckettheresultsbyof forced WETH supply at that price. One borrower, one bar on the chart. Do this for every borrower in the protocol, bucket the results byP_{\text{liq}}$, and you have a histogram: forced-sell notional as a function of price. That is the on-chain liquidation depth chart — the DEX-native cousin of an order book, except the "orders" are involuntary and their prices are computed, not quoted.

On-chain liquidation depth chart: aggregated Aave and Compound collateral bucketed by liquidation price into a histogram of forced-sell pressure stacked below spot

Three honesty caveats keep this from being fantasy:

  1. Multi-asset positions have no single trigger price. A position with two volatile collaterals and two debts liquidates on a surface in price space, not a point. The practical reduction is to compute the trigger along the axis of the dominant volatile collateral while holding every other oracle price at its current value. That is correct for a move in one asset and wrong for a correlated basket move — which matters, because correlated crashes are precisely when many triggers move together. Treat the single-asset PliqP_{\text{liq}} as a first-order marginal, not a guarantee.
  2. Forced sell \neq market dump at one venue. Competent liquidators do not blindly market-sell seized collateral into the thinnest available pool; they route across DEX and CEX, and often hold and delta-hedge on a perp rather than realize the collateral immediately (the exit-swap problem the mechanics primer dwells on). So QforcedQ_{\text{forced}} is an upper bound on price-impacting flow, not a point estimate. Some of it leaks into hedges that never touch spot.
  3. Triggers move with the oracle, not the market. On Aave and Compound the position becomes liquidatable when the oracle crosses PliqP_{\text{liq}}, and oracles update on deviation-and-heartbeat cadence, lagging the market. The depth chart is therefore a map of where forced flow becomes eligible, gated by the next oracle transmit — a subtlety the primer covers in detail.

A third source sits between the money-market chart and the CEX heatmap: perp DEXs. Hyperliquid, GMX, and dYdX v4 run leveraged perpetuals like a centralized exchange but keep position state on-chain or in a queryable clearinghouse. That means their liquidation prices obey the same isolated-margin formula as CEX perps — but computed from actual positions (size, collateral, entry) rather than estimated from aggregate OI. Hyperliquid's clearinghouse state exposes each account's margin and mark price; GMX positions are on-chain and liquidate at oracle-derived prices via keepers. The practical upshot: for perp DEXs you can build a liquidation map with CEX-style leverage but on-chain-style precision, much closer to the Aave chart's exactness than to the heatmap's guesswork. Where a venue publishes positions, you never have to guess.

Even with the caveats, the on-chain chart is the cleanest forced-flow map that exists anywhere in markets: no assumption about leverage distribution, no hidden size, every input readable from state.

The CEX liquidation heatmap

Centralized perpetual exchanges give you the opposite situation — vastly larger open interest, and almost none of the position-level detail that makes the on-chain chart exact. You cannot read individual positions. What you can read is aggregate open interest and traded volume. The liquidation heatmap is what you get when you try to reconstruct the depth chart from those aggregates plus assumptions, and the assumptions are load-bearing.

The per-position arithmetic is simple. For an isolated-margin linear (USDT-settled) long entered at price EE with leverage LL and maintenance-margin rate mm, liquidation fires when equity falls to the maintenance requirement:

EL+(PE)=EmPliqlong=E(11L+m)\frac{E}{L} + (P - E) = E \cdot m \quad\Longrightarrow\quad P_{\text{liq}}^{\text{long}} = E\left(1 - \frac{1}{L} + m\right)

and symmetrically Pliqshort=E(1+1Lm)P_{\text{liq}}^{\text{short}} = E\left(1 + \frac{1}{L} - m\right). Fix an entry at E = \3{,}000withwithm = 0.5%$ and walk the leverage tiers:

Leverage PliqlongP_{\text{liq}}^{\text{long}} Distance below entry
$2,415 −19.5%
10× $2,715 −9.5%
25× $2,895 −3.5%
50× $2,955 −1.5%
100× $2,985 −0.5%

The shape of that column is the whole reason heatmaps light up just beneath recent price: high-leverage positions liquidate within a hair of entry, so wherever volume recently traded, a dense band of 50–100× triggers sits a fraction of a percent away. The heatmap builder proceeds: treat recent traded volume as a proxy for where positions were opened (their EE), spread that volume across an assumed set of leverage tiers — 5×, 10×, 25×, 50×, 100× with some assumed weights — project each slice to its PliqP_{\text{liq}}, and shade the price axis by the estimated leveraged notional that liquidates there. Bright bands are dense estimated liquidation zones.

CEX liquidation heatmap: estimated leveraged notional projected to liquidation prices across leverage tiers, drawn as horizontal intensity bands above and below the current price

Be explicit about why this is a fuzzy picture and not the on-chain chart's twin:

  • The leverage distribution is unknown. The entire heatmap is a convolution of volume against an assumed leverage histogram. Different assumptions relocate the bright bands. Two reputable data vendors publish visibly different heatmaps for the same market on the same day, and both are "right" given their priors.
  • Cross-margin breaks the per-position formula. The PliqP_{\text{liq}} above is an isolated-margin result. A cross-margin position liquidates on whole-account equity, so its effective trigger depends on the trader's other positions, their unrealized PnL, and any collateral they top up mid-move — none of which is observable. Cross-margin size is effectively invisible to the estimator.
  • Hidden and dynamic size. Open interest is a net-plus-gross aggregate; it does not tell you the mapping from OI to individual entries. Traders add, trim, and hedge continuously. Tiered maintenance margin (mm rises with position notional) shifts big positions' triggers relative to small ones at the same leverage.
  • Liquidation is chunked, not instantaneous. Exchanges liquidate large positions incrementally and route residual risk through an insurance fund and auto-deleveraging, so even a correctly located cluster does not dump as one print.

The correct way to hold the heatmap is as a prior over where forced flow is likely concentrated, to be confirmed or refuted by realized liquidation prints (the forceOrder stream in the pipeline section below), not as a ledger. It is genuinely useful and genuinely imprecise, and pretending otherwise is how people get run over by the very clusters they are watching. For why so much leverage piles up on perps in the first place — and why funding cost keeps nudging those positions toward their triggers — see funding rate arbitrage across exchanges.

Cascade dynamics, quantified

A single liquidation is a data point. A cascade is the feedback loop, and it has a threshold you can write down. The loop is mechanical: a forced sale hits the book → price impact moves the market → the move pushes the next tier of positions past their trigger → those liquidate → more forced selling → repeat. Whether this fizzles or runs away is not a matter of sentiment; it is a ratio of two quantities you have already built.

Work in fractional price drops r=ΔP/Pr = -\Delta P / P. Two ingredients:

  • Liquidation density ρ\rho — forced-sell notional per unit fractional price drop, read straight off the depth chart / heatmap: ρ=dQ/dr\rho = -\,dQ / dr. It measures how much fuel is stacked in a price band.
  • Market depth Δ\Delta — the notional of market-selling required to move price by one unit of rr. Under a linear (Kyle) impact model, selling notional QQ moves price by r=Q/Δr = Q / \Delta. This is the order book's capacity to absorb forced flow, and it is exactly the quantity the order-book wall and queue-position analysis is about — a "wall" is a local spike in Δ\Delta.

Now iterate. An exogenous shock drops price by r0r_0, triggering Q0=ρr0Q_0 = \rho \, r_0 of forced selling. That selling causes a further drop r1=Q0/Δ=(ρ/Δ)r0r_1 = Q_0 / \Delta = (\rho/\Delta)\, r_0. Define the cascade multiplier

g=ρΔg = \frac{\rho}{\Delta}

and the recursion is simply rn+1=grnr_{n+1} = g \, r_n. The total drop is a geometric series:

rtotal=r0(1+g+g2+)=r01g(g<1)r_{\text{total}} = r_0 \left(1 + g + g^2 + \cdots\right) = \frac{r_0}{1 - g} \quad (g < 1)

Everything lives in the value of gg:

  • g<1g < 1subcritical. Each round of liquidations triggers less selling than the round before. The cascade self-extinguishes; the total move is a bounded multiple 1/(1g)1/(1-g) of the initial shock. Most liquidation events are here.
  • g1g \ge 1supercritical. Each round triggers at least as much selling as the last. The geometric series diverges; the move is bounded only by the exhaustion of liquidatable positions, the deepening of the book at lower prices, or an exchange circuit breaker. This is the "flash crash / long squeeze" regime.

gg is a reproduction number — the R0R_0 of a liquidation epidemic. It says the cascade runs away exactly when the forced-sell liquidity clustered in a price band exceeds the book liquidity available to absorb it there. That is why a modest shock into a dense cluster on a thin book is far more dangerous than a large shock into empty price space: the danger is ρ/Δ\rho / \Delta, not the shock size. This self-exciting structure — events triggering more events of the same kind — is the same one that motivates modeling order flow with Hawkes processes, and it is why liquidations arrive in clusters rather than uniformly.

Cascade chain: a forced sale creates price impact that pushes the next cluster of positions underwater, drawn as a descending staircase annotated with the reproduction-number threshold g equals one

Put numbers on it. Suppose the book is such that $10M of market selling moves ETH by 1%, so \Delta = 10\text{M} / 0.01 = \1\text{B}$ of notional per unit fractional price. Now compare two regimes for the 1%-wide band just below spot:

  • Dense band, $30M of clustered forced-sell notional. Then \rho = 30\text{M} / 0.01 = \3\text{B}andandg = \rho/\Delta = 3.Supercritical:ashockthatclipsthetopofthebanddetonatesthewholestack,andthemodelfloorissetnotby. Supercritical: a shock that clips the top of the band detonates the whole stack, and the model floor is set not by g$ but by wherever positions run out.
  • Sparse band, $6M of clustered notional. Then \rho = \600\text{M},, g = 0.6,andthetotalmoveis, and the total move is r_0 / (1 - 0.6) = 2.5,r_0$ — an amplified but bounded dip. Same shock, same book, five-fold-thinner cluster, and the outcome flips from collapse to a buyable wick.

The discrete version is a short simulation over the sorted clusters, and it is worth writing because it makes the threshold tangible:

def cascade(p0, clusters, kyle_lambda):
    """
    p0:          price after the exogenous shock
    clusters:    {trigger_price: forced_notional} for long positions
    kyle_lambda: fractional price impact per $ of market sell (1/depth)
    Returns the floor price and total liquidated notional.
    """
    p, sold, fired = p0, 0.0, set()
    while True:
        new = [(tp, n) for tp, n in clusters.items()
               if tp not in fired and tp >= p]
        if not new:
            break
        q = sum(n for _, n in new)          # this round's forced sell
        fired.update(tp for tp, _ in new)
        p *= (1 - kyle_lambda * q)          # linear price impact of the round
        sold += q
    return p, sold

Two practical notes. First, gg is local — it varies along the price axis, because both ρ\rho (cluster density) and Δ\Delta (book depth) do. The tradeable question is not "is the market fragile" but "at which specific price does gg cross 1." Second, the same mechanism runs in reverse for shorts on the way up (a short squeeze is a cascade with the signs flipped), so the map has two sides: long-liquidation fuel below spot, short-liquidation fuel above it. The forced-selling-begets-price-impact-begets-forced-selling loop is the endogenous-risk mechanism formalized in the fire-sale literature (Cont & Wagalath), where distressed liquidation manufactures its own correlation and impact.

Signals: clusters as magnets and reversal zones

A map of forced flow generates two distinct, almost opposite, tradeable readings depending on timing relative to the cascade.

Before: clusters are price magnets. A dense liquidation cluster is a pool of guaranteed, price-insensitive flow. That is attractive to two kinds of actors: liquidity-seeking traders who want to fill size against forced counterparties, and predatory traders who push price toward the cluster specifically to set off the flow (the stop-hunt, at protocol scale). The result is a well-documented tendency for price to gravitate toward large clusters — the level acts as a magnet — because there is a standing incentive to close the distance. When you see spot drift toward a bright band on low conviction, the band itself is part of the explanation. Predicting the book's reaction as price approaches — will the wall absorb the flow or fold — is exactly the kind of short-horizon order-book prediction problem that models like DeepLOB attack.

After: clusters are reversal zones. This is the more valuable and more abused reading, so state it carefully. Forced-liquidation flow is, by construction, non-informational — the seller is not selling because they have a view that price is too high; they are selling because a margin engine told them to. Non-informational flow moves price temporarily. Once the clustered positions are exhausted, the mechanical selling stops abruptly, and if the cascade overshot fair value on the way down, price tends to retrace — the "liquidation wick." The mechanism is not folklore: it is the standard result that price impact from forced, uninformed selling has a transient component that reverts once the flow ceases, the same fire-sale logic that produces temporary dislocation and subsequent partial reversion in the equities distressed-selling literature.

Liquidation clusters acting first as a price magnet drawing spot toward the level, then as a reversal zone where a cascade overshoots and the wick retraces once forced flow is exhausted

The discipline this demands, stated as flatly as possible:

  • Mean reversion after a cascade is a documented tendency, not a law, and not a number. It is conditional on the flow having been genuinely non-informational and on no fresh information arriving during the cascade. A liquidation cascade that is also the market repricing on real news (a depeg, an exploit, a macro shock) will not revert — the forced flow and the informational flow are superimposed, and only the former is transient. There is no universal "buy the wick" edge, and any specific reversion percentage you see quoted without a stated sample, venue, and regime should be treated as marketing.
  • The signal is the exhaustion, not the drop. The tradeable moment is when realized liquidation prints thin out — when the forceOrder tape goes quiet after a burst — because that is when the mechanical seller is gone. Entering into the middle of a supercritical cascade (g1g \ge 1) is stepping in front of the very feedback loop the previous section warned about.
  • Both readings need the same map. Magnet and reversal are the same clusters seen at different phases; you cannot trade either without first building the depth chart and heatmap and continuously reconciling them against realized prints.

There is also a slower, directional read in the asymmetry of the two-sided map. Long-liquidation fuel sits below spot, short-liquidation fuel above; when one side is loaded far heavier than the other, the market has a mechanical bias toward the heavy side, because that is where a shock finds the most self-reinforcing flow. A market with a wall of long liquidations 3% down and almost nothing above is structurally fragile to the downside regardless of narrative — the path of least resistance is the path with the most fuel. Persistent, one-sided funding is often what builds that asymmetry in the first place: a market that pays longs to stay short (deeply negative funding) accumulates crowded shorts whose liquidation cluster then sits above price as squeeze fuel, and vice versa. The funding tape and the liquidation map are two views of the same leverage.

The data pipeline

The system is a fusion of two feeds with opposite characters: a forward-looking on-chain position index (where forced flow will become eligible) and a realized CEX liquidation stream (where forced flow is printing right now). One tells you where the fuel is; the other tells you it has ignited.

The forward map — on-chain position index. Bootstrap from the Aave/Compound event history (Supply, Borrow, Repay, Withdraw, LiquidationCall), either by replaying logs or querying a subgraph on The Graph, and fold them into current per-user balances — the exact indexing subsystem the mechanics primer describes for liquidation bots, reused here for aggregation instead of execution. From balances plus current risk parameters, compute each position's PliqP_{\text{liq}} and QforcedQ_{\text{forced}}, and bucket into the depth-chart histogram. Refresh on new blocks; the histogram is cheap to maintain incrementally once the balances are live.

The realized tape — Binance forceOrder stream. Binance Futures publishes actual liquidations over a websocket, wss://fstream.binance.com/ws/!forceOrder@arr (all-symbol array) or <symbol>@forceOrder, each event carrying side, price, and quantity of a liquidation order. One documented gotcha, and it is exactly the kind of imprecision to be honest about: the public stream is throttled to at most one liquidation event per symbol per second — during a violent cascade, when liquidations arrive far faster than 1/s, the stream samples rather than reports every fill, so aggregate liquidation volume reconstructed from it systematically undercounts precisely when it matters most. Use the stream for timing and direction of the cascade (is it firing, which side, is it accelerating or thinning), not as a precise volume ledger.

A minimal ingestion skeleton — two async producers writing into one normalized bus:

import asyncio, json, websockets

async def binance_liquidations(bus):
    url = "wss://fstream.binance.com/ws/!forceOrder@arr"
    async with websockets.connect(url) as ws:
        async for msg in ws:
            o = json.loads(msg)["o"]              # order payload
            await bus.put({
                "src": "binance", "kind": "realized",
                "symbol": o["s"],
                "side": o["S"],                   # SELL = long liquidation
                "price": float(o["p"]),
                "qty": float(o["q"]),             # NB: stream is sampled at 1/s
            })

async def onchain_positions(bus, subgraph, poll=12):
    while True:
        positions = subgraph.fetch_open_positions()   # balances + risk params
        chart = {}
        for pos in positions:
            p_liq = pos.debt / (pos.collateral * pos.liq_threshold)
            q = pos.close_factor * pos.debt * (1 + pos.liq_bonus)
            chart[round(p_liq, 2)] = chart.get(round(p_liq, 2), 0.0) + q
        await bus.put({"src": "aave", "kind": "forward", "chart": chart})
        await asyncio.sleep(poll)                       # ~1 block cadence

async def main(subgraph):
    bus = asyncio.Queue()
    await asyncio.gather(
        binance_liquidations(bus),
        onchain_positions(bus, subgraph),
        consumer(bus),        # reconcile forward map vs realized tape, emit signals
    )

The consumer is where the strategy lives: hold the forward map (on-chain chart plus the estimated CEX heatmap), estimate the local cascade multiplier g=ρ/Δg = \rho/\Delta against live order-book depth, and watch the realized forceOrder tape to detect ignition and — the tradeable part — exhaustion. When the tape bursts and then thins while price sits below a cluster the map said was there, you have a non-informational overshoot with the forced seller gone: the reversal setup. When the tape is accelerating and g1g \ge 1 ahead, you have a supercritical cascade to stand clear of. Same map, opposite actions, and the tape is what disambiguates them in real time.

What to take away

Liquidations invert the usual information asymmetry of markets: instead of flow being hidden until it prints, the price and size of forced selling are computable in advance — exactly on-chain, approximately on CEX perps. Build the map (the on-chain depth chart is exact up to routing and oracle lag; the CEX heatmap is a prior conditioned on an unknown leverage distribution and blind to cross-margin), and the map's fragility reduces to one ratio: the cascade multiplier g=ρ/Δg = \rho/\Delta, forced-sell density over book depth, a reproduction number that is subcritical below 1 and runaway above it. The signal splits by phase — clusters are magnets before, reversal zones after — and the reversal edge exists only because forced flow is non-informational and therefore transient, a documented tendency that evaporates the moment a cascade coincides with real news. Trade the exhaustion, not the drop; respect gg; and never mistake a fuzzy heatmap for a ledger of where the bodies are buried.

References

  • Qin, Zhou, Gamito, Jovanovic, Gervais (2021), An Empirical Study of DeFi Liquidations: Incentives, Risks, and Instabilities. arXiv:2106.06389.
  • Kyle, A. S. (1985), Continuous Auctions and Insider Trading. Econometrica 53(6) — the linear price-impact coefficient λ\lambda used in the cascade model.
  • Cont, R., & Wagalath, L. (2016), Fire Sales Forensics: Measuring Endogenous Risk. Mathematical Finance 26(4) — price impact of forced liquidation and endogenous correlation.
  • Bacry, E., Mastromatteo, I., Muzy, J.-F. (2015), Hawkes Processes in Finance. Market Microstructure and Liquidity 1(1) — self-exciting clustering of order and liquidation flow.
  • Binance Futures API documentation — Liquidation Order Streams (!forceOrder@arr, <symbol>@forceOrder), including the 1-event-per-second-per-symbol throttling note.
  • Aave v3 and Compound III subgraphs on The Graph; Aave getUserAccountData and reserve risk parameters.
Sorumluluk Reddi: Bu makalede sağlanan bilgiler yalnızca eğitim ve bilgilendirme amaçlıdır ve finansal, yatırım veya ticaret tavsiyesi niteliği taşımaz. Kripto para ticareti önemli bir kayıp riski içerir.

Yazarlar

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Piyasanın Önünde Olun

Özel yapay zeka ticaret içgörüleri, piyasa analizi ve platform güncellemeleri için bültenimize abone olun.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.