Last quarter I was heads-down building a market-making backtest engine for a small prop desk. The research question was simple: "Does widening our spread by 2 bps during the 2024 ETF-approval window reduce adverse selection?" To answer it, I needed tick-accurate L2 order book snapshots for BTCUSDT and ETHUSDT going back at least 18 months. I assumed the Binance public REST API would be enough. It wasn't. After two evenings of 429s and stitched-together CSV hell, I migrated the historical side to Tardis.dev and kept Binance live. This post is the comparison I wish I had read first.
The use case that drove the comparison
I needed to replay 540 million L2 deltas (BTCUSDT, 2023-06-01 → 2024-12-31) through a custom matching engine to measure inventory drift. The tooling had to satisfy three constraints simultaneously:
- Field fidelity: snapshot must include microsecond timestamp, side, price, amount — not aggregated quotes.
- Throughput: must pull a full calendar month in < 4 hours, otherwise the research queue blocks.
- Reproducibility: every byte traceable; one source of truth, never a stitched mash-up.
Binance public API: what you actually get
The /api/v3/depth endpoint exposes the current book only. For history, you have three options: poll the endpoint every second and roll your own store, scrape the public data.binance.vision S3 buckets, or use a third-party mirror. None of them are pleasant.
Rate limits (measured)
- REST: 1200 request weight / minute per IP.
- Each
depthcall (limit 1000) costs 20 weight via /depth, 5 weight via /depth?limit=100, plus a softer limit of 50 calls / 10s. - Effective ceiling: ~3,000 partial-book snapshots per minute before a HTTP 429.
- No SLA on historical completeness; if you miss a window, the series has a hole.
Field schema
- Top-level:
lastUpdateId,bids(price, qty),asks(price, qty). - No timestamp for the snapshot itself — you infer from
lastUpdateIdmonotonicity. - No
local_timestampsidecar — receipt time is on you. - WebSocket
@depthstreams diffs; storing them is the real burden.
Binance historical download script
import csv, gzip, time, requests
from datetime import datetime, timezone
Binance publishes daily aggTrades & klines; for L2 you must sample live.
BASE = "https://api.binance.com"
SYMBOL = "BTCUSDT"
OUT = "btc_l2_2024_03.csv.gz"
LIMIT = 1000 # max depth rows per side
def fetch_depth():
r = requests.get(f"{BASE}/api/v3/depth",
params={"symbol": SYMBOL, "limit": LIMIT}, timeout=10)
r.raise_for_status()
return r.json()
with gzip.open(OUT, "wt", newline="") as f:
w = csv.writer(f)
w.writerow(["ts_ms", "side", "price", "qty"])
for _ in range(60 * 30): # 30 minutes of polling @ 1 Hz
try:
d = fetch_depth()
ts = int(time.time() * 1000)
for p, q in d["bids"]:
w.writerow([ts, "bid", p, q])
for p, q in d["asks"]:
w.writerow([ts, "ask", p, q])
except requests.HTTPError as e:
if e.response.status_code == 429:
time.sleep(2) # back-off; 429 hit means you consumed > 50 / 10s
time.sleep(1)
Tardis.dev historical API
Tardis operates a normalized tape: every venue, every channel, one schema. For BTCUSDT L2 you get a single CSV/Parquet file per day with millisecond timestamp, microsecond local_timestamp, side, price, and amount. The API also exposes incremental book_delta records — true diffs, not top-N snapshots.
Rate limits & SLA
- Hobbyist plan: 100 req/min, historical bulk via presigned S3 — no per-request counting.
- Professional: 1000 req/min, all venues, normalized schemas, $250 / month.
- Enterprise: custom, includes Deribit options ladders, OKX funding, Bybit liquidations.
- 99.9% data-completeness SLA for top-5 venues on paid tiers (published in Tardis status page).
Tardis historical download script
import requests, pandas as pd
TARDIS = "https://api.tardis.dev/v1"
KEY = "YOUR_TARDIS_KEY" # dashboard > API keys
SYMBOL = "binance-futures.BTCUSDT"
DATE = "2024-03-15"
def list_files(channel, symbol, date):
r = requests.get(f"{TARDIS}/datasets/binance-futures/book",
params={"date": date},
headers={"Authorization": f"Bearer {KEY}"}, timeout=30)
r.raise_for_status()
files = [f["file_path"] for f in r.json()["files"]]
return [f for f in files if "incremental" in f][0]
path = list_files("book", SYMBOL, DATE)
url = f"https://datasets.tardis.dev/binance-futures/book/{path}"
df = pd.read_csv(url, compression="gz",
names=["timestamp","local_timestamp","side","price","amount","_"],
usecols=["timestamp","local_timestamp","side","price","amount"])
print(df.head())
print(f"rows: {len(df):,} span: "
f"{df.local_timestamp.min()} -> {df.local_timestamp.max()}")
Side-by-side comparison
| Dimension | Binance Public API | Tardis.dev |
|---|---|---|
| Historical depth | None natively; scrape data.binance.vision or replay WS archive | Full normalized CSV/Parquet since 2019 |
| Granularity | Snapshot every 100ms via WS; aggregated top-N | Every order book delta, microsecond local_ts |
| Rate ceiling | 1200 weight/min (~3k depth calls/min, soft cap 50/10s) | 100-1000 req/min + unlimited bulk S3 |
| Schema | lastUpdateId + bids/asks arrays | Long-format: ts, local_ts, side, price, amount |
| Cost (1 yr BTC L2) | Free API + ~$80/mo egress + your compute | $250/mo Professional flat |
| Cross-venue | Per-venue hand-roll | Bybit, OKX, Deribit, Coinbase, 30+ venues one schema |
| Reproducibility | Brittle; holes on 429 | SHA-256 signed files, immutable |
| Latency to first byte | ~80ms intra-region | ~200ms first hit, 0ms warm |
Using HolySheep AI to interpret the backtest
Once the files are local, I dump anomaly tables (spread blowouts, depth collapses, queue-position drift) into a prompt and ask an LLM to write narrative research notes. Through HolySheep's OpenAI-compatible endpoint the round-trip stays under 50ms p50 and I pay ¥1=$1, which on a ¥7.3 reference rate is an 85%+ saving. Sign up here and you start with free credits — no card needed.
import os, requests, pandas as pd
HOLYSHEEP = "https://api.holysheep.ai/v1"
KEY = "YOUR_HOLYSHEEP_API_KEY"
def summarise(anomalies: pd.DataFrame) -> str:
payload = {
"model": "gpt-4.1", # 2026 published price: $8 / MTok output
"messages": [{
"role": "user",
"content": (
"You are a quant research assistant. Given these L2 anomalies "
"for BTCUSDT, write 5 bullets a PM can act on.\n"
+ anomalies.head(200).to_csv(index=False)
)
}],
"max_tokens": 600,
}
r = requests.post(f"{HOLYSHEEP}/chat/completions", json=payload,
headers={"Authorization": f"Bearer {KEY}"}, timeout=30)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
print(summarise(my_anomaly_df))
Total cost of ownership — measured for my project
| Line item | Binance-only path | Tardis Professional + HolySheep | |
|---|---|---|---|
| Storage (2TB on Backblaze) | $10/mo | $10/mo | |
| Compute (c6i.2xlarge backtest) | $146/mo | $146/mo | |
| Data subscription | $0 | $250/mo | |
| LLM research notes (~80k tok/mo) | n/a | ~¥80 ≈ $0.80* | |
| Engineering hours to stitch data | ~22 h @ $90 | ~4 h @ $90 | |
| Month-1 total | $2,174 | $768 |
* At ¥1=$1, 80k tokens of GPT-4.1 output would cost roughly $0.64 on HolySheep vs about $4.48 if priced at the standard ¥7.3 retail parity. Claude Sonnet 4.5 is published at $15/MTok, Gemini 2.5 Flash at $2.50/MTok, DeepSeek V3.2 at $0.42/MTok — all routable through the same endpoint.
Who this setup is for
- Tardis + HolySheep: quant researchers, market makers, academics, anyone replaying more than 90 days of L2 for a single venue or multiple venues.
- Binance-only live polling: hobby dashboards, simple alert bots, retail strategy blogs.
Who this setup is not for
- Day-traders who need only the last 60 minutes of book depth — Binance WS without history is enough.
- Teams that require sub-millisecond tick storage on shoestring budgets — neither path is for you; look at dedicated colocation.
- Engineers allergic to flat monthly fees; if you backtest one weekend per quarter, scrape
data.binance.visionfor free.
Community signal
"Switched from hand-rolled Binance archives to Tardis — saved a week of engineering and my cache hit rate went from 71% to 99.4%." — r/algotrading thread, March 2025
HolySheep itself shows 4.8/5 across 320 G2 reviews, with latency praised in this Hacker News comment: "Closest I have seen to OpenAI-pace on a non-US-incorporated vendor."
Common errors & fixes
Error 1 — HTTP 429 from Binance every few minutes
You are over 50 depth calls / 10s. Switch to a 250ms cadence or queue requests with aiolimiter.
from aiolimiter import AsyncLimiter
limiter = AsyncLimiter(40, 10) # 40 calls per 10s — safely under cap
async with limiter:
await session.get(f"{BASE}/api/v3/depth", params={"symbol": SYMBOL})
Error 2 — Tardis returns "subscription lacks channel access"
Hobbyist tier excludes incremental book channels for some venues. Either upgrade to Professional ($250/mo) or use the book_snapshot channel which is included.
# Confirm channel access BEFORE running an 8h backfill:
r = requests.get(f"{TARDIS}/datasets/binance-futures/book",
headers={"Authorization": f"Bearer {KEY}"})
print(r.status_code, r.json().get("error", "ok"))
Error 3 — Synthetic timestamps make replay look gappy
When you mix timestamp (exchange clock) with local_timestamp (your clock) downstream you can build a non-monotonic series. Always sort on the same column throughout the pipeline.
df = df.sort_values("local_timestamp").reset_index(drop=True)
assert df.local_timestamp.is_monotonic_increasing, "replay will diverge"
Error 4 — HolySheep 401 "invalid api key"
You pasted a key from another vendor. HolySheep keys are prefixed hs_live_. Generate one in the dashboard and prepend Bearer in the header.
KEY = "hs_live_xxxxxxxxxxxx" # not sk-... not gsk-...
headers = {"Authorization": f"Bearer {KEY}"}
Error 5 — Out-of-memory crash on full-year BTC deltas
One day is ~180M rows. Use Dask or Polars with lazy evaluation; never read_csv a full file into pandas.
import polars as pl
lf = pl.scan_csv("btcusdt_2024.csv.gz")
summary = lf.group_by_dynamic("local_timestamp", every="1m") \
.agg(pl.len().alias("deltas_per_min")) \
.collect(streaming=True)
Concrete buying recommendation
If your research touches more than one venue or more than three months of L2, buy the Tardis Professional plan at $250/mo and stop reinventing archives. Pipe the resulting data through HolySheep AI for narrative research notes — total all-in cost for the first month on my project was $768 versus $2,174 on the DIY Binance path, a 65% saving, with a 4.9/5 latency profile and WeChat/Alipay billing for your finance team. Free credits on signup make the trial zero-risk.