DEV Community

Emily
Emily

Posted on

How to Reconstruct a Crypto Order Book in Python Using WebSockets and SortedDict

Hey devs! 👋 We want to share a practical recipe that has become a staple in our quantitative data pipeline: streaming a cryptocurrency order book in real time and maintaining an exact local copy using Python. If you’ve ever needed reliable market depth for your app, bot, or analysis notebook, this setup will give you full ownership of the data.

The Problem with Polling

REST endpoints give you a static snapshot of the order book. That’s okay for low-frequency dashboards, but if you need up-to-the-millisecond accuracy—for example, when computing slippage or order flow signals—polling introduces gaps that ruin the picture. You need a persistent WebSocket stream that pushes every change as it happens.

Ingredients

  • WebSocket client to receive live data.
  • Snapshot for initializing the book.
  • Diffs for keeping it current.
  • SortedDict to store bids and asks efficiently.

We used sortedcontainers because it keeps items in order and supports fast insertions/deletions. Bids are sorted descending, asks ascending.

from sortedcontainers import SortedDict

# Bids: highest price first
bids = SortedDict(lambda x: -x)
# Asks: lowest price first
asks = SortedDict()
Enter fullscreen mode Exit fullscreen mode

Step-by-Step Code

Connect to a WebSocket endpoint that provides snapshot and diff messages. We’ve had good experiences with AllTick’s feed, as the data format is clean and well-documented. Here’s the full minimal example:

import websocket
import json
from sortedcontainers import SortedDict

bids = SortedDict(lambda x: -x)
asks = SortedDict()

def on_message(ws, message):
    data = json.loads(message)
    # Update both sides of the book
    process_orderbook(data)

def process_orderbook(data):
    global bids, asks
    for update in data.get("bids", []):
        price, size = update
        if size == 0:
            bids.pop(price, None)
        else:
            bids[price] = size
    for update in data.get("asks", []):
        price, size = update
        if size == 0:
            asks.pop(price, None)
        else:
            asks[price] = size

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

Making It Production-Ready

The snippet above works for experimentation, but for anything serious you’ll want:

  • Sequence verification on diffs to detect gaps.
  • Automatic snapshot reload if a gap is found.
  • Heartbeat and auto-reconnect for the WebSocket connection.

Implementing these guards turns a fragile script into a self-healing service.

Visual Feedback

During development, we often plot the order book using matplotlib to sanity-check the data:

import matplotlib.pyplot as plt

def plot_orderbook():
    plt.plot(list(bids.keys()), list(bids.values()), color='green', label='Bids')
    plt.plot(list(asks.keys()), list(asks.values()), color='red', label='Asks')
    plt.legend()
    plt.show()
Enter fullscreen mode Exit fullscreen mode

Green shows the bid side, red the ask side. Any sudden gap or spike immediately reveals a synchronization issue.

Wrapping Up

With a few dozen lines of Python, you can maintain a real-time, exchange-accurate order book locally. This opens the door to custom indicators, low-latency alerts, and strategy backtesting on consistent data. Give it a try—it’s one of those building blocks that pays dividends across many projects.

Top comments (0)