DOCS/CONCEPTS

Symbology

One symbol per instrument across every venue. BTC-PERP on Hyperliquid and BTC-PERP on Binance are the same kind of contract with prices in the same units, so cross-venue queries need no lookup table.

Every row carries two symbols. symbol is ours and follows the rules below. venue_symbol is the venue's own string, unchanged, so you can always trace a row back to the venue's documentation or raw feed.

Format rules

InstrumentPatternExample
SpotBASE-QUOTEBTC-USDT, ETH-BTC, BTC-USD
Perpetual, main linearBASE-PERPBTC-PERP
Perpetual, second stablecoinBASE-USDC-PERPBTC-USDC-PERP
Perpetual, inverseBASE-USD-INV-PERPBTC-USD-INV-PERP
Dated futureBASE-DDMMMYYBTC-27MAR27
OptionBASE-DDMMMYY-STRIKE-C|PBTC-27MAR27-90000-C
  • Characters. Uppercase A–Z, digits and hyphens only. No slashes, underscores or lowercase, so symbols are safe in file names and URLs without escaping.
  • Main linear perpetual. BTC-PERP is the venue's main stablecoin-margined linear perpetual. That is the USDT contract on Binance, Bybit, OKX and Bitget, and the USDC contract on venues where USDC is the only linear margin, such as Hyperliquid and dYdX. The settlement asset is always in instruments.settle.
  • Second stablecoin. BTC-USDC-PERP names a USDC-margined perpetual on a venue whose BTC-PERP is USDT-margined. Dated futures and options take the same infix when a venue lists both variants (BTC-USDC-27MAR27).
  • Inverse. Coin-margined contracts carry -USD-INV: BTC-USD-INV-PERP, BTC-USD-INV-27MAR27. Prices are in USD; sizes are converted to base units like every other contract.
  • Dates. Expiry is the UTC date the contract expires, as DDMMMYY with an English month abbreviation. The expiry time of day is in instruments.expiry (08:00 UTC on most venues).
  • Strikes. Written in full without separators or trailing zeros: 90000, 2.5.
  • Asset codes. Normalized to the common ticker: Kraken's XBT becomes BTC, Bitfinex's UST (Tether) becomes USDT. Fiat stays fiat: BTC-USD on Coinbase is a different market from BTC-USDT.
  • Price units. Prices are never rescaled. Contracts quoted per 1,000 tokens keep the multiplier in the symbol, so 1000PEPE-PERP prices are 1,000 times PEPE-PERP prices. instruments.multiplier holds the factor and base is PEPE in both.

Venue mappings

Native symbols for the same instrument across venues. Cells marked n/a mean the venue does not list that contract. Columns for Phase 2 and 3 venues show the mapping we will apply once capture starts, subject to a data agreement with each exchange; see Roadmap for dates.

FDC symbolHyperliquidBinanceBybitOKXDeribitKrakenCoinbase
BTC-USDTn/aBTCUSDTBTCUSDTBTC-USDTn/aXBTUSDTBTC-USDT
BTC-USDn/an/an/an/an/aXBTUSDBTC-USD
BTC-PERPBTCBTCUSDTBTCUSDTBTC-USDT-SWAPBTC_USDC-PERPETUALPF_XBTUSDn/a
BTC-USDC-PERPn/aBTCUSDCBTCPERPBTC-USDC-SWAPn/an/an/a
BTC-USD-INV-PERPn/aBTCUSD_PERPBTCUSDBTC-USD-SWAPBTC-PERPETUALPI_XBTUSDn/a
BTC-26MAR27n/aBTCUSDT_270326n/aBTC-USDT-270326n/an/an/a
BTC-USD-INV-26MAR27n/aBTCUSD_270326BTCUSDH27BTC-USD-270326BTC-26MAR27FI_XBTUSD_270326n/a
BTC-26MAR27-90000-Cn/aBTC-270326-90000-CBTC-26MAR27-90000-CBTC-USD-270326-90000-CBTC-26MAR27-90000-Cn/an/a
1000PEPE-PERPkPEPE1000PEPEUSDT1000PEPEUSDTn/an/an/an/a
PEPE-PERPn/an/an/aPEPE-USDT-SWAPn/aPF_PEPEUSDn/a

Three rows deserve a second look:

  • Deribit's native BTC-26MAR27 is an inverse contract, so it maps to BTC-USD-INV-26MAR27. The same string means different contracts on different venues, which is why we never reuse a venue's symbol as our own.
  • Hyperliquid's BTC settles in USDC and still maps to BTC-PERP, because USDC is its only linear margin asset. Filter on instruments.settle if the margin asset matters to your analysis.
  • Bybit's options settle in USDC and Deribit's in BTC, yet both map to BTC-26MAR27-90000-C. Option premiums carry their currency in options_chain.premium_ccy.

The instruments table

instruments is the source of truth for every symbol: contract size, tick size, lot size, settlement asset, expiry, status and the period each set of values was in force. Reference data is versioned daily: we read every venue's instrument list once per UTC day, and each change opens a new row with valid_from and valid_to, so the specs in force on any date are one join away. All columns are listed on Schema reference.

venuesymbolvenue_symboltypesettlecontract_sizetick_sizestatus
hyperliquidBTC-PERPBTCperpUSDC11trading
hyperliquid1000PEPE-PERPkPEPEperpUSDC10000.000001trading
binanceBTC-USD-INV-PERPBTCUSD_PERPperpBTC100 USD0.1trading
okxBTC-PERPBTC-USDT-SWAPperpUSDT0.010.1trading
deribitBTC-USD-INV-26MAR27BTC-26MAR27futureBTC10 USD2.5trading

For inverse contracts, contract_size is expressed in USD per contract and contract_kind is inverse. Every size column in market-data tables has already been converted to base units at the price of the trade or level, so you only need contract_size if you want contract counts back.

Expiries

A dated symbol identifies one contract for its whole life, because the expiry date is part of the symbol. When it expires:

  • instruments closes the current row and opens a final one with status = expired and delisted_at set to the expiry time.
  • The venue's delivery or settlement price is written as the last mark_index row for the symbol, with ts_exchange equal to the expiry time.
  • History stays queryable under the same symbol indefinitely. The symbol is never reassigned.

We do not publish stitched continuous-futures series, because every desk rolls differently. To build one, list contracts with instruments(base="BTC", instrument_type="future"), order them by expiry and choose your own roll rule (fixed days before expiry, open-interest crossover, or volume crossover).

Renames and relistings

Venues rename tickers when a token rebrands or migrates, and they sometimes delist a contract and list a replacement. We handle the three cases differently, based on whether the venue kept the same order book and positions.

CaseWhat changesHow to query across it
Venue changes only its native stringNew instruments row with the new venue_symbol. symbol and instrument_id unchanged.Nothing to do: symbol is continuous.
Token rebrand, same book and positionssymbol changes (for example MATIC-PERP to POL-PERP), instrument_id stays.Query by instrument_id to get one series spanning both symbols.
Delisted and replaced by a new listingOld instrument ends with status = delisted; the new one gets a new instrument_id. The old row's successor_id points to the new one.Follow successor_id. We do not join the two series for you, since the books and open interest were not continuous.

A query by symbol always returns rows recorded under that symbol, and only those. Renames are announced in the changelog on the day we apply them.

Looking up symbols

Resolve symbols with the instruments endpoint. Filters combine; as_of returns the row in force at that moment, and history=true returns every row.

from fdc import Client

fdc = Client()

# every BTC perpetual we capture, across venues
perps = fdc.instruments(base="BTC", instrument_type="perp").to_pandas()

# native symbol to ours
row = next(iter(fdc.instruments(venue="hyperliquid", venue_symbol="kPEPE")))
print(row["symbol"], row["multiplier"])   # 1000PEPE-PERP 1000

# specs in force on a past date
spec = fdc.instruments(venue="hyperliquid", symbol="BTC-PERP",
                       as_of="2026-03-01T00:00:00Z")
RESPONSE
{
  "data": [{
    "venue": "hyperliquid", "symbol": "1000PEPE-PERP", "venue_symbol": "kPEPE",
    "source": "fdc_capture", "instrument_id": 300118, "instrument_type": "perp",
    "base": "PEPE", "quote": "USD", "settle": "USDC", "contract_kind": "linear",
    "contract_size": "1000", "multiplier": 1000, "tick_size": "0.000001",
    "lot_size": "1", "max_leverage": 10, "status": "trading",
    "listed_at": 1701129600000000000, "valid_from": 1784505600000000000, "valid_to": null
  }],
  "next_cursor": null
}

Instrument lookups are cheap and cached for 60 seconds at the edge. Resolve symbols once at startup and again on each UTC day rollover, rather than on every request.