What you can read

View as MarkdownOpen the editor

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).
GroupWhat you getCharts
Order flowBuy and sell volume, as the exchange tagged each tradeCrypto, prediction markets
The footprint: buy and sell at each priceCrypto, prediction markets
Volume by trade sizeCrypto
The order book, up to 500 levels a sideCrypto, prediction markets
Long and short liquidationsCrypto perpetuals
PositioningOpen interestCrypto perpetuals, prediction markets
Funding and the long/short ratioCrypto perpetuals
Options and volatilityImplied volatility, skew and DVOLBTC, ETH
Options open interest and volumeBTC, ETH
The options chain, with greeksAny coin an options venue lists
Beyond the venueSpot-ETF flows, holdings and premiumBTC, ETH, SOL
Ethena collateralBTC, ETH
Bitfinex margin fundingCoins Bitfinex lends
Token supply, economic series, Binance's treasuryEvery chart
Polymarket oddsCrypto, prediction markets
Price and timeCandles, and each bar's time, trade date and sessionEvery chart
Other markets and timeframesAnother market's candles: crypto, stocks, forex, gold and silverEvery chart
A coarser timeframe, or its closed candles as a streamEvery chart
The finer bars inside each barCharts 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().

Every feed on the chart's rows: the candles set one row per bar; buy and sell volume and open interest give each row its numbers; a daily ETF flow lands on the first bar of its day and later bars carry it; onBar() runs once per row and reads every feed on that row, the column circled in orange.a new dayonBar()candlesbuy and sellopen interestETF flow
  1. Candles: the chart's own bars set the rows, one per bar.
  2. Buy and sell volume: two numbers on every row, buyers up and sellers down.
  3. Open interest: one number on every row.
  4. ETF flow: one number a day. It lands on the day's first bar, and the bars after it carry it.
  5. onBar() runs once per row and reads every feed on that row.
wrun
// 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.

wrun
// 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.

wrun
// 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.

wrun
// 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.

wrun
// 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.

wrun
// 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.

wrun
// 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.

FeedsCrypto perpetualCrypto spotPrediction marketUS stocks and forexCME 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 against a block per bar: open interest gives each bar one value, read with in_oi(); the book gives the circled bar a block, read with in_book_view() as a flat run of numbers where every three, price, size and side, are one level, so the loop steps i by three.1.82B1.83B1.83B1.85B1.84B1.86Bin_oi()64210.03.2+164209.512.6+164212.50.8-1in_book_view()priceisizei+1sidei+2i += 3
  1. One number per bar: open interest gives every bar a single value, read with in_oi().
  2. A block per bar: the book gives the circled bar a run of numbers, read with in_book_view().
  3. Rows of three: every three numbers are one level, [price, size, side], with +1 a bid and -1 an ask.
  4. i += 3: the loop steps one row at a time, up to the count in_book_cells() returns.
wrun
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.

wrun
// "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());
}
BTCUSDT perpetual on Binance, 1 hour bars, Aug 10 to Aug 18, 2026Real output from OpenMarket's engine

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.