ChartDeck data
Open interest, funding, basis, long/short ratios, liquidations, CVD, all-exchange flow and ETF flows as series in a script: units, markets and plans.
ChartDeck collects much more than candles: taker buy and sell volume (on one exchange and summed over every exchange), open interest, funding, the perpetual–spot basis, the Coinbase premium, long/short ratios, liquidations and US spot-ETF flows. A script reads them as ordinary series, one value per bar, through the data namespaces: flow, oi, funding, basis, lsr, liq, etf and fp (footprints).
//@chartscript 1
indicator("OI against price", { format: format.volume })
const oiChange = (oi.close - oi.close[24]) / oi.close[24] * 100
plot(oi.close, "Open interest (coins)", color.accent)
plot(oiChange, "OI change over 24 bars, %", oiChange >= 0 ? color.up : color.down, { display: display.data_window })You use them like close or volume: history with [n], inside ta.* functions, in conditions and alerts. A bar with no value reads na, so nz() and na() work as everywhere else.
#The same numbers as the built-in studies
Each series is read from the built-in study that draws the same data, with that study's own loader: the same request to ChartDeck's servers, the same history paging, the same alignment onto the bars. oi.close is, bar for bar, the value the Open interest study shows on the same chart; flow.cvd is the perp line of CVD with its Binance perp source and no reset; liq.long_usd the bar under zero in Liquidations. The official scripts of those studies (View source / Make a copy in the study's settings; see built-ins) are written with these names and give the built-ins' numbers.
#What you can read
| Series | What it is | Unit | Market | Plan |
|---|---|---|---|---|
oi.close | Open interest of the chart's market, the last sample in force at each bar's end | coins | the chart's venue | every plan (history: your plan's order-flow window) |
oi.delta | Change in open interest on the bars where a new sample landed, na between samples | coins | the chart's venue | every plan |
oi.usd | oi.close × close, per coin (a 1000PEPE or kPEPE market counts 1,000 coins a unit) | USD | the chart's venue | every plan |
oi.ref | Open interest of the coin's Binance perpetual, on any chart (a MEXC or BloFin chart reads Binance's figure) | Binance's units | Binance, for the chart's coin | every plan |
oi.ref_usd | oi.ref × close, per coin (a 1000PEPE contract counts 1,000 coins) | USD | Binance, for the chart's coin | every plan |
oi.agg, oi.agg_usd | Open interest summed over every perpetual venue with OI history | coins / USD | all perp venues of the coin | Pro, Elite |
funding.rate | Funding rate in force at each bar | % per funding interval | the chart's venue | every plan |
funding.settled | true on a bar that holds a funding settlement | bool | the chart's venue | every plan |
funding.interval_hours | The venue's funding interval (8 on most venues, 1 on Hyperliquid) | hours | the chart's venue | every plan |
funding.agg_weighted, funding.agg_mean | Funding over the venues listing the coin, weighted by open interest / simple mean | % per 8 hours | all perp venues of the coin | Pro, Elite |
basis.pct | Perpetual over spot: (perp close ÷ spot close − 1) × 100, against the same exchange's spot market or Binance spot | % | the chart's venue | every plan |
basis.cb_premium | Coinbase premium: (Coinbase USD close ÷ Binance USDT spot close − 1) × 100 | % | the chart's coin (BTC if Coinbase does not list it) | every plan |
lsr.accounts, lsr.top | Long/short ratio of all accounts / of the top traders' positions (1 = balanced) | ratio | Binance, Bybit, OKX perpetuals | Pro, Elite |
lsr.margin | Bitfinex margin positions, long ÷ short | ratio | Bitfinex charts | Pro, Elite |
liq.long_usd, liq.short_usd, liq.total_usd | Measured liquidations, positive numbers | USD | the venues that publish them, for the chart's market | Pro, Elite |
etf.net_flow | US spot-ETF net flow of the chart's coin, per US trading day | USD | BTC, ETH, SOL, HYPE, ZEC and a few more | Plus, Pro, Elite |
flow.buy_vol, flow.sell_vol | Taker buy / taker sell volume of the bar | base coin | the chart's market | every plan |
flow.delta | Taker buy minus taker sell volume of the bar | base coin | the chart's market | every plan |
flow.buy_share | Taker buy volume ÷ volume, 0 to 1 (0.5 = balanced) | ratio | the chart's market | every plan |
flow.cvd, flow.spot_cvd | Cumulative delta of the coin's Binance perpetual / spot market, from the first loaded bar with flow | USDT | Binance, for the chart's coin | every plan |
flow.agg_buy, flow.agg_sell | Taker buys / taker sells of the bar summed over every exchange, perpetuals and spot | USD | every exchange ChartDeck merges for the coin | Pro, Elite |
flow.agg_delta | flow.agg_buy − flow.agg_sell (the Aggregated delta / CVD study's bars) | USD | every exchange | Pro, Elite |
flow.agg_cvd | flow.agg_delta summed from the first loaded bar with flow (the study's line) | USD | every exchange | Pro, Elite |
flow.agg_perp_cvd, flow.agg_spot_cvd | The same sum for the perpetuals only / the spot markets only | USD | every exchange | Pro, Elite |
flow.big_buy_usd, flow.big_sell_usd, flow.big_count | The chart's Big trades bubbles of the bar: taker buys / sells, and how many (Trade prints) | USD / count | the chart's Big trades exchanges | every plan, signed in (history: your plan's Big trades reach) |
liq.long_liq_usd, liq.short_liq_usd | The liquidations the Liquidation candles mark in the bar (Liquidation data) | USD | the venues that publish them | Pro, Elite |
fp.* | The bar's footprint: buys and sells per price row, its point of control, delta extremes and readings (Footprints) | base coin / price | the chart's market | Pro, Elite |
Every name, with its exact wording, is in the reference: oi, funding, basis, lsr, liq, etf, flow.
Two kinds of source, worth knowing:
- From the bars themselves:
flow.buy_vol,flow.sell_vol,flow.deltaandflow.buy_sharecome from each candle's taker-buy volume. Binance and Aster candles carry it, and so does every tick and range bar. Other venues' candles and seconds bars carry none: there these arena, never estimated. They load nothing and cost nothing. - From ChartDeck's data servers: every other series. Each is loaded once for the chart and refreshed about every 30 seconds while the chart is on screen.
A script that reads these series (or the record data: prints, liquidation levels, the book, volume at price) draws for the first time once they are in, together with the other markets and timeframes its first run asks for: for up to 8 seconds the legend says "Waiting for data" and the pane stays empty, so you never see a first picture made without them. Data that does not come in that time (a market without it, a plan without it, an error) does not hold the script longer: it draws, and the legend says what is missing. Later updates run as they come.
#How a series meets the bars
- Minute, hour, day, week and month charts: one value per bar, read on the chart's own grid. Open interest is the last sample taken before the bar ended (a step series, never interpolated). Funding is the rate in force at the bar's end.
- Seconds, tick and range charts: the exchanges publish these series per minute at best, so the series is read at a fine time step (1 minute where the loaded bars allow it) and each bar takes the value in force at its end. A gap in the data stays a gap: a bar whose value is more than three steps old reads
na. - Liquidations are hourly: on bars shorter than an hour the hour's total sits on the bar that holds the hour's start (on tick and range bars it is shared over the hour by time). The last 7 days, or 30 on Elite when the chart reaches back further.
- ETF flows are daily: a daily bar gets its day, weekly and monthly bars the sum of their days, and intraday bars the latest day published by their time (a day's flow is known after the US close, 21:00 UTC).
- All-exchange flow (
flow.agg_*) is the Aggregated delta / CVD study's data: every trade of every exchange ChartDeck merges for the coin, summed per bar from the data hub's recorded minutes and then the live 10-second buckets. Before the hub's minutes start the history is ChartDeck's footprint recording of the perpetual exchanges it records: on those bars the sums are perpetuals only andflow.agg_spot_cvdisna. Minute charts and up use the recorded history; a seconds chart starts at the 10-second buckets. On an aggregated chart these series are the coin's whole flow, whatever the chart's exchange preset. The live part streams the coin's all-exchange trades, so it uses one of your plan's order-flow coins, as the study does. oi.refis the Open interest study run on the coin's Binance perpetual and read on your chart's bars, the same way asoi.close. When Binance lists a contract of 1,000 coins (1000PEPEUSDT), that is the one read.- CVD is cumulative from the first loaded bar that has flow, as the study draws it. A script loads its series for the bars it runs on (its own history, see bars per run), so the sum starts where the script's run starts, the same on ChartDeck's servers, and not where the chart's own CVD study starts. Compare the two by their changes, not by their level. The CVD study itself can also draw this chart's own trades, Binance spot or all exchanges, restart each session, day, week or month (UTC), and draw candles; those choices are not script series. A script restarts its own sum, for example with
timeframe.change("1D")as the Cumulative volume delta template does.
A series is na where its source has nothing: a spot market has no open interest or funding, a venue that publishes no open interest has none, a bar before the start of the exchange's history has none. The legend says why (below).
#Plans and limits
The data a script reads is the data your plan reads in the built-in studies, nothing more:
- History: the order-flow window of your plan (1 day on Beginner, 30 on Plus, 90 on Pro, 365 on Elite). Older bars read
na. - Pro series:
oi.agg*,funding.agg_*,lsr.*,liq.*andfp.*need Pro or Elite;etf.net_flowneeds Plus, Pro or Elite.flow.agg_*needs the all-exchange trade feed (Pro and Elite), the same rule as the Aggregated delta / CVD study. Without them the series isnaand the legend says "not included in your plan". The compiler does not refuse them: a published script that reads them still works for its Pro users. - Every plan:
oi.ref(Binance's open interest),flow.cvd/flow.spot_cvd(Binance's taker flow) and the Binance prints (flow.prints(..., "binance"), Trade prints) give every chart the reference of the largest venue. - Data series per script: each distinct series source is one loader on your chart (open interest and OI delta are two; the three long/short ratios are three;
liq.long_usd& co. are one;flow.agg_*is one;fp.*is one;flow.big_*is one;liq.long_liq_usdandliq.short_liq_usdare one; theflow.buy_volfamily is free). A script may load 4 at once on Beginner, 8 on Plus and 16 on Pro and Elite. Series read inside a request count too, once per requested market and timeframe (below). Past that, the extra series arenaand the legend says how many were not loaded. See Limits.
#What the legend tells you
A script that reads ChartDeck data gets the data's notes in its legend row automatically, the same notes the built-in studies show:
- where a series' history starts when that is inside the chart ("OI history starts 2026-09-02 06:00 UTC on BloFin"), so a short history never looks like a broken script;
- when your plan's window cut the history ("history limited to 30 days on your plan");
- which venues an aggregated series summed, and which of them ChartDeck recorded itself;
- a series not available on this market ("Funding rate: not available on Coinbase"), not in your plan, or past your plan's number of series;
- the source of data that requires one: a script reading
etf.net_flowalways shows "Flow data: Farside Investors (farside.co.uk)". The author cannot remove it.
#Data and requests
Outside a request, a data series is the chart's own market, aligned to its bars. Inside a request expression it is the requested market at the requested timeframe: ChartDeck loads it for that market with the same loaders, aligns it to the requested bars, and the request lines the values up with your chart like any other value.
//@chartscript 1
indicator("OI: this coin against ETH")
// each market's open interest change over the last 24 bars, in %
const myChange = (oi.close - oi.close[24]) / oi.close[24] * 100
const ethChange = request.market("BINANCE:ETHUSDT", "", (oi.close - oi.close[24]) / oi.close[24] * 100, { at: request.developing })
plot(myChange, "This market", color.accent)
plot(ethChange, "ETH", color.muted)request.tf("1D", oi.close)is the daily open interest of your market (its own daily rows, not a sample of the chart's).- A request on the chart's own market and timeframe reads the chart's own values.
- A request that reads data at
request.developingon a higher timeframe of your own market reads the last closed higher bar (as for another market): the higher bar's data so far is not known from the chart's bars. flow.buy_vol,flow.sell_vol,flow.deltaandflow.buy_sharecome from the requested bars' own taker volume, so they have values where that market's candles carry it (Binance, Aster).- Each requested market and timeframe that reads data loads its own series and counts toward your plan's data series per script. The first draw waits for them, as it waits for the chart's own series.
- A seconds timeframe (
"10S") carries no data series: inside such a request they readna. - The per-bar series of footprints (
fp.*), the chart's Big trades (flow.big_*) and the liquidation candles (liq.long_liq_usd,liq.short_liq_usd) work inside a request too, at the requested timeframe:request.lower_tf("1", fp.delta)gives each bar its 1-minute footprint deltas. - Record data stays the chart's: trade prints, liquidation levels, the order book, volume at price, the economic calendar, and the lists
fp.rows,fp.delta_at,fp.since,flow.big_trades,flow.big_since,flow.big_threshold,liq.eventsandliq.events_sincereadnaor empty inside a request, with warningCS3124.
#Protected scripts and script alerts
A protected Community script and a script alert run on ChartDeck's servers. Those runs read the same series, fetched by the server for the chart's market, with the same paging and the same alignment, for the plan of the member who looks at the chart (a protected script) or the plan of the alert's owner (a script alert). Two members on different plans watching one protected script each get their own plan's data. They run on exactly the same bars as the script on a chart (bars per run), so the series start at the same bar. Server runs do not cover tick and range charts.
#Examples
#Funding turns positive with rising open interest
//@chartscript 1
indicator("Funding flip with OI", { overlay: true })
const lookback = input.int(12, "OI change over (bars)", { minval: 1, maxval: 200 })
const oiUp = oi.close > oi.close[lookback]
const flip = ta.crossover(funding.rate, 0)
plotshape(flip && oiUp, "Positive funding, OI rising", shape.triangleup, location.belowbar, color.up, { size: size.small })
alert.on(flip && oiUp, "Funding flip", "Funding turned positive while open interest rose")#Annualised funding, any venue
//@chartscript 1
indicator("Funding, annualised", { format: format.percent })
const perYear = funding.rate * (24 / nz(funding.interval_hours, 8)) * 365
plot(perYear, "Annualised funding %", perYear >= 0 ? color.up : color.down, { style: plot.style_columns })
hline(0, "Zero", color.muted)#Delta divergence from the bars' own taker volume
//@chartscript 1
indicator("Delta against price")
const len = input.int(20, "Length", { minval: 2, maxval: 200 })
// cumulative delta over the last `len` bars (na where the venue's candles carry no taker volume)
const sumDelta = math.sum(nz(flow.delta), len)
const priceUp = close > close[len]
plot(sumDelta, "Delta over the window", sumDelta >= 0 ? color.up : color.down, { style: plot.style_columns })
bgcolor(priceUp && sumDelta < 0 ? color.new(color.down, 85) : !priceUp && sumDelta > 0 ? color.new(color.up, 85) : na)#Liquidation spikes (Pro)
//@chartscript 1
indicator("Liquidation spikes", { overlay: true })
const mult = input.float(4, "Spike = this many times the average", { minval: 1, step: 0.5 })
const total = nz(liq.total_usd)
const avg = ta.sma(total, 48)
const spike = avg > 0 && total > mult * avg
plotshape(spike && nz(liq.long_usd) > nz(liq.short_usd), "Longs flushed", shape.triangleup, location.belowbar, color.up)
plotshape(spike && nz(liq.short_usd) >= nz(liq.long_usd), "Shorts squeezed", shape.triangledown, location.abovebar, color.down)#Binance's open interest on any chart
//@chartscript 1
indicator("This venue's OI against Binance")
// both in USD: how big is this venue next to Binance, and is the money moving the same way?
const share = oi.usd / oi.ref_usd * 100
plot(share, "This venue as % of Binance", color.accent)
plotshape(ta.change(oi.ref, 12) > 0 && ta.change(oi.close, 12) < 0, "Binance adds, this venue cuts", shape.circle, location.top, color.muted)#All-exchange CVD against price (Pro)
//@chartscript 1
indicator("All-exchange CVD divergence")
const len = input.int(48, "Look back (bars)", { minval: 5, maxval: 500 })
// the coin's taker flow over every exchange, perpetuals and spot apart
plot(flow.agg_perp_cvd, "Perpetuals CVD", color.accent)
plot(flow.agg_spot_cvd, "Spot CVD", color.cyan)
const priceUp = close > close[len]
const spotDown = flow.agg_spot_cvd < flow.agg_spot_cvd[len]
bgcolor(priceUp && spotDown ? color.new(color.down, 88) : na, { title: "Price up, spot selling" })#OI-weighted funding against this venue (Pro)
//@chartscript 1
indicator("Venue funding vs the market")
const gap = funding.rate * (8 / nz(funding.interval_hours, 8)) - funding.agg_weighted
plot(gap, "This venue minus the OI-weighted market, % per 8 h", gap >= 0 ? color.up : color.down, { style: plot.style_columns })
hline(0, "Zero", color.muted)