DEV Community

EmilyL
EmilyL

Posted on

Reconstructing a Cryptocurrency Order Book from Real-Time API Incremental Updates — A Practical Guide

When we started building out our crypto trading infrastructure, we quickly ran into a challenge that sounds simple but is actually a deep engineering problem: turning a firehose of incremental order book updates from a cryptocurrency API into a continuously accurate local representation of the market. This post is the guide we wish we’d had back then, written from the perspective of a team of independent high-frequency traders. We’ll cover the requirements, the data pain points, the specific product-level solutions we built, and how it all fits into real industry applications.

What Problem Are We Solving?

We need a local order book that accurately reflects the exchange’s live state. Every strategy — from quoting to statistical arbitrage to liquidity analysis — depends on this ground truth. But the API doesn’t send us a full picture; it sends small incremental patches.

Data Pain Points: Understanding What You’re Actually Receiving

Incremental Updates Are Instructions, Not States

A full order book contains every active bid and ask level with their respective quantities. However, pushing the entire book on each change would be prohibitively bandwidth-heavy. Instead, cryptocurrency APIs use incremental feeds that deliver only the modified levels. You’ll see something like:

Direction Price Quantity Change
Buy 65000 +0.5
Sell 65010 -1

Think of this as a log entry: “Apply this delta.” You cannot interpret it in isolation; you must maintain your own state and apply each delta in sequence. If you treat each delta as an independent event, the order of application can get scrambled, and your local book will drift from reality.

Sequence Numbers Are Your Only Safeguard

Network transport means messages can arrive out of order. A later message might reach your server before an earlier one. If you apply them by arrival time, the state becomes logically corrupted. Our solution is strict sequence-number discipline. The API provides a sequence or updateId with every message. Our rule:

  1. Get a full snapshot and record its sequence number.
  2. Buffer all subsequent deltas.
  3. Only apply deltas whose sequence number is exactly one greater than our current state.
  4. If a sequence gap appears, discard the local state and re-fetch a fresh snapshot.

This ensures we never build on a broken foundation.

Product Functionality: Designing the Local Book and Connection

Use a Dictionary, Not a List

Early on, we used arrays for price levels. As the number of levels grew, update performance tanked. Now we use dictionaries (maps) keyed by price:

order_book = {
    "bids": {
        65000: 1.5,
        64999: 2.0
    },
    "asks": {
        65001: 1.8,
        65002: 3.1
    }
}
Enter fullscreen mode Exit fullscreen mode

On each delta: if new quantity > 0, set the price key; if quantity == 0, delete the key. This structure makes getting best bid/ask and calculating depth extremely fast.

WebSocket for Low-Latency Feeds

HTTP polling introduces unacceptable latency for order book updates. We always use WebSocket connections. While integrating one feed, we based our initial handler on the AllTick API WebSocket market data pattern. The core processing loop is:

import websocket
import json

order_book = {
    "bids": {},
    "asks": {}
}

def update_order_book(data):
    for item in data.get("bids", []):
        price = float(item["price"])
        volume = float(item["volume"])
        if volume == 0:
            order_book["bids"].pop(price, None)
        else:
            order_book["bids"][price] = volume
    for item in data.get("asks", []):
        price = float(item["price"])
        volume = float(item["volume"])
        if volume == 0:
            order_book["asks"].pop(price, None)
        else:
            order_book["asks"][price] = volume

def on_message(ws, message):
    data = json.loads(message)
    if data.get("symbol") == "BTCUSDT":
        update_order_book(data)
        print(order_book)

ws = websocket.WebSocketApp(
    "wss://apis.alltick.co/websocket-api",
    on_message=on_message
)
ws.run_forever()
Enter fullscreen mode Exit fullscreen mode

This is the foundation. Wrap it with sequence validation, heartbeat checks, and automatic snapshot recovery on disconnect for a production-grade system.

Industry Applications: Where Accurate Depth Matters

We use this book for market making, arbitrage signals, and real-time liquidity monitoring. A small consistent error in depth data can gradually erode profitability. Two additional notes from our production experience:

  • After a WebSocket disconnect, the local book is outdated. Reconnect logic must fetch a fresh snapshot first, then resume deltas.
  • Price precision: avoid floating-point keys. Convert all prices to integers based on the tick size to prevent matching errors.

Accurate order book reconstruction is not just about receiving data; it’s about synchronizing a distributed state. Get this right, and your trading strategies have a solid foundation.

Top comments (0)