Skip to main content
Version: Next

Local Order Book Maintenance

Maintain a local order book through WebSocket incremental updates for low-latency depth data access.

Core Concepts

FieldDescription
UFirst update ID - first update in this push
uLast update ID - last update in this push
idSequence number from REST API snapshot (requires with_id=true)

Synchronization Process

  1. Subscribe to incremental updates: Subscribe to {symbol}@order_book_update
  2. Cache messages: Cache all incremental messages before fetching snapshot
  3. Get snapshot: Call REST API to get order book snapshot with sequence number
GET /api/v1/futures/open-api/orderbook/BTCUSDT?depth=100&with_id=true
  1. Process cache:
    • Discard messages where u < id + 1 (expired)
    • Find message where U <= id + 1 && u >= id + 1 to start sync
    • If U > id + 1 snapshot is outdated, re-fetch
  2. Continue updating: Verify each message U <= lastProcessedId + 1, otherwise rebuild

Update Rules

  • Quantity "0" means delete that price level
  • Non-zero quantity means update or add price level
  • Bids (b) sorted high to low
  • Asks (a) sorted low to high

Pseudo-code Example

// 1. Connect and subscribe
ws.send(JSON.stringify({
action: 'subscribe',
streams: ['BTCUSDT@order_book_update']
}));

// 2. Cache incremental messages
const buffer = [];
ws.onmessage = (msg) => {
const data = JSON.parse(msg.data);
if (data.action === 'order_book_update') {
buffer.push(data.result);
}
};

// 3. Get REST API snapshot with sequence number
const snapshot = await fetch('/api/v1/futures/open-api/orderbook/BTCUSDT?depth=100&with_id=true');
const { bids, asks, id: snapshotId } = snapshot.data;

// 4. Initialize local order book
const orderbook = {
bids: new Map(bids.map(([p, q]) => [p, q])),
asks: new Map(asks.map(([p, q]) => [p, q])),
lastUpdateId: snapshotId
};

// 5. Process cached messages
for (const update of buffer) {
if (update.u < snapshotId + 1) continue;
if (update.U > snapshotId + 1) {
rebuildOrderbook();
break;
}
applyUpdate(update);
}

// 6. Apply incremental updates
function applyUpdate(update) {
for (const [price, qty] of update.b) {
if (qty === '0') orderbook.bids.delete(price);
else orderbook.bids.set(price, qty);
}
for (const [price, qty] of update.a) {
if (qty === '0') orderbook.asks.delete(price);
else orderbook.asks.set(price, qty);
}
orderbook.lastUpdateId = update.u;
}

Error Handling

Error ScenarioRecovery
WebSocket disconnectedAuto-reconnect, re-subscribe, rebuild
Discontinuous sequence (U > lastId + 1)Re-fetch snapshot, rebuild
Snapshot outdatedRe-fetch snapshot

Notes

  • Incremental push frequency: aggregated every 100ms
  • Price and quantity are strings to avoid floating-point precision issues
  • Periodically validate local order book against REST API snapshot