Schema reference
Every venue, every dataset, one set of columns. A Binance trade and a Hyperliquid trade have the same shape, the same types and the same clock, so a query written for one venue runs on all of them.
This page documents schema version 0.9 (draft), which becomes 1.0 when the v1 API goes live with Phase 1. Column names on this page are final for 1.0; we may still add columns before then, and we will not remove or rename any without a changelog entry. Every response and file states the version it was written with (FDC-Schema-Version header on REST, fdc.schema_version in Parquet metadata).
Conventions
- Timestamps are int64 nanoseconds since the Unix epoch, UTC. No time zones, no ISO strings, no floats.
- Prices and sizes are
decimal128(38,18)in Parquet and strings in JSON and CSV, so nothing is lost to binary floating point. Trailing zeros are dropped: a venue's"0.10"becomes"0.1". - Sizes are in base units on every venue. Contract counts are converted with
contract_sizefrominstruments, which is why a Binance coin-margined contract and a Hyperliquid perpetual can be summed directly. - Enums are lowercase strings, dictionary-encoded in Parquet. New enum values can appear in minor versions; code that reads them should pass unknown values through instead of failing.
- Null means the venue does not publish the value for that row. We never fill a missing value with zero or a guess.
Types
| Type | Parquet | JSON |
|---|---|---|
| string | UTF-8 string | string |
| int32 / int64 | INT32 / INT64 | number |
| decimal128(38,18) | FIXED_LEN_BYTE_ARRAY, DECIMAL(38,18) | string, for example "104318.5" |
| float64 | DOUBLE | number |
| bool | BOOLEAN | true / false |
| enum | string, dictionary-encoded | string |
| list<string> | LIST of string | array of strings |
json-bigint) or use Parquet.Common columns
Every market-data table (all tables on this page except instruments, gaps and the two chain tables) starts with these columns, in this order.
| Column | Type | Description |
|---|---|---|
venue | enum | Venue id, lowercase: hyperliquid, binance, bybit, okx and so on. Full list on Venues. |
symbol | string | Normalized symbol, for example BTC-PERP or BTC-USDT. Rules on Symbology. |
venue_symbol | string | The venue's native symbol, unchanged: BTC on Hyperliquid, BTCUSDT on Binance, BTC-USDT-SWAP on OKX. |
ts_exchange | int64 | Venue timestamp in nanoseconds since the Unix epoch, UTC. Scaled up from the venue's native precision, so a millisecond venue always ends in six zeros. Null when the venue sends no timestamp for the message type. |
ts_capture | int64 | Our receive timestamp in nanoseconds since the Unix epoch, UTC, from a PTP-disciplined clock on the capture host. Null only on venue_archive rows, which we did not capture. See Timestamps & clocks. |
seq | int64 | Venue sequence number for the stream the row came from. Rows produced by one venue message share a seq. Null for venue_archive rows and for the few streams where a venue publishes no sequence (listed per venue on Venues). |
source | enum | fdc_capture for rows we captured live, venue_archive for rows backfilled from a venue's published archive, fdc_derived for rows we compute (candles, hourly book snapshots, extended fields). |
region | enum | Capture region that supplied the row after merging: apne1 (Tokyo), euw1 (Ireland), use1 (N. Virginia, from Phase 2). Null for venue_archive rows. |
A row's identity is (venue, symbol, seq) plus its position within the message. Where seq is null, use (venue, symbol, ts_exchange, trade_id) for trades.
Datasets
Columns below are listed after the common columns. Tags show the lowest plan that includes the dataset; plan details are on Pricing.
trades
One row per execution as printed by the venue. When a single aggressive order sweeps several levels, venues differ: some print one trade per maker, some print one aggregated trade. We keep the venue's granularity; taker_order_id lets you aggregate where it is published.
Primary key: (venue, symbol, trade_id)
| Column | Type | Description |
|---|---|---|
price | decimal128(38,18) | Execution price in quote currency. |
size | decimal128(38,18) | Executed quantity in base units (contracts converted to base using contract_size from instruments). |
side | enum | Aggressor side: buy when the taker bought, sell when the taker sold. Null on the rare venue records that do not identify the aggressor. |
trade_id | string | Venue trade id as published. Stored as a string because several venues use ids longer than 64 bits or non-numeric ids. |
notional | decimal128(38,18) | price × size in quote currency, computed by us. Inverse contracts report notional in USD. |
taker_order_id | string | Order id of the aggressing order, where the venue publishes it (Hyperliquid, Coinbase, Deribit). Null elsewhere. |
maker_order_id | string | Order id of the resting order. Joins to order_id in book_l3. |
is_block | bool | True for block trades and RFQ fills reported on the public tape (Deribit, OKX). False for on-book matches. |
{"venue":"hyperliquid","symbol":"BTC-PERP","venue_symbol":"BTC",
"ts_exchange":1789482600127000000,"ts_capture":1789482600131482113,
"seq":1094102785458213,"source":"fdc_capture","region":"apne1",
"price":"104318.5","size":"0.0421","side":"buy","trade_id":"812774190531627",
"notional":"4391.80885","taker_order_id":"141092377410","maker_order_id":"141092371988",
"is_block":false}quotes
Level 1: best bid and offer. One row each time either side of the top of book changes.
| Column | Type | Description |
|---|---|---|
bid_price | decimal128(38,18) | Best bid price. Null when the bid side is empty. |
bid_size | decimal128(38,18) | Total size resting at the best bid, base units. |
ask_price | decimal128(38,18) | Best ask price. Null when the ask side is empty. |
ask_size | decimal128(38,18) | Total size resting at the best ask, base units. |
origin | enum | venue when the venue publishes a top-of-book feed, book when we derive L1 from our L2 reconstruction. Both are emitted for venues that publish L1 separately, so you can compare them. |
candles
OHLCV bars built by us from trades, bucketed on ts_exchange (source = fdc_derived), or taken from a venue's licensed historical archive, where the agreement with that venue includes one (source = venue_archive). Intervals with no trades produce no row. For candles, ts_exchange is the time of the last trade in the bucket, ts_capture is when the bucket closed in our pipeline and seq is the sequence of the last trade.
Primary key: (venue, symbol, interval, ts_open)
| Column | Type | Description |
|---|---|---|
interval | enum | 1s, 1m, 5m, 1h or 1d. |
ts_open | int64 | Bucket start, nanoseconds, aligned to UTC. Buckets are assigned on ts_exchange so they line up with the venue's own charts. |
open | decimal128(38,18) | First trade price in the bucket. |
high | decimal128(38,18) | Highest trade price. |
low | decimal128(38,18) | Lowest trade price. |
close | decimal128(38,18) | Last trade price. |
volume | decimal128(38,18) | Traded quantity, base units. |
quote_volume | decimal128(38,18) | Traded notional, quote currency. |
buy_volume | decimal128(38,18) | Base volume where the aggressor bought. volume − buy_volume is aggressor-sell volume. |
trade_count | int64 | Number of trades. |
vwap | decimal128(38,18) | Volume-weighted average price. Null when trade_count is 0. |
book_l2
Price-level order book. One row per level per update. Order books are never backfilled: history starts on the day our capture of the venue began (Hyperliquid: November 2025). Read Order book depth before replaying: the semantics of snapshots, truncation and is_last matter.
| Column | Type | Description |
|---|---|---|
side | enum | bid or ask. |
price | decimal128(38,18) | Price level. |
size | decimal128(38,18) | New total size resting at this level, base units. "0" removes the level. Sizes are never incremental. |
is_snapshot | bool | True on rows of a full-depth snapshot, which replaces the whole book. Snapshots are written at every UTC hour (so each daily file opens with the 00:00 snapshot) and whenever the venue sends one, for example after a resync. False on deltas, which set one price level. |
snapshot_reason | enum | Why a snapshot was written: venue (sent by the venue, for example on subscribe or after a resync), file_start (the 00:00 UTC snapshot that opens each daily file) or checkpoint (our hourly full-depth snapshot, and the synthetic snapshot that starts a REST or SDK response). Null on deltas. |
is_last | bool | True on the final row of one venue message. Apply rows up to and including is_last before reading the book, so you never observe a half-applied update. |
checksum | int64 | On file_start and checkpoint snapshot rows: CRC32 of the top 25 levels of our snapshot, computed as described on Order book depth. Null on other rows. Venue checksum values stay in the raw tier. |
checksum_ok | bool | Result of validating the venue checksum against the raw message at capture time, on venues that publish one (OKX, Kraken, Bitget, Bitfinex). Null on venues without a checksum. |
level_count | int32 | Number of orders at the level, where the venue publishes it (OKX, Bitget, Kraken). Null elsewhere. |
book_l3
Order-by-order book: every add, modify, cancel and fill, on venues that publish order-level data. Hyperliquid L3 is built from validator node output, so it covers every order on the book.
| Column | Type | Description |
|---|---|---|
order_id | string | Venue order id. Stable for the life of the order, including across modifies that keep the id. |
event | enum | add, modify, cancel or fill. |
side | enum | bid or ask: the side the order rests on. |
price | decimal128(38,18) | Order price after the event. |
size | decimal128(38,18) | Remaining resting size after the event, base units. 0 after a full fill or a cancel. |
fill_size | decimal128(38,18) | Quantity filled by this event. Null unless event = fill. |
trade_id | string | For fills, the trade this fill belongs to. Joins to trades.trade_id. |
is_snapshot | bool | True on snapshot rows: add events that list every resting order in queue order, written at every UTC hour and after a resync. False on live events. |
snapshot_reason | enum | venue, file_start or checkpoint, as in book_l2. Null on live events. |
is_last | bool | Same meaning as in book_l2: final row of one venue message or block. |
prev_price | decimal128(38,18) | Price before a modify. Null for other events. |
prev_size | decimal128(38,18) | Resting size before the event. Lets you compute the change without keeping state. |
keeps_priority | bool | For modifies, whether the order keeps its place in the queue under the venue's rules (a size decrease usually does, a price change never does). |
order_type | enum | limit, post_only, ioc, stop or trigger, where the venue publishes it. Null otherwise. |
reduce_only | bool | Reduce-only flag, where published. |
book_l4
All book_l3 columns, in the same order, plus participant_id, counterparty_id and entity_id. Participant attribution comes from the venue, where it publishes it; entity_id needs the chain intelligence add-on. Chain-derived attribution across venues (L4+) lives in the chain tables.
| Column | Type | Description |
|---|---|---|
participant_id | string | Account identifier published by the venue. On Hyperliquid this is the trader's on-chain address, lowercase hex with 0x prefix (42 characters). Null where the venue does not attribute the order. |
counterparty_id | string | For fills, the participant on the other side. Null for other events. |
entity_id | string | Entity that controls participant_id, from our chain intelligence. Joins to chain_entities. Populated only with the chain intelligence add-on (included in Enterprise); null otherwise, and null when the address is not resolved. |
funding
Predicted and settled funding rates for perpetuals. One settled row per contract per interval; predicted rows at the venue's publication cadence. Venues settle every hour, every 4 hours or every 8 hours, so compare venues on rate_1h.
Primary key: (venue, symbol, kind, ts_funding, ts_exchange)
| Column | Type | Description |
|---|---|---|
kind | enum | predicted (published continuously during the interval) or settled (the rate actually paid at ts_funding). |
rate | decimal128(38,18) | Rate for one funding interval as published by the venue, as a fraction (0.0001 = 1 bp). Positive means longs pay shorts. |
interval_s | int32 | Funding interval in seconds: 3600 on Hyperliquid, 28800 on most Binance, Bybit and OKX contracts, with exceptions that change over time. |
rate_1h | decimal128(38,18) | rate scaled to one hour: rate × 3600 / interval_s. The column to compare across venues. |
rate_ann | decimal128(38,18) | rate_1h × 8760. Simple annualization, no compounding. |
ts_funding | int64 | Settlement time of the interval this rate applies to, nanoseconds. |
accrual | decimal128(38,18) | On predicted rows, the funding accrued so far in the current interval where the venue publishes it. On settled rows, equal to rate. |
mark_price | decimal128(38,18) | Mark price at publication, where the venue includes it. |
index_price | decimal128(38,18) | Index price at publication, where included. |
Hourly grid
Funding is also published on a UTC hourly grid, one row per perpetual per hour, so venues with different intervals line up without resampling. Grid rows carry the common columns plus:
| Column | Type | Description |
|---|---|---|
ts_grid | int64 | The UTC hour this row describes, nanoseconds. |
predicted_rate_1h | decimal128(38,18) | The latest predicted rate at ts_grid, scaled to one hour. |
stale | bool | True when the latest predicted rate is older than the venue's normal publication cadence allows, for example during an outage. |
age_s | int32 | Seconds between the predicted row used and ts_grid. |
open_interest
Open interest per derivative contract, at the venue's push cadence or sampled every 5 seconds where the venue only offers a REST endpoint.
| Column | Type | Description |
|---|---|---|
oi_contracts | decimal128(38,18) | Open interest in the venue's contract units, as published. |
oi_base | decimal128(38,18) | Open interest in base units, converted with contract_size. |
oi_notional_usd | decimal128(38,18) | Open interest in USD, using the venue's own valuation when published, otherwise oi_base × mark_price. |
origin | enum | stream when pushed by the venue, poll when sampled from a REST endpoint. Polled rows have seq null. |
liquidations
Forced closures as published by the venue. Coverage follows what each venue publishes and is confirmed with the venue before capture starts; see Venues.
| Column | Type | Description |
|---|---|---|
side | enum | Side of the liquidation order: sell closes a long, buy closes a short. |
price | decimal128(38,18) | Execution price, or the bankruptcy price where the venue reports only that (noted in price_kind). |
price_kind | enum | execution or bankruptcy. |
size | decimal128(38,18) | Liquidated quantity, base units. |
notional_usd | decimal128(38,18) | Liquidated notional in USD. |
method | enum | book (sent to the order book), backstop (taken over by a liquidity vault, such as Hyperliquid's HLP), adl (auto-deleveraging). |
participant_id | string | Participant liquidated, where the venue attributes it (Hyperliquid addresses). Null elsewhere. |
throttled | bool | True when the venue's feed is sampled (for example, at most one liquidation per symbol per second), so this row may stand for several liquidations. Sum notional_usd from such feeds with care. |
trade_id | string | Trade id of the resulting fill, where it can be matched. |
mark_index
Mark, index and oracle prices for derivatives, at the venue's publication cadence.
| Column | Type | Description |
|---|---|---|
mark_price | decimal128(38,18) | Venue mark price used for margin and liquidation. |
index_price | decimal128(38,18) | Venue index price (the spot reference). |
oracle_price | decimal128(38,18) | Oracle price where the venue runs a separate oracle (Hyperliquid validators publish one roughly every 3 seconds). Null elsewhere. |
basis_bps | float64 | (mark_price / index_price − 1) × 10,000, computed by us. |
options_chain
Top of book, mark, implied volatility and greeks per option, as published by the venue (planned for Deribit, OKX, Bybit and Binance). In v1 we do not compute IV or greeks ourselves. A full-chain snapshot is written every minute, with change rows in between.
| Column | Type | Description |
|---|---|---|
underlying | string | Normalized underlying, for example BTC. |
expiry | int64 | Expiry time, nanoseconds. |
strike | decimal128(38,18) | Strike price. |
option_type | enum | call or put. |
bid_price | decimal128(38,18) | Best bid, quoted in the venue's premium currency (see premium_ccy). |
ask_price | decimal128(38,18) | Best ask. |
bid_size | decimal128(38,18) | Size at best bid, contracts. |
ask_size | decimal128(38,18) | Size at best ask, contracts. |
mark_price | decimal128(38,18) | Venue mark price. |
premium_ccy | string | Currency the prices are quoted in: BTC on Deribit inverse options, USDT or USDC on linear ones. |
underlying_price | decimal128(38,18) | Underlying or forward price the venue used for greeks. |
mark_iv | float64 | Implied volatility of the mark, annualized, as a fraction (0.52 = 52%). |
bid_iv | float64 | IV of the best bid. Null where not published. |
ask_iv | float64 | IV of the best ask. Null where not published. |
delta | float64 | Venue-published delta. |
gamma | float64 | Venue-published gamma. |
vega | float64 | Venue-published vega. |
theta | float64 | Venue-published theta. |
open_interest | decimal128(38,18) | Open interest, contracts. |
is_snapshot | bool | True on rows of the full-chain snapshot written every minute, which lists every listed option once. False on change rows between snapshots. |
instruments
Reference data with full history, versioned daily. Each row describes one instrument for one period; a tick size change closes the old row and opens a new one. Join on (venue, symbol) with valid_from <= ts < valid_to to get the contract specs in force at any moment. Common columns present: venue, symbol, venue_symbol, source.
Primary key: (venue, symbol, valid_from)
| Column | Type | Description |
|---|---|---|
instrument_id | int64 | Our stable id. Survives venue renames where the venue keeps the same contract and book. |
instrument_type | enum | spot, perp, future or option. |
venue_market | string | The venue's own market or product type, where one native symbol is reused across markets (Binance spot and USD-M, Bitget product types). Null where the venue has a single market. |
base | string | Base asset, normalized (BTC, never XBT). |
quote | string | Quote asset. |
settle | string | Settlement asset. USDC for Hyperliquid perpetuals, BTC for inverse BTC contracts. |
contract_kind | enum | linear, inverse or quanto. Null for spot. |
contract_size | decimal128(38,18) | Base units per contract. Sizes in every other table are already converted with this value. |
multiplier | int32 | Symbol multiplier for contracts listed in units of 1,000 or 1,000,000 (for example 1000PEPE-PERP). 1 otherwise. |
tick_size | decimal128(38,18) | Minimum price increment. |
lot_size | decimal128(38,18) | Minimum size increment, base units. |
funding_interval_s | int32 | Default funding interval in seconds for perpetuals (3600, 14400 or 28800). Null for other instruments. Each funding row also carries the interval in force for that print in interval_s. |
min_notional | decimal128(38,18) | Minimum order notional, quote currency, where published. |
max_leverage | int32 | Maximum leverage at the time of the row, where published. |
expiry | int64 | Expiry, nanoseconds. Null for spot and perpetuals. |
strike | decimal128(38,18) | Strike, options only. |
option_type | enum | call or put, options only. |
status | enum | trading, halted, reduce_only, expired or delisted. |
listed_at | int64 | Venue listing time where the venue publishes it, otherwise the first trade we or the venue archive recorded. |
delisted_at | int64 | Delisting or expiry time. Null while live. |
successor_id | int64 | For a contract the venue replaced with a new listing, the instrument_id of the replacement. |
valid_from | int64 | Start of the period this row describes. Reference data is versioned daily: we take each venue's instrument list once per UTC day, and any change to tick size, lot size, status or symbol opens a new row starting at 00:00 UTC of the day it was first observed. |
valid_to | int64 | End of the period. Null for the current row. |
extended
Derived microstructure fields computed on ts_capture. Stored in long format: one row per field, variant and timestamp. The SDK (wide=True) and REST (layout=wide) can return a wide layout instead, with one column per field and variant (ofi_ml_l1, ofi_ml_l5, vpin and so on). Field definitions, parameters and units are on Extended fields.
| Column | Type | Description |
|---|---|---|
field | enum | Field key: ofi_ml, vpin, queue, cxl_fill, resil, lambda, markout or part. |
variant | string | Output of the field, such as l5 for OFI-ML or buy_1s for markouts. |
value | float64 | Field value. Units per field on Extended fields. |
on_grid | bool | True for rows on the 100 ms ts_capture grid, false for event-driven rows. |
emit | enum | grid or event. The same information as on_grid, as a string for readable filters. |
ts_available | int64 | When the value became knowable, nanoseconds on the ts_capture clock. Equal to ts_capture except on per-trade markout events (trade time plus 60 s) and sweep events (when the measurement closed). |
ref_id | string | On per-trade markout events, the trade_id. Null otherwise. |
chain_entities
Address-to-entity links from our blockchain intelligence. Core columns are below; the full column list, methods and coverage are on Chain intelligence.
| Column | Type | Description |
|---|---|---|
entity_id | string | Our entity id, stable across addresses and venues. |
address | string | On-chain address linked to the entity. |
chain | enum | Chain of the address. |
label | string | Entity label where one is established. |
entity_type | enum | Category: exchange, protocol, bridge or unlabeled. |
confidence | float64 | Confidence of the address-to-entity link, 0 to 1. |
valid_from | int64 | Start of the period the link is valid for. |
valid_to | int64 | End of the period. Null while current. |
chain_flows
On-chain transfers between resolved entities and venue wallets. Core columns are below; direction, trade links and confidence are documented on Chain intelligence.
| Column | Type | Description |
|---|---|---|
ts_block | int64 | Block timestamp, nanoseconds. |
chain | enum | Chain. |
tx_hash | string | Transaction hash. |
from_entity | string | Sending entity_id, where resolved. |
to_entity | string | Receiving entity_id, where resolved. |
asset | string | Asset transferred. |
amount | decimal128(38,18) | Amount in asset units. |
venue | enum | Venue on either end of the flow, when one side is a known venue wallet. |
gaps
Every interval that survived dual-region merging without data. A gap is recorded, never filled. How gaps are detected is on Data quality.
Primary key: gap_id
| Column | Type | Description |
|---|---|---|
gap_id | string | Stable id, for example gap_hl_20260611_0007. |
venue | enum | Venue id. |
dataset | enum | Affected dataset, such as book_l3. One outage can produce rows for several datasets. |
symbol | string | Affected symbol. Null when the whole venue stream was affected. |
seq_start | int64 | First missing sequence number, where the stream is sequenced. |
seq_end | int64 | Last missing sequence number. |
ts_start | int64 | Last good ts_capture before the gap, nanoseconds. |
ts_end | int64 | First good ts_capture after the gap. Null while the gap is still open on the live stream. |
reason | enum | seq_break (sequence discontinuity), checksum_mismatch (venue checksum failed), venue_outage (venue stopped publishing, including maintenance) or disconnect (our connections dropped in every region). |
regions_missing | list<string> | Regions that missed the interval. A row exists only when every capturing region missed it. |
resync | bool | True when the book was rebuilt from a fresh venue snapshot after the gap. The first book rows after ts_end are then a snapshot. |
detected_by | enum | How the gap was found: seq (venue sequence check), checksum (venue checksum), region_compare (the two regions' streams compared), snapshot_compare (a full venue snapshot disagreed with our book) or trade_reconcile (trade ids or counts checked against the venue's REST history after the day closes). |
detected_at | int64 | When our pipeline recorded the gap. |
revision | int32 | Data revision in which this row first appeared. |
note | string | Plain-text detail, such as the venue's maintenance notice id. |
Parquet layout
Bulk files follow one path pattern for every dataset. Access is granted per customer through cross-account S3 permissions; setup is on Bulk S3.
s3://fdc-archive/{dataset}/venue={venue}/date={YYYY-MM-DD}/{symbol}.parquet
s3://fdc-archive/book_l3/venue=hyperliquid/date=2026-09-15/BTC-PERP.parquet
s3://fdc-archive/trades/venue=hyperliquid/date=2026-09-15/ETH-PERP.parquet- Partitioning. One file per symbol per UTC day. A row belongs to the day of its
ts_capture. Rows withsource = venue_archive(from a venue's licensed historical archive, where the agreement with that venue includes one) have nullts_captureandseq; they are partitioned and sorted byts_exchange. - Sort order. Rows are sorted by
ts_capture, thenseq, then position within the message. Row group statistics onts_capturelet Arrow, DuckDB, Polars and Spark skip row groups when you filter on time. - Row groups. Up to 1,000,000 rows each. Compression is zstd level 3. Enum and string columns are dictionary-encoded.
- Book files start with the 00:00 UTC full-depth snapshot, so each daily file can be replayed on its own. Further snapshots follow at every UTC hour.
- Names use the normalized symbol. Characters outside
[A-Z0-9-]do not occur in symbols, so no escaping is needed.
File metadata
Each file carries key-value metadata in its Parquet footer.
| Key | Example | Meaning |
|---|---|---|
fdc.schema_version | 0.9 | Schema version the file was written with. |
fdc.dataset | book_l3 | Dataset name. |
fdc.revision | 1 | Data revision. Starts at 1; a corrected file is republished with the next number. See Data quality. |
fdc.row_count | 48210377 | Rows in the file, for a cheap completeness check. |
fdc.gap_count | 0 | Rows in gaps that overlap this file. |
fdc.seq_range | 1094042255360000-1095332003840411 | First and last seq in the file. |
fdc.sha256 | 9f2c…e41a | Digest of the row data, stable across re-encodings of the same revision. |
Reading a file
import polars as pl
path = "s3://fdc-archive/trades/venue=hyperliquid/date=2026-09-15/BTC-PERP.parquet"
df = (
pl.scan_parquet(path)
.filter(pl.col("ts_capture") >= 1789482600000000000) # 14:30 UTC
.select("ts_capture", "price", "size", "side")
.collect()
)SELECT venue, side, count(*) AS n, sum(size) AS base_volume
FROM read_parquet('s3://fdc-archive/trades/venue=*/date=2026-09-15/BTC-PERP.parquet',
hive_partitioning = true)
GROUP BY venue, side
ORDER BY venue, side;CSV and JSON
CSV and newline-delimited JSON contain the same columns in the same order as Parquet. CSV files have a header row, use a comma separator, quote only when a value contains a comma, and write null as an empty field. JSON rows omit nothing: null values are written as null. Both are gzip-compressed in bulk delivery (.csv.gz, .jsonl.gz).
Versioning
Within a major schema version, changes are additive: new columns go at the end of a table and new enum values may appear. Renaming a column, changing its type or changing its meaning requires a new major version, announced at least 90 days ahead on the changelog, with both versions served in parallel for at least 12 months. Data corrections are a separate mechanism (revisions, not schema versions) and are covered on Data quality.