Liquidation data
The liquidation model in a script, with the levels now (liq.levels, observed positions included), the hourly heat field and the legend facts.
ChartDeck estimates where leveraged positions would be liquidated, from open interest, price and typical leverage on each venue. It is a model, not exchange data. Where an exchange publishes positions (Hyperliquid, dYdX, Lighter) the observed levels come with it. The built-in Liquidation Levels and Liquidation Heatmap studies draw this data; a script reads the same with the liq functions. (The realized liquidations, the force-closes that happened, are the series liq.long_usd, liq.short_usd and liq.total_usd: see ChartDeck data; placed on each bar as the Liquidation candles mark them, they are liq.long_liq_usd, liq.short_liq_usd and liq.events: see Liquidations on each bar.)
#The levels now
liq.levels(side) returns the model's biggest levels (12 per side, 40 on Pro and Elite) and the observed ones, as liq.level values. It describes now, so it is filled on the newest bar only: every other bar gets an empty array. Draw from it inside if (barstate.islast).
| Field | Type | Meaning |
|---|---|---|
price | float | where the liquidations sit |
side | string | "long" (below the price: longs liquidated on a fall) or "short" (above) |
notional | float | the estimated size, in the quote currency |
observed | bool | true = positions seen on an exchange; false = model estimate |
venues | string | the venue of an observed level, the model's scope otherwise |
updated | int | when the data was last updated (ms) |
//@chartscript 1
indicator("Liquidation lines", { overlay: true, max_lines_count: 100 })
state lines = array.new<line>()
if (barstate.islast) {
for (const l of lines) {
l.delete()
}
lines.clear()
for (const lv of liq.levels()) {
const col = lv.side == "long" ? color.up : color.down
lines.push(line.new(time, lv.price, time_close, lv.price, xloc.bar_time, extend.both, color.new(col, lv.observed ? 0 : 60), line.style_solid, lv.observed ? 2 : 1))
}
}liq.levels("long") and liq.levels("short") keep one side.
#The heat field
liq.heat() gives the model's field over the bar as a heatmap.column: 240 price rows between 10% below the lowest and 10% above the highest price of the window, the values in the quote currency (smoothed between rows, as the built-in draws them). The field is hourly: every bar inside one hour gets that hour's column (its span says 1 hour), and a bar longer than an hour gets the largest value of each row over its hours. It is a Pro feature, as the Liquidation Heatmap is: on other plans liq.heat() is na. See Heatmaps for an example.
#For the legend
| Function | Gives |
|---|---|
liq.updated() | when the data was last updated (ms) |
liq.venues() | the model's scope as text, for example "All venues (14 listed)" |
liq.window() | "7d" or "30d" (Elite) |
liq.is_model() | true for the model; false when a venue with observed positions is pinned |
//@chartscript 1
indicator("Liquidation legend", { overlay: true })
if (barstate.islast) {
legend.info(liq.venues())
legend.info("updated " + str.format_time(liq.updated(), "HH:mm", "UTC") + " UTC")
legend.badge(liq.is_model() ? "Model estimate" : "Observed", "Model estimate, not exchange data.")
}#Where it comes from
The data is the Liquidation studies' own, with their settings: the window (7 or 30 days), a pinned venue and the observed layers you chose in the Liquidation panel apply to scripts on that chart too. It is refreshed every 5 minutes; a change runs the script again. A script on ChartDeck's servers (a protected script, a script alert) reads the 7-day window over all venues with every observed layer your plan includes.
#Liquidations on each bar
The Liquidation candles chart type marks the liquidations that happened: longs liquidated and shorts liquidated, as exact prints where ChartDeck records them (bars under 1 hour, the last day) and hourly rows otherwise. A script reads the same marks on its own bars (Pro and Elite):
| Name | Gives |
|---|---|
liq.long_liq_usd, liq.short_liq_usd | the USD of longs / shorts liquidated in the bar |
liq.events(back) | the bar's liquidations: time, price, usd, side ("long" or "short"), venues, exact |
liq.events_since() | where the data starts (7 days back, 30 on Elite) |
//@chartscript 1
indicator("Liquidations per bar")
plot(liq.long_liq_usd, "Longs liquidated", { color: color.red, style: plot.style_columns })
plot(-liq.short_liq_usd, "Shorts liquidated", { color: color.green, style: plot.style_columns })An hourly row goes on a bar of its hour whose range holds its price, as the candles place it. Before the data starts the values are na, never 0; a bar inside the data with no liquidation reads 0. These are measured liquidations placed on your bars, unlike liq.long_usd and liq.short_usd, which keep their hourly totals. On other plans every value is na and the legend says "Liquidation candles: not included in your plan".
liq.events(back) lists a bar's liquidations by time. exact tells an exact print from an hourly row:
//@chartscript 1
indicator("Large exact liquidations", { overlay: true, max_labels_count: 200 })
const minUsd = input.float(250000, "Mark from (USD)")
for (const e of liq.events()) {
if (e.exact && e.usd >= minUsd) {
label.new(e.time, e.price, "", xloc.bar_time, yloc.price, e.side == "long" ? color.down : color.up, label.style_circle, na, size.tiny)
}
}The data is asked again every minute. In Bar replay a liquidation appears once its bar (an exact print) or its hour (an hourly row) has ended. A script on ChartDeck's servers (a protected script, a script alert) reads the same data with the same rules, for the plan of the member viewing it or of the alert's owner. The per-bar values also work inside a request; the lists read the chart's own bars only.