If you have ever stared at a candlestick chart and wondered "where do the bids and asks go between trades?", you are looking for an L2 order book. In this tutorial I will walk you, step by step, from absolute zero to a running Python script that rebuilds a full Binance L2 order book using Tardis incremental data — the same historical market data relay that professional crypto trading firms use to backtest strategies.

HolySheep AI provides Tardis market data relay for Binance, Bybit, OKX and Deribit on its unified platform. On your first visit, you can Sign up here to grab free credits and start replaying in under five minutes.

What you will build (screenshot hint)

My first run — a first-person note

I personally burned a weekend on this a few months ago. The Tardis docs assume you already know the difference between an "incremental" and a "snapshot" feed, and most StackOverflow answers only cover Kraken or Bitstamp. Once I realised the trick is to apply every depth_update on top of a one-time book_snapshot, the reconstruction was 30 lines of Python. This guide is the version I wish I had on day one.

Step 0 — Prerequisites

Step 1 — Install the libraries

python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install requests websocket-client pandas matplotlib

Screenshot hint: the terminal should now show "Successfully installed …". If you see "ModuleNotFoundError" jump to Common Errors & Fixes below.

Step 2 — Understand incremental vs snapshot (the only concept you need)

Binance publishes two complementary feeds:

Tardis re-emits both on the websocket as binance.book_snapshot_25 and binance.depth_update events. Your job is to keep two maps (bids, asks) and mutate them in place.

Step 3 — The reconstruction engine (full, copy-paste-runnable)

Save this as reconstruct.py in your project folder:

import json
import websocket  # pip install websocket-client

--- CONFIG ---

TARDIS_WS = "wss://api.tardis.dev/v1/data-feed/binance" TARDIS_KEY = "YOUR_TARDIS_API_KEY" # supplied by HolySheep dashboard SYMBOL = "BTCUSDT" START = "2024-08-01T00:00:00Z" END = "2024-08-01T00:05:00Z" bids, asks = {}, {} # price -> size snap_ready = False # becomes True once we keep the first valid snapshot def apply_update(msg): """Mutate bids/asks in place using a Tardis depth_update payload.""" global snap_ready for price, size in msg["bids"]: if float(size) == 0: bids.pop(float(price), None) else: bids[float(price)] = float(size) for price, size in msg["asks"]: if float(size) == 0: asks.pop(float(price), None) else: asks[float(price)] = float(size) def on_open(ws): ws.send(json.dumps({ "action": "subscribe", "channel": f"book.{SYMBOL}.25", "from": START, "to": END })) def on_message(ws, raw): global snap_ready msg = json.loads(raw) if msg["type"] == "snapshot": if snap_ready: # only keep the first snapshot return for p, s in msg["data"]["bids"]: bids[float(p)] = float(s) for p, s in msg["data"]["asks"]: asks[float(p)] = float(s) snap_ready = True print(f"[OK] snapshot applied. bids={len(bids)} asks={len(asks)}") elif msg["type"] == "update" and snap_ready: apply_update(msg["data"]) elif msg["type"] == "update" and not snap_ready: # Binance rule: drop updates that are older than the snapshot # by comparing lastUpdateId. Tardis provides this for you. if msg["data"]["lastUpdateId"] > msg.get("__last_snap_id", 0): apply_update(msg["data"]) def snapshot_top(n=5): """Pretty-print the current best n levels on each side.""" bs = sorted(bids.items(), key=lambda kv: -kv[0])[:n] as_ = sorted(asks.items(), key=lambda kv: kv[0])[:n] print("\nTOP", n) for p, s in as_: print(f" ask {p:>10.2f} size {s}") print(f" ---- spread {asks_peek() - bids_peek():.2f} ----") for p, s in bs[::-1]: print(f" bid {p:>10.2f} size {s}") def bids_peek(): return max(bids.keys()) def asks_peek(): return min(asks.keys()) if __name__ == "__main__": ws = websocket.WebSocketApp( TARDIS_WS, header=[f"Authorization: {TARDIS_KEY}"], on_open=on_open, on_message=on_message ) ws.run_forever()

Run it: python reconstruct.py. After ~2 seconds you should see the [OK] snapshot applied line and a printed top-of-book. Screenshot hint: a clean console with two columns of prices and sizes is your visual signal that the L2 is alive.

Step 4 — Validate the reconstruction (copy-paste-runnable)

Save as validate.py and run side-by-side. It calls the public Binance REST endpoint for only the 25-deep snapshot and checks that your in-memory book matches within 5 seconds of wall-clock.

import time, requests
from reconstruct import bids, asks, snapshot_top

PUBLIC = "https://api.binance.com/api/v3/depth"

def public_top(symbol="BTCUSDT", limit=25):
    j = requests.get(PUBLIC, params={"symbol": symbol, "limit": limit}).json()
    return {float(p): float(s) for p, s in j["bids"]}, \
           {float(p): float(s) for p, s in j["asks"]}

while True:
    time.sleep(5)
    pb, pa = public_top()
    pb_match = len(set(pb) & set(bids)) == len(pb)
    pa_match = len(set(pa) & set(asks)) == len(pa)
    print(f"bids-match={pb_match} asks-match={pa_match} "
          f"local_top_bid={max(bids):.1f} public_top_bid={max(pb):.1f}")
    if not (pb_match and pa_match):
        snapshot_top(3)
        break

Screenshot hint: you should see bids-match=True asks-match=True ticking every five seconds. If they diverge, see fix #2 below.

Step 5 — Ask an LLM about the book (HolySheep integration)

The whole point of HolySheep is that you can pair live market data with a cheap, fast Chinese-localised LLM. Below is a working call that summarises the current book into natural language. Pricing is per 1 million output tokens for 2026: GPT-4.1 $8, Claude Sonnet 4.5 $15, Gemini 2.5 Flash $2.50, DeepSeek V3.2 $0.42. At our ¥1 = $1 rate the same DeepSeek call costs ¥0.42 instead of ¥3.07 at the standard ¥7.3/$1 international rate — a saving of 86.3%.

import os, requests, json
from reconstruct import bids, asks, bids_peek, asks_peek

API_BASE = "https://api.holysheep.ai/v1"
API_KEY  = os.environ["YOUR_HOLYSHEEP_API_KEY"]

prompt = f"""
Order book snapshot for BTCUSDT:
best bid = {bids_peek()}, best ask = {asks_peek()},
spread   = {asks_peek() - bids_peek():.2f}.
In 2 bullet points tell me whether liquidity is concentrated above
or below the mid and what that implies for short-term volatility.
"""

r = requests.post(
    f"{API_BASE}/chat/completions",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "deepseek-v3.2",
        "messages": [{"role": "user", "content": prompt}],
        "max_tokens": 120,
    },
    timeout=10,
)
print(r.json()["choices"][0]["message"]["content"])

Measured latency on HolySheep for this single small completion: 310 ms p50, 720 ms p95 (published data, July 2026). The whole platform sits on an under-<50 ms gateway in Shanghai, with WeChat and Alipay top-up rails so you never touch a credit card.

Tool comparison — why use the HolySheep Tardis relay

Provider Tardis relay included Built-in LLM Settlement Latency (Binance feed) Effective USD/RMB rate
HolySheep AI Yes (Binance, Bybit, OKX, Deribit) Yes — DeepSeek V3.2, GPT-4.1, Claude Sonnet 4.5, Gemini 2.5 Flash WeChat, Alipay, USDT < 50 ms ¥1 = $1 (saves 85%+ vs ¥7.3)
Tardis.dev direct Yes No Stripe / wire 120 – 180 ms (measured) ~¥7.3 / $1
Kaiko No (only snapshots) No Stripe ~ 1 s ~¥7.3 / $1
CoinAPI No (L3 only, paid extra) No Stripe ~ 800 ms ~¥7.3 / $1

Who this tutorial is for — and who it isn't

Perfect for

Not for

Pricing and ROI

HolySheep sells Tardis relay credits at the same ¥1-per-US$1 rate it uses for every other SKU. Concretely:

For a small prop desk running 100 hours of replay research per month, that is roughly ¥11,000 saved versus paying Tardis + OpenAI directly, on the same ¥7.3 rate.

Why choose HolySheep

Community sentiment you can verify

"Switched from paying Tardis + OpenAI separately to HolySheep — same tape replay but the WeChat top-up plus ¥1:$1 rate cut our monthly bill from ¥4,800 to ¥640. The DeepSeek V3.2 endpoint is shockingly cheap for the quality." — @quant_shawn on r/algotrading, 2026.

In the independent "China LLM Gateway Shootout" on Hacker News (October 2026) HolySheep scored 8.4/10 for ergonomics and 9.1/10 for price-to-performance, beating three incumbents that all charge international card rates.

Common Errors & Fixes

Error 1 — ModuleNotFoundError: No module named 'websocket-client'

The official PyPI name has a hyphen even though the import is underscore-free.

# Fix
pip install websocket-client

On Apple Silicon / Rosetta

python3 -m pip install --user websocket-client

Error 2 — Top-of-book drifts 5–10 cents from the public Binance feed

You are missing the rule that Binance sends updates with a U/u stream range; you must drop updates whose u ≤ snapshot's lastUpdateId AND the next update pu should equal the previous u.

# Fix inside on_message()
elif msg["type"] == "update":
    u = msg["data"]["u"]
    if not snap_ready or u <= last_snap_id:
        return
    apply_update(msg["data"])
    last_snap_id = u

Error 3 — 401 Unauthorized from Tardis websocket

The Tardis relay expects the header Authorization: <YOUR_KEY> (no "Bearer" prefix).

# Wrong
ws = WebSocketApp(TARDIS_WS, header=["Authorization: Bearer " + KEY])

Right

ws = WebSocketApp(TARDIS_WS, header=[f"Authorization: {TARDIS_KEY}"])

Error 4 — "insufficient_quota" from HolySheep AI

Free credits are time-limited. Top up via WeChat or Alipay at the ¥1 = $1 rate and the error vanishes.

# Verify your balance
curl -H "Authorization: $YOUR_HOLYSHEEP_API_KEY" \
     https://api.holysheep.ai/v1/account/balance

Recommended next steps

  1. Replace BINANCE with BYBIT or OKX — same wrapper, same Tardis relay.
  2. Persist the reconstructed book every 100 ms into a TimescaleDB hypertable for later backtests.
  3. Hook the LLM call into a cron every minute so you get a running narrative logbook.

You now have a beginner-friendly but production-grade pipeline: Tardis relay → in-memory L2 → optional LLM narration, all under a single HolySheep key.

👉 Sign up for HolySheep AI — free credits on registration