Record an order book snapshot (and the changes after it)

Matchstick guide Last updated: October 17, 2026
#guide#import#order-book-snapshot#record-it-yourself#bring-your-own-data

What an order book snapshot is, why one snapshot is not enough to replay, and how to record a snapshot plus every change after it from Kraken's public feed, with no account or subscription.

What you get: a real, current order book that you recorded yourself, replayed step by step in the Matchstick Replay app. Recording needs no exchange account, no API key and no subscription. The file stays on your machine; Matchstick’s servers never see it.

Access: The Replay app is invite-only. Request access at app.matchstick.trading; the public demo at replay.matchstick.trading needs no account.

The rule: record it yourself, for yourself, and don’t share the file. That goes for screenshots and videos of a replay of it too. If you want something to show other people, use the sample sessions in the app, which are synthetic and labelled.

Check the exchange’s own terms before you record its feed; this guide is for your own use on your own machine.

What an order book snapshot is

An order book snapshot is the book at one moment: the total size waiting at each buy price and each sell price. It is a single picture.

A single picture cannot be replayed. Replay moves through a book event by event, so it needs the snapshot and every change after it. If a file holds a snapshot and nothing after it, the import fails with LEGACY_IMPORT_FAILED and the message “contains a snapshot but no updates after it; there is nothing to replay” (the import guide lists this error).

What the script records

The script below does both parts. When it connects to Kraken’s public BTC/USD feed, Kraken first sends a snapshot of the book (100 price levels per side). The script writes that snapshot as the first rows of the file, marked is_snapshot=true, then writes each change that arrives afterwards. The result is a snapshot plus the changes that followed it, which the app can step through one event at a time.

It records the order book only, not trades.

1. Record

You need Node.js 22 or newer (the script was run on Node 24). Nothing to install: the script below uses only what Node ships with. It connects to Kraken’s public WebSocket book feed, which needs no account, and writes each book message as a row in the same CSV layout Replay already imports for Tardis.dev files. Save it as record-kraken-book.mjs:

// Record Kraken's public BTC/USD order book to a Tardis-shaped incremental_book_L2 CSV.
// Usage: node record-kraken-book.mjs [seconds] [out.csv]   (Node 22+, no packages, no account)
import { createWriteStream } from "node:fs";

const seconds = Number(process.argv[2] ?? 300);
const out = process.argv[3] ?? "kraken_BTC-USD_book.csv";
const SYMBOL = "BTC/USD";

const file = createWriteStream(out);
file.write("exchange,symbol,timestamp,local_timestamp,is_snapshot,side,price,amount\n");

// Never print exponent notation: Replay rejects it.
const dec = (n) => (String(n).includes("e") ? n.toFixed(12).replace(/0+$/, "").replace(/\.$/, "") : String(n));
// Local receive time in microseconds, forced to never go backwards.
const t0 = Date.now() * 1000, h0 = process.hrtime.bigint();
let last = 0;
const nowUs = () => {
  const us = t0 + Number((process.hrtime.bigint() - h0) / 1000n);
  last = Math.max(last + 1, us);
  return last;
};
// Exchange time "2026-10-09T04:19:57.174206Z" -> microseconds since the epoch.
const exchUs = (iso) => {
  const [, whole, frac = ""] = iso.match(/^(.*?)(?:\.(\d+))?Z$/);
  return Date.parse(`${whole}Z`) * 1000 + Number((frac + "000000").slice(0, 6));
};

let rows = 0, snapshots = 0;
const ws = new WebSocket("wss://ws.kraken.com/v2");
ws.onopen = () => ws.send(JSON.stringify({ method: "subscribe", params: { channel: "book", symbol: [SYMBOL], depth: 100 } }));
ws.onmessage = (e) => {
  const m = JSON.parse(String(e.data));
  if (m.channel !== "book") return;
  const local = nowUs();
  for (const d of m.data) {
    const snap = m.type === "snapshot";
    if (snap) snapshots++;
    const ts = d.timestamp ? exchUs(d.timestamp) : local;
    for (const [side, levels] of [["bid", d.bids], ["ask", d.asks]])
      for (const l of levels) {
        file.write(`kraken,${SYMBOL.replace("/", "-")},${ts},${local},${snap},${side},${dec(l.price)},${dec(l.qty)}\n`);
        rows++;
      }
  }
};
ws.onerror = (e) => { console.error("feed error", e.message); process.exit(1); };
setTimeout(() => { ws.close(); file.end(() => console.log(`wrote ${rows} rows, ${snapshots} snapshot(s) -> ${out}`)); }, seconds * 1000);

Run it for as long as you like, within the import limit (512 MiB per file, see the Tardis guide); this records five minutes:

node record-kraken-book.mjs 300 kraken_BTC-USD_book.csv

It prints the row count when it finishes. A first run of this script on 2026-10-08 recorded four minutes of BTC/USD and produced 18,186 rows (1.3 MB), which Replay imported as 17,986 events. That is roughly 5 to 6 MB an hour at that pace; a busier market writes more, so check the file size, and stop well short of the limit. Only that four-minute file was tested.

2. What the script writes

The columns are exchange,symbol,timestamp,local_timestamp,is_snapshot,side,price,amount, the layout in Import a Tardis.dev order book, so the same import and the same rules apply:

  • The first rows are Kraken’s snapshot of the book (100 price levels per side), marked is_snapshot=true. Every row after that is one price level’s new size; 0 removes the level.
  • local_timestamp is your computer’s clock at the moment each message arrived, in microseconds, and never goes backwards. timestamp is Kraken’s own time, kept as extra evidence.
  • It records the order book only, not trades.
  • Keep the computer awake while it runs. If the connection drops, no more rows arrive; stop it and run it again for a new file. One file is one continuous recording.

3. Import it

  1. Open the Matchstick Replay app. Request access if you do not have an invite yet.
  2. Open the session menu at the top of the window.
  3. Choose Import file… and pick your .csv.

Then step forward and back one event at a time. Errors you might hit are listed in the Tardis guide.

What this isn’t

  • It isn’t a recorder that Matchstick hosts or runs for you. The script runs on your machine and talks to Kraken directly.
  • It isn’t a Matchstick data product. Matchstick provides no data and makes no claim about the data, its accuracy, or what you may do with it.
  • The script is an example, run and checked on 2026-10-08. Kraken can change its feed at any time; if the script stops working, the CSV layout above is what matters.