Skip to main content

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

  1. Complete the BSL Direct TCP v2 handshake.
  2. Send a MarketDataRequest (message kind 20):
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
  1. The gateway replies, all wrapped in the session's SequencedData envelope:
    • MarketDataResponse: accepted, latest_seq, snapshot_seq, granted heartbeat_ms.
    • MarketBookSnapshot (kind 22): the full book at snapshot_seq.
    • then live MarketBookDelta (kind 23), MarketTrade (kind 24), and MarketStatus (kind 25) 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.

FrameKindBody
MarketDataResponse21accepted, latest_seq, snapshot_seq, heartbeat_ms
MarketBookSnapshot22market_id, channel, snapshot_seq, state_version, count, level*
MarketBookDelta23market_id, seq, prev_seq, full_replace, count, level*
MarketTrade24market_id, seq, count, [book, price, qty, aggressor, ts_ms]*
MarketStatus25market_id, status, ts_ms

Recovery

  • In-session gap (you see a sequence skip): send ResendRequest from the expected sequence; the gateway replays the retained tail.
  • Source gap (the feed bus lagged): the gateway emits a fresh MarketBookSnapshot automatically — re-apply it as the new book.
  • Reconnect: re-send MarketDataRequest with resume_from_seq set 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.