Local Order Book Maintenance
Maintain a local order book through WebSocket incremental updates for low-latency depth data access.
Core Concepts
| Field | Description |
|---|---|
U | First update ID - first update in this push |
u | Last update ID - last update in this push |
id | Sequence number from REST API snapshot (requires with_id=true) |
Synchronization Process
- Subscribe to incremental updates: Subscribe to
{symbol}@order_book_update - Cache messages: Cache all incremental messages before fetching snapshot
- 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
- Process cache:
- Discard messages where
u < id + 1(expired) - Find message where
U <= id + 1 && u >= id + 1to start sync - If
U > id + 1snapshot is outdated, re-fetch
- Discard messages where
- 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 Scenario | Recovery |
|---|---|
| WebSocket disconnected | Auto-reconnect, re-subscribe, rebuild |
Discontinuous sequence (U > lastId + 1) | Re-fetch snapshot, rebuild |
| Snapshot outdated | Re-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