Representing Variable-Depth Order Book Snapshots
Summary
This reference explains a data structure for representing a self-contained order book snapshot with variable numbers of bid and ask levels. Each side stores orders and a corresponding count for every level, alongside the instrument identifier, event flags, sequence number, and event and initialization timestamps. The two sides may have different lengths, including empty sides, and snapshots can exceed the structure’s inline capacity.
The document distinguishes this snapshot from incremental order book delta streams, which represent updates rather than a complete state. It also notes compatibility limits: legacy C interfaces and fixed-depth SBE encoding require ten levels on each side, even though the current structure accepts variable lengths. Code examples in Rust and Python illustrate construction, but the reference gives no trading strategy, market analysis, or empirical evidence about how snapshot depth should be used.
Key ideas
- An order book depth snapshot holds multiple bid and ask levels as a complete state.
- Each price level has a corresponding order count, and the two sides can have different lengths.
- The snapshot includes instrument, sequence, flags, and timing metadata.
- A depth snapshot is structurally different from a stream of incremental book updates.
- Legacy C and fixed-depth SBE formats require ten levels per side.
Tags
Full text
# OrderBookDepth
# OrderBookDepth
`OrderBookDepth` represents a snapshot with a variable number of bid and ask levels.
Use it when a venue publishes a self-contained depth snapshot rather than incremental deltas.
## Fields
| Field | Rust type | Python type | Required/default | Notes |
| --------------- | --------------------------- | ----------------- | ---------------- | ------------------------------------------ |
| `instrument_id` | `InstrumentId` | `InstrumentId` | Required | Instrument whose book is represented. |
| `bids` | `SmallVec<[BookOrder; 10]>` | `list[BookOrder]` | Required | Bid levels in book order. |
| `asks` | `SmallVec<[BookOrder; 10]>` | `list[BookOrder]` | Required | Ask levels in book order. |
| `bid_counts` | `SmallVec<[u32; 10]>` | `list[int]` | Required | Number of bid orders at each level. |
| `ask_counts` | `SmallVec<[u32; 10]>` | `list[int]` | Required | Number of ask orders at each level. |
| `flags` | `u8` | `int` | Required | `RecordFlag` bit field for event metadata. |
| `sequence` | `u64` | `int` | Required | Venue sequence number, or zero if absent. |
| `ts_event` | `UnixNanos` | `int` | Required | Event timestamp in nanoseconds. |
| `ts_init` | `UnixNanos` | `int` | Required | Initialization timestamp in nanoseconds. |
## Behavior
- Rust and PyO3 Python constructors accept variable-length sides. Each side requires one count
per order; bid and ask sides can have different lengths.
- Empty sides use empty sequences. The inline capacity is ten; larger snapshots allocate as needed.
- This type is not interchangeable with incremental `OrderBookDelta` streams.
The former `OrderBookDepth10` type name is gone. Catalog directories named `order_book_depth10`
still migrate, and Arrow files that stored that type in schema metadata still transcode. The
legacy C FFI and the fixed-depth SBE encoding require exactly ten levels per side.
## Example
```rust tab="Rust"
use nautilus_core::UnixNanos;
use nautilus_model::{
data::{BookOrder, OrderBookDepth},
enums::OrderSide,
identifiers::InstrumentId,
types::{Price, Quantity},
};
let bids = vec![BookOrder::new(OrderSide::Buy, Price::from("2500.10"), Quantity::from("3.5"), 1)];
let asks = vec![BookOrder::new(OrderSide::Sell, Price::from("2500.20"), Quantity::from("2.0"), 2)];
let depth = OrderBookDepth::new(
InstrumentId::from("ETHUSDT-PERP.BINANCE"),
bids,
asks,
vec![1],
vec![1],
0,
42,
UnixNanos::from(1_000_000_000),
UnixNanos::from(1_000_000_100),
);
```
```python tab="Python"
from nautilus_trader.model import InstrumentId
from nautilus_trader.model import Price
from nautilus_trader.model import Quantity
from nautilus_trader.model import BookOrder
from nautilus_trader.model import OrderBookDepth
from nautilus_trader.model import OrderSide
bids = [
BookOrder(
OrderSide.BUY,
Price.from_str(f"{2500.10 - i * 0.10:.2f}"),
Quantity.from_str("3.5"),
i + 1,
)
for i in range(3)
]
asks = [
BookOrder(
OrderSide.SELL,
Price.from_str(f"{2500.20 + i * 0.10:.2f}"),
Quantity.from_str("2.0"),
i + 11,
)
for i in range(2)
]
depth = OrderBookDepth(
instrument_id=InstrumentId.from_str("ETHUSDT-PERP.BINANCE"),
bids=bids,
asks=asks,
bid_counts=[1] * len(bids),
ask_counts=[1] * len(asks),
flags=0,
sequence=42,
ts_event=1_000_000_000,
ts_init=1_000_000_100,
)
```
## Related guides
- [QuoteTick](quote_tick.md) covers top-of-book data derived from depth.
- [Order books](index.md#order-books) explains order book state.
- [Python API reference](/docs/python-api-latest/model/data.html) lists Python members.Shown in full with attribution under the source's licence. Licence: LGPL-3.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.