Order Books

What L2 order book data can be used for?

L2 data (market-by-price) includes bids and asks orders aggregated by price level and can be used to analyze among other things:

  • order book imbalance

  • average execution cost

  • average liquidity away from midpoint

  • average spread

  • hidden interest (i.e., iceberg orders)

We do provide L2 data both in CSV format as incremental order book L2 updates, tick level order book snapshots (top 25 and top 5 levels) as well as in exchange-native format via API and client libraries that can perform full order book reconstruction client-side.

What L3 order book data can be used for?

L3 data (market-by-order) includes every order book order addition, update, cancellation and match and can be used to analyze among other things:

  • order resting time

  • order fill probability

  • order queue dynamics

Historical L3 data is currently available via API for Bitfinex, Coinbase Exchange and Bitstamp - remaining supported exchanges provide L2 data only.

What is the maximum order book depth available for each supported exchange?

We always collect full depth order book data as long as exchange's WebSocket API supports it. Table below shows current state of affairs for each supported exchange.

exchange
order book depth
order book updates frequency

full order book depth snapshot and updates

real-time

full order book depth snapshot and updates

real-time

top 1000 levels initial order book snapshot, full depth incremental order book updates

real-time, dynamically adjusted

top 1000 levels initial order book snapshot, full depth incremental order book updates

real-time, dynamically adjusted

top 1000 levels initial order book snapshot, full depth incremental order book updates

100ms

top 100 levels initial order book snapshot and updates

real-time

top 400 levels initial order book snapshot and updates

real-time

top 400 levels initial order book snapshot and updates

real-time

top 400 levels initial order book snapshot and updates

real-time

top 400 levels initial order book snapshot and updates

real-time

top 150 levels initial order book snapshot and updates

30ms

top 150 levels initial order book snapshot and updates

30ms

top 150 levels initial order book snapshot and updates

30ms

top 150 levels initial order book snapshot and updates

100ms

top 100 levels initial order book snapshot and updates

real-time

top 100 levels initial order book snapshot and updates

real-time

full order book depth snapshot and updates

real-time

full order book depth snapshot and updates

real-time

top 1000 levels initial order book snapshot and updates

real-time

full order book depth snapshot and updates

real-time

full order book depth snapshot and updates

real-time

full order book depth snapshot and updates

real-time

top 25 levels initial order book snapshot and updates

real-time

full order book depth snapshot and updates

real-time

top 15 levels snapshots

real-time

top 30 levels initial order book snapshot and updates

20ms

top 100 levels initial order book snapshot and updates

real-time

top 1000 levels initial order book snapshot, full depth incremental order book updates

100ms

top 20 levels order book snapshots

unknown

top 30 levels order book snapshots

unknown

top 15 levels order book snapshots

200ms

top 15 levels order book snapshots

200ms

order book snapshots

unknown

top 400 levels initial order book snapshot and updates

real-time

full order book depth snapshot and updates

real-time

full order book depth snapshot and updates

real-time

top 1000 levels initial order book snapshot, full depth incremental order book updates

100ms

How are order book data snapshots provided?

Historical market data available via HTTP API provides order book snapshots at the beginning of each day (00:00 UTC) - see details.

We also provide custom order book snapshots with customizable time intervals from tick-by-tick, milliseconds to minutes or hours via client libs in which case custom snapshots are computed client side from raw data provided via HTTP API as well as via downloadable CSV files - book_snapshot_25 and book_snapshot_5 .

Do you collect order books as snapshots or in streaming mode?

Order books are collected in streaming mode - snapshot at the beginning of each day and then incremental updates. See details.

We also provide custom order book snapshots with customizable time intervals from tick-by-tick, milliseconds to minutes or hours via client libs in which case custom snapshots are computed client side from raw data provided via HTTP API as well as via downloadable CSV files - book_snapshot_25 and book_snapshot_5 .

How incremental_book_l2 CSV dataset is built from real-time data?

Cryptocurrency exchanges' real-time APIs vary a lot, but for L2 order book data they all tend to follow a similar flow: first, when a WS connection is established and subscription is confirmed, exchanges send an initial order book snapshot (all existing price levels or top x levels depending on exchange), and then start streaming order book update messages (often called deltas). Those updates, when applied to the initial snapshot, result in an up-to-date order book state at a given time.

circle-info

We do provide initial L2 snapshots in incremental_book_L2 dataset at the beginning of each day (00:00 UTC, more details), but also any time an exchange closes its real-time WebSocket connection, see details.

circle-info

Snapshot rows (is_snapshot=true) may contain price levels outside the nominal top-N depth advertised by the exchange (e.g., beyond top 1000 for Binance). This is because snapshots combine the exchange-provided snapshot with any incremental updates buffered during connection setup. Consumers should always reset their local order book state when encountering a new snapshot batch, regardless of depth.

Let's take FTX as an example and start with its snapshot order book message (which is frequently called 'partial' in exchange API docs as well).

Remaining bids and asks levels were removed from this sample message for the sake of clarity.

Such snapshot message maps to the following rows in CSV file:

exchange
symbol
timestamp
local_timestamp
is_snapshot
side
price
amount

ftx

ETH/USD

1601510401216632

1601510401316432

true

ask

359.8

8.101

ftx

ETH/USD

1601510401216632

1601510401316432

true

bid

359.72

121.259

... and here's a sample FTX orderbook update message.

Let's see how it maps to CSV format.

exchange
symbol
timestamp
local_timestamp
is_snapshot
side
price
amount

ftx

ETH/USD

1601510427184054

1601510427204046

false

ask

360.24

4.962

ftx

ETH/USD

1601510427184054

1601510427204036

false

ask

361.02

0

See this answer if you have doubts how to reconstruct order book state based on data provided in incremental_book_L2 dataset.

How can I reconstruct full order book state from incremental_book_L2 CSV dataset?

In order to reconstruct full order book state correctly from incremental_book_L2 data:

  • Rows before the first snapshot in the file should be skipped — they are buffered updates received before the exchange sent the initial snapshot after a connection restart.

  • For each row in the CSV file (iterate in the same order as provided in file):

    • only if the local timestamp of the current row is larger than the previous row local timestamp (local_timestamp column value) does it mean you can read your local order book state as consistent. Why? CSV format is flat where each row represents a single price level update, but most exchanges' real-time feeds publish multiple order book level updates via a single WebSocket message that need to be processed together before reading locally maintained order book state. We use local timestamp value here to detect all price level updates belonging to a single 'update' message.

    • if current row is a part of the snapshot (is_snapshot column value set to true) and previous one was not, reset your local order book state object that tracks price levels for each order book side as it means that there was a connection restart and exchange provided full order book snapshot or it was a start of a new day (each incremental_book_L2 file starts with the snapshot)

    • if current row amount is set to zero (amount column value set to 0) remove such price level (row's price column) from your local order book state as such price level does not exist anymore

    • if current row amount is not set to zero update your local order book state price level with new value or add new price level if not exist yet in your local order book state - maintain separately bids and asks order book sides (side column value)

Alternatively we do also provide top 25 and top 5 levels order book snapshots CSV datasets ready to download.

Can order book snapshots be empty?

Yes. For very illiquid instruments (e.g., deep out-of-the-money options or niche currency pairs) order book snapshots can be present but empty — containing no bid or ask levels. This is not a data gap; it reflects the actual state of the order book on the exchange at that time. Subsequent snapshots after reconnects may also be empty if the instrument remains illiquid.

Can historical order books reconstructed from L2 updates be crossed (bid-ask overlap) occasionally?

Although is should never happen in theory, in practice due to various crypto exchanges bugs and peculiarities it can happen (very occasionally), see some posts from users reporting those issues:

We do track sequence numbers of WebSocket L2 order book messages when collecting the data and restart connection when sequence gap is detected for exchanges that do provide those numbers. We observe that even in scenario when sequence numbers are in check, bid/ask overlap can occur.

When such scenario occurs, exchanges tend to 'forget' to publish delete messages for the opposite side of the book when publishing new level for given side - we validated that hypothesis by comparing reconstructed order book snapshots that had crossed order book (bid/ask overlap) for which we removed order book levels for the opposite side manually (as exchange didn't publish that 'delete'), with quote/ticker feeds if best bid/ask matches (for exchanges that provide those) - see sample code that implements that manual level removal logicarrow-up-right.

If you encounter a crossed book during reconstruction, the recommended approach is to remove overlapping levels from the opposite side. Additionally, crossed states are always resolved by the next snapshot reset (either at 00:00 UTC daily resubscription or after a WebSocket reconnect).

Last updated