BSL Binary Market Data
This page describes the planned binary market-data contract for the BSL Direct TCP session. It is not the current public beta order-entry contract.
The live BSL connectivity bundle currently advertises Direct TCP message kinds
for order entry only: CompactActionFrame, AuthSidecar, and
CompactFrameGroup, with response payloads CoreAck, GatewayReject, and
CoreAckBatch. Use the public WebSocket feed for live market data until the
connectivity bundle advertises the market-data message kinds below.
When enabled, the binary market-data feed will deliver full-depth book snapshots, incremental book deltas, and trade prints over the same v2 recoverable BSL Direct TCP session as order entry. Heartbeats, gap-fill resend, and sequence tracking come from the shared recoverable-session machinery.
The public WebSocket JSON feed remains the current beta market-data path.
Session flow
- Complete the BSL Direct TCP v2 handshake.
- Send a
MarketDataRequest(message kind20):
u64_le market_id
u8 channel # 0 = Book, 1 = Trades, 2 = Bbo
u32_le snapshot_depth
u64_le resume_from_seq # 0 = full snapshot; >0 = reconnect from a feed sequence
- The gateway replies, all wrapped in the session's
SequencedDataenvelope:MarketDataResponse:accepted,latest_seq,snapshot_seq, grantedheartbeat_ms.MarketBookSnapshot(kind22): the full book atsnapshot_seq.- then live
MarketBookDelta(kind23),MarketTrade(kind24), andMarketStatus(kind25) messages.
Every market-data message rides inside SequencedData with a per-session
sequence, so a detected gap is filled with a ResendRequest, and a source-side
gap re-snapshots automatically.
Binary frames
All integers are little-endian. Price is micro-USDC (u64); quantity is atomic
units (u64). A book level is book(u8) side(u8) price_micros(u64) qty(u64)
(book: 0 = YES, 1 = NO, 2 = SPOT; side: 0 = bid, 1 = ask). In a delta a level
with qty == 0 removes that price.
| Frame | Kind | Body |
|---|---|---|
MarketDataResponse | 21 | accepted, latest_seq, snapshot_seq, heartbeat_ms |
MarketBookSnapshot | 22 | market_id, channel, snapshot_seq, state_version, count, level* |
MarketBookDelta | 23 | market_id, seq, prev_seq, full_replace, count, level* |
MarketTrade | 24 | market_id, seq, count, [book, price, qty, aggressor, ts_ms]* |
MarketStatus | 25 | market_id, status, ts_ms |
Recovery
- In-session gap (you see a sequence skip): send
ResendRequestfrom the expected sequence; the gateway replays the retained tail. - Source gap (the feed bus lagged): the gateway emits a fresh
MarketBookSnapshotautomatically — re-apply it as the new book. - Reconnect: re-send
MarketDataRequestwithresume_from_seqset to the highest feed sequence you applied. The gateway replays the missed updates, or re-snapshots if that sequence has aged out of the retention window.
SDK support
The Rust SDK decodes these frames directly (senticore_sdk::market_data):
decode_market_book_snapshot, decode_market_book_delta, decode_market_trade,
decode_market_status, plus encode_market_data_request. A
BslTcpEvent::MarketData { kind, body } from the session carries the raw frame
body to pass into the matching decoder.