What you can read
A wrun indicator reads the market under the candles. Every level of the
order book, buy and sell volume as the exchange tagged each trade, volume
at each price and in each trade size, open interest, funding and
liquidations, the live options chain with its greeks, ETF flows and
economic series: each reaches your code as numbers, lined up bar for bar
with the chart. One input line asks for a feed and onBar() reads it,
with no fetch call and no network.
What you can build from these feeds:
- Absorption. The bars where heavy buying or selling failed to move price, from the exchange's own trade tags (Absorption).
- A value area. Volume at every price, folded into a point of control and a value area on the price axis (Volume profile and value area).
- Positioning regimes. Open interest against price, split into new longs, new shorts, short covering and long closing (Positioning regimes).
- Liquidation bursts. Forced buying and selling in USD, tagged on price when one side jumps past its norm (Liquidation bursts).
- A live gamma map. Gamma at every strike, the flip and the call and put walls from the options chain, and whether dealers are long or short gamma where spot trades (Gamma map).
- Book walls. The heavier side of the order book near the price, the dollars resting by distance from the mid and the biggest bid and ask walls, kept current on the live bar (Order book HUD).
- ETF flows. Each day's net spot-ETF flow under the chart, with the running total (ETF flows).
| Group | What you get | Charts |
|---|---|---|
| Order flow | Buy and sell volume, as the exchange tagged each trade | Crypto, prediction markets |
| The footprint: buy and sell at each price | Crypto, prediction markets | |
| Volume by trade size | Crypto | |
| The order book, up to 500 levels a side | Crypto, prediction markets | |
| Long and short liquidations | Crypto perpetuals | |
| Positioning | Open interest | Crypto perpetuals, prediction markets |
| Funding and the long/short ratio | Crypto perpetuals | |
| Options and volatility | Implied volatility, skew and DVOL | BTC, ETH |
| Options open interest and volume | BTC, ETH | |
| The options chain, with greeks | Any coin an options venue lists | |
| Beyond the venue | Spot-ETF flows, holdings and premium | BTC, ETH, SOL |
| Ethena collateral | BTC, ETH | |
| Bitfinex margin funding | Coins Bitfinex lends | |
| Token supply, economic series, Binance's treasury | Every chart | |
| Polymarket odds | Crypto, prediction markets | |
| Price and time | Candles, and each bar's time, trade date and session | Every chart |
| Other markets and timeframes | Another market's candles: crypto, stocks, forex, gold and silver | Every chart |
| A coarser timeframe, or its closed candles as a stream | Every chart | |
| The finer bars inside each bar | Charts of 2 minutes and up |
One line per feed
Name a feed once at the top of the file. Read this bar's value in
onBar().
- Candles: the chart's own bars set the rows, one per bar.
- Buy and sell volume: two numbers on every row, buyers up and sellers down.
- Open interest: one number on every row.
- ETF flow: one number a day. It lands on the day's first bar, and the bars after it carry it.
onBar()runs once per row and reads every feed on that row.
// at the top of the file: the feed, under a name you pick
input("oi", oi.close);
// inside onBar(): this bar's value
const oi = in_oi();Knobs appear only when a feed has a choice to make: a side, a tenor, a fund, a venue.
Order flow
Who bought, who sold, at which price and in what size, and what still rests in the book.
// buy and sell volume, in coins
input("buy", trades.volume, { side: "BUY" });
input("sell", trades.volume, { side: "SELL" });
// the footprint: [low, high, buy, sell] at each price
input("profile", volume_profile.cells, { max_cells: 8192 });
// [bucket, buy_usd, sell_usd, buy_count, sell_count] per size
input("sizes", trade_volume_by_size.cells, { max_cells: 7 });
// the book: [price, size, side] per level
input("book", book.cells, { max_cells: 1000, block_size: 10 });
// liquidations in USD, both sides unless side picks one
input("liq", liquidations.liquidations, { missing: "zero" });Buy minus sell, summed bar after bar, is CVD. Size buckets run from 1,
trades under 1K USD, to 7, trades of 10M and up, each fill at its own
size; a long is liquidated by a forced sell, so side: "SELL" reads
longs.
Positioning
Who holds the market, what holding it costs, and which way they lean.
// open interest, in USD
input("oi", oi.close, { missing: "nan" });
// the funding rate, in percent per hour
input("funding", funding.rate_close, { missing: "zero" });
// longs over shorts, every account
input("ls", long_short_ratio.total_account, { missing: "nan" });Funding is normalized to one hour, so venues with different funding
intervals compare. The long/short ratio counts every account, or the
venue's top traders with top_trader_account or top_trader_position,
on charts of 5 minutes or coarser.
Options and volatility
What the options market prices in, by tenor and by strike.
// implied volatility and skew on Deribit, one tenor each
input("iv", implied_volatility.implied_volatility,
{ tenor: "ONE_M" });
input("skew", skew.skew, { tenor: "ONE_M", delta: 25 });
// the volatility index, DVOL, in index points
input("dvol", volatility_index.close);
// put open interest on Deribit, call volume on Binance
input("put_oi", options_oi.puts);
input("call_vol", options_volume.calls, { venue: "binance" });
// every listed contract, on the live bar
input("chain", options_chain.cells, { max_cells: 2000 });Tenors are ONE_W, ONE_M, TWO_M, THREE_M and SIX_M, and skew's
delta is 5, 15, 25 or 35. The chain fills the live bar only, one
[strike, expiry_ms, side, oi, gamma, delta, mark_iv, underlying, multiplier, vega] row per contract.
Beyond the venue
What moves the coin from outside the exchange: ETF money, supply, rates and the odds.
// spot-ETF flow (USD, daily), holdings (coins), premium (%)
input("flow", etf_flow.flow_usd, { fund: "all", missing: "nan" });
input("held", etf_holdings.holdings, { fund: "all" });
input("premium", etf_premium.premium_rate, { fund: "IBIT" });
// Ethena collateral in USD; Bitfinex funding provided
input("ethena", ethena_positions.collateral);
input("provided", bitfinex_funding.funding_size);
// market cap, daily; the US 10-year yield; Binance's own BTC
input("mcap", token_supply.marketcap, { token: "Bitcoin" });
input("us10y", economic.value,
{ publisher: "FRED", series: "DGS10" });
input("treasury", treasury_balance.balance, { asset: "BTC" });
// a Polymarket market's odds, 0 to 1, by condition id
input("yes", odds.close, { symbol: "0x...", outcome: "YES" });A token is named the way its series spells it (Bitcoin, never BTC),
and a Polymarket market by its condition id. A day's ETF flow is known
only after the US session, so on an intraday chart it shows the day, not
a signal you had at the open.
Price and time
The chart's candles and clock; the candle needs no input line.
// this bar's candle
bar.open(); bar.high(); bar.low(); bar.close(); bar.volume();
// its open, in epoch seconds UTC
bar.time();
// the exchange's trade date
input("day", time.trade_date);
// 1 regular, 2 pre-market, 3 after-hours, 0 closed
input("phase", time.session);On US stocks the session follows New York's pre-market, regular and
after-hours sessions; a market without sessions reads 1 on every bar.
Other markets and timeframes
Another market beside yours, a higher timeframe, or the bars inside each bar.
// another market's candles
input("btc", ohlcv.close,
{ symbol: "BTCUSDT", exchange: "BINANCE_FUTURES" });
// a coarser timeframe, and its closed candles as a stream
input("daily", ohlcv.close, { interval: "1d" });
input("d", candles.cells, { interval: "1d", bars: 400 });
// the finer bars inside each bar
input("m1", intrabar.cells, { interval: "1m", max_cells: 60 });Only candle feeds take a market pin, symbol and exchange together: a
crypto market, a US stock or ETF (POLYGON), a forex pair, gold or silver
(FX_OTC, XAU/USD, XAG/USD), never a CME market. A coarser candle counts only once it
closes, so history shows what you would have seen live.
What each chart has
Perpetuals carry the most. Stocks and forex carry candles and a few series.
| Feeds | Crypto perpetual | Crypto spot | Prediction market | US stocks and forex | CME futures |
|---|---|---|---|---|---|
| Order flow | ● | ◐ no liquidations | ◐ trades, footprint, book | ○ | ○ |
| Positioning | ● | ○ | ◐ open interest | ○ | ○ |
| Options | ◐ by coin | ◐ by coin | ○ | ○ | ○ |
| Beyond the venue | ◐ by coin | ◐ by coin | ◐ odds, supply, economic, treasury | ◐ supply, economic, treasury | ○ |
| Price and time | ● | ● | ● | ● | ○ |
| Other markets | ● | ● | ● | ● | ○ |
On CME futures only OpenMarket's official indicators run; your drafts and other authors' indicators do not. A stock traded on a crypto venue is a crypto chart: the venue decides what a chart has, not the ticker.
Blocks, not numbers
A .cells feed hands you the whole bar: every level of the book, every
price of the footprint.
- One number per bar: open interest gives every bar a single value,
read with
in_oi(). - A block per bar: the book gives the circled bar a run of numbers,
read with
in_book_view(). - Rows of three: every three numbers are one level,
[price, size, side], with+1a bid and-1an ask. i += 3: the loop steps one row at a time, up to the countin_book_cells()returns.
function onBar(): void {
const n = in_book_cells(); // this bar's count: 0 empty, -1 none
if (n <= 0) return;
const cells = in_book_view(); // the block itself, no copy
for (let i = 0; i + 2 < n; i += 3) {
const price = cells[i];
const size = cells[i + 1];
const side = cells[i + 2]; // +1 a bid, -1 an ask
}
}Every block reads the same way, stepping by its row's width: 4 for the
footprint, 5 for size buckets, 6 for candles, 10 for the chain. Only the
first n numbers are this bar's, so bound every loop by the count.
A block larger than max_cells stops the run instead of being cut. The
first input sets the rows and cannot be a block, so a file that reads
blocks starts with input("close", ohlcv.close);.
When a bar has no reading
missing decides what an empty bar reads: the last value, NaN or
zero.
// "carry", the default: the last value
input("funding", funding.rate_close);
// "nan": a bar without a reading reads NaN, never a guess
input("oi", oi.close, { missing: "nan" });
// "zero": a quiet bar reads 0
input("liq", liquidations.liquidations, { missing: "zero" });Blocks never carry: a bar without one gets an empty block. A feed the chart cannot serve on this market stops the run and names the feed, on the indicator's legend and in the editor's Console.
Four feeds, one file
Taker delta, the change in open interest and liquidations, in USD per bar.
input("close", ohlcv.close); // first: it sets the rows
input("buy", trades.volume, { side: "BUY" }); // in coins
input("sell", trades.volume, { side: "SELL" });
input("oi", oi.close, { missing: "nan" }); // in USD
input("liq", liquidations.liquidations, { missing: "zero" });
output("delta", histogram, lower,
{ color: "#94a3b8", label: "Delta, USD", format: "si" });
output("oi_change", line, lower,
{ color: "#c2410c", label: "OI change, USD", format: "si" });
output("liquidated", line, lower,
{ color: "#64748b", label: "Liquidated, USD", format: "si" });
let lastOi = NaN; // open interest on the last bar that had one
function onBar(): void {
const close = bar.close();
if (isNaN(close)) return;
out_delta((in_buy() - in_sell()) * close); // coins to USD
const oi = in_oi();
out_oi_change(oi - lastOi); // NaN until two readings
if (!isNaN(oi)) lastOi = oi;
out_liquidated(in_liq());
}Paste it under the //@lang=wrun-ts marker and press Run on a crypto
perpetual chart. On spot, open interest reads NaN and liquidations zero,
as their missing knobs say.
The close line stays first: it sets the rows the other feeds line up
with, and bar.close() reads through it. Every knob, unit and edge case
is on Data sources; pins are on
Multi-source and
Multi-timeframe.