Exchange and Symbol Format

The exchange ids and the venue-native symbol spellings an Indicator uses everywhere a market is named: pinned inputs, om metric get and om metric series, watch…

The exchange ids and the venue-native symbol spellings an Indicator uses everywhere a market is named: pinned inputs, om metric get and om metric series, watch conditions, and om open. The vocabulary is the same one kScript (legacy) uses, so a symbol that worked in a source(...) call works in an input(...) pin.

Where the vocabulary is used

A market is always the pair exchange + symbol, and the two travel together:

  • Pinned inputs in the file: input("btc", ohlcv.close, { symbol: "BTCUSDT", exchange: "BINANCE_FUTURES" }). A lone symbol or a lone exchange is refused at the sheet, because half a pin names a market that does not exist. Pins are honored on your machine; the chart reads its own market for every input.
  • Evaluation on your machine: om metric get and om metric series take --symbol and --exchange for the market the unpinned inputs follow, plus --interval in either spelling (1h or HOUR).
  • Watch conditions: the selector block names exchange, symbol, and interval ({ "exchange": "BINANCE_FUTURES", "symbol": "BTCUSDT", "interval": "HOUR" }); an edge operator requires the interval.
  • Charts: om open @scope/name and om chart indicator add place a package on the chart's own market.

Example: one market on three venues

Three pinned closes of the same asset, spelled the way each venue spells it, and two spreads between them. The first input stays unpinned so the package follows the market it is evaluated on:

import { input, line, lower, ohlcv, output } from "./sdk/declare";
import { in_binance_perp, in_binance_spot, in_close, in_coinbase } from "./gen/inputs";
import { emitRow, out_basis_pct, out_coinbase_gap_pct } from "./gen/outputs";

input("close", ohlcv.close);
// Every pin names the venue's own spelling of the market, and symbol and exchange always pin together.
input("binance_spot", ohlcv.close, { symbol: "BTCUSDT", exchange: "BINANCE", description: "Binance spot, joined form" });
input("binance_perp", ohlcv.close, { symbol: "BTCUSDT", exchange: "BINANCE_FUTURES", description: "Binance perpetual, joined form" });
input("coinbase", ohlcv.close, { symbol: "BTC-USD", exchange: "COINBASE", description: "Coinbase spot, hyphen form" });
output("basis_pct", line, lower, { unit: "%", description: "Binance perp premium over Binance spot" });
output("coinbase_gap_pct", line, lower, { unit: "%", description: "Coinbase spot over Binance spot" });

let basis: f64 = NaN;
let gap: f64 = NaN;

export function init(): void {}

export function state(): i32 {
  const spot = in_binance_spot();
  if (isNaN(spot) || spot <= 0.0) return 0;
  basis = ((in_binance_perp() - spot) / spot) * 100.0;
  gap = ((in_coinbase() - spot) / spot) * 100.0;
  return 1;
}

export function finalize(): void {
  out_basis_pct(basis);
  out_coinbase_gap_pct(gap);
  emitRow();
}

export function reset(): void {
  basis = NaN;
  gap = NaN;
}

The unpinned close is never read by the code; it is the grid every pinned input aligns to. Install the package and evaluate it against the market you want the spreads on:

om wrun install ./venue-spreads --replace
om metric series --metric wrun/@you/venue-spreads/basis_pct --symbol BTCUSDT --exchange BINANCE_FUTURES --interval 1h --bars 48

Exchange reference table

Exchange ids are the data plane's spelling, always uppercase. Symbols are venue-native: each venue's own separator, or none. The format column shows the venue's convention with an example market; om symbols --exchange <id> lists the exact symbols a venue serves.

ExchangeCategorySymbol formatExample
BINANCESPOTBTCUSDTBitcoin to Tether (spot)
BINANCE_FUTURESPERPETUALBTCUSDTBTC/USDT perpetual
BINANCE_DELIVERYdated futuresvenue-nativeBTC dated contracts
BITFINEXSPOTBTCUST or BTC:USDBitcoin to USD (spot)
BITFINEX_DERIVATIVESPERPETUALBTCF0:USTF0BTC perpetual
BITGETPERPETUALBTCUSDTBTC/USDT perpetual
BITMEXPERPETUALXBTUSDBitcoin to USD
BITSTAMPSPOTBTCUSDBitcoin to USD (spot)
BYBITPERPETUALBTCUSDTBTC/USDT perpetual
BYBIT_SPOTSPOTBTCUSDTBitcoin to USDT (spot)
COINBASESPOTBTC-USDBitcoin to USD (spot)
DERIBITPERPETUALBTC-PERPETUAL, BTC_USDC-PERPETUALBTC/USD and BTC/USDC perpetuals
GATE_IOSPOTBTC_USDCBitcoin to USDC (spot)
GATE_IO_FUTURESPERPETUALBTC_USDTBTC/USDT perpetual
HUOBISPOTvenue-nativespot markets
HUOBI_DM_SWAP, HUOBI_DM_LINEAR_SWAPPERPETUALvenue-nativecoin- and USDT-margined swaps
HYPERLIQUIDSPOTHYPE-USDCHYPE to USDC (spot)
HYPERLIQUID_FUTURESPERPETUALBTCBTC perpetual (the bare base asset)
HYPERLIQUID_HIP3PERPETUALvenue-nativeHIP-3 perpetuals
OKEXSPOTBTC-USDTBitcoin to USDT (spot)
OKEX_FUTURESdated futuresBTC-USDT-251226BTC future (Dec 26, 2025)
OKEX_SWAPPERPETUALBTC-USDT-SWAPBTC/USDT perpetual swap
UPBITSPOTKRW-USDTKorean won to USDT
CMEdated futuresvenue-nativelisted futures
POLYMARKETprediction marketsthe 66-character conditionIdone outcome market; read through the odds source

Spot venues that have a derivatives twin pair up in the data plane (BINANCE with BINANCE_FUTURES, BYBIT_SPOT with BYBIT, OKEX with OKEX_SWAP, GATE_IO with GATE_IO_FUTURES, HYPERLIQUID with HYPERLIQUID_FUTURES); the aggregated CVD recipe leans on exactly that pairing.

Discover instead of guess

A guessed id is an input that never gets a row. The CLI lists the live vocabulary:

om exchanges
om symbols --exchange OKEX_SWAP --format json
om markets --exchange HYPERLIQUID_FUTURES
om resolve "btc perp on okx"

om exchanges prints every id and its category; om symbols the exact symbols one venue serves; om markets the tradeable markets with their metadata; om resolve turns a phrase into the exchange + symbol pair the other commands take.

Notes

Case sensitivity. Exchange ids are uppercase (BINANCE, never binance), and symbols are matched as the venue spells them. Interval short forms are case-sensitive too: 1m is a minute and 1M is a month, which is why the data plane's own names (MINUTE, HOUR, FOUR_HOURS, DAY, WEEK) are the safe spelling in a sheet or a watch selector.

Separators vary. Hyphens (BTC-USD), underscores (BTC_USDT), colons (BTC:USD), or nothing (BTCUSDT), per venue. The same asset is a different string on every venue, so a package that pins several venues carries one spelling per pin; there is no normalized symbol in a pin.

Data availability. Not every source exists for every venue and symbol: funding, open interest, and liquidations are perpetual-venue feeds, options tenors are Deribit's, and the celled book class needs a block_size the venue serves (om block-sizes --exchange <id> lists them). An input on a market the venue does not serve delivers no rows; on the chart, the chart names the source it cannot serve.

Dated futures and options. Use the format the venue publishes; YYMMDD in an OKX future is the expiry. Dated books are neither spot nor perpetual, so the CLI leaves their category unclassified rather than guessing.

Polymarket. An odds input names one outcome market by its conditionId (0x plus 64 hex characters), never the market slug or the event, with outcome YES or NO; the exchange is implicit and refused if written (Data sources).