tickstreamdocs

DOCS

Historical data archive

Full tick, Level 2 and option-chain history since 2019 over REST — for backtesting and research.

The historical archive serves the complete record — every trade tick, every Level 2 book update, and daily option-chain snapshots (full greeks & open interest) — back to 2019, straight from our Parquet stores as JSON. It's the same data our own research and live-tested algos run on. Base URL: https://api.tick-stream.xyz/v1.

plans

These endpoints require a data-archive package (or All-in-One): /history/ticks and /history/book need the NQ ticks archive, /history/options needs the options archive. Each package comes in two forms — a one-time purchase (the archive up to your purchase date, yours forever; ranges past your snapshot date are clamped and the response carries snapshot_until) or the updates subscription (same price up front, then $10/mo; the archive always reaches live). Cancelling the updates subscription converts it into a snapshot at the end of the last paid month — you keep everything you paid for. Want to evaluate first? A free 2-month NQ tick sample (Feb – Mar 2025, 22.9M trades, plus two full days of Level-2 depth, same schemas) is downloadable without signup. The live snapshot endpoints (/quote, /ticks) are separate and come with any realtime plan.

Common parameters

All three endpoints share the same range and paging contract.

ParamRequiredDescription
start / endnoISO-8601 (2022-06-13 or 2022-06-13T13:30:00Z) or Unix seconds. Defaults to a short window ending now — pass an explicit range for the archive.
limitnoMax rows per call (default 50,000, max 500,000).

Every response carries count and truncated. When truncated is true, fetch the next page by setting start to the last returned ts (rows are time-ordered, oldest first). Timestamps are Unix seconds (UTC).

GET /history/ticks

Full trade-tick archive for a futures symbol. NQ ticks plan.

ParamRequiredDescription
symbolyesFutures root, e.g. NQ, ES.
curl "https://api.tick-stream.xyz/v1/history/ticks?symbol=NQ&start=2022-06-13&end=2022-06-14" \
  -H "Authorization: Bearer sk_live_…"
from tickstream import Client
c = Client("sk_live_…")
rows = c.history_ticks("NQ", start="2022-06-13", end="2022-06-14")
print(len(rows), "ticks")
{
  "symbol": "NQ",
  "start": 1655085600, "end": 1655172000,
  "count": 48213, "truncated": false,
  "ticks": [
    { "ts": 1655127000, "price": 12043.25, "size": 2, "side": "buy" }
  ]
}

Each tick: ts, price, size, and side (the aggressor — "buy" or "sell").

Aggressor provenance. From March 2026 onward, ticks are our own live capture and side is the exchange-reported aggressor. For 2019 – Feb 2026 the archive is built from a historical BBO tape (every trade print plus the prevailing best bid/ask); side is inferred with the standard quote rule — trade at the ask = "buy", at the bid = "sell", tick rule inside the spread (<1% of prints remain "unknown"). Re-encoded 2026-07-03; daily volume now matches real contract volume across the whole archive. If you downloaded tick history before that date, re-pull it — the earlier encoding exposed raw quote updates alongside trades.

GET /history/book

Level 2 order-book depth archive — every bid/ask update. NQ ticks plan.

ParamRequiredDescription
symbolyesFutures root, e.g. NQ.
curl "https://api.tick-stream.xyz/v1/history/book?symbol=NQ&start=2024-01-10T14:30:00Z&end=2024-01-10T15:00:00Z" \
  -H "Authorization: Bearer sk_live_…"
{
  "symbol": "NQ", "count": 12044, "truncated": false,
  "book": [
    { "ts": 1704897000, "side": "bid", "level": 1, "price": 16942.50, "size": 14, "flag": 0 }
  ]
}

Each row: ts, side ("bid"/"ask"), level (1-based depth rank, 1 = best level in the stream's window), price, size, and flag.

Two eras, two models. From June 2026 onward rows are our own live capture: full-book snapshots at a ~250 ms cadence (≈4/s) — all levels of both sides re-stated in each snapshot, flag always 0. Group rows by ts and replace the whole book; no event-sourcing needed.

For the 2019 – Feb 2026 archive the source is an incremental depth tape and flag is the book action: 0 = add, 1 = update, 2 = remove. The replay rules below were derived empirically against two full days (24M events) and are the best-performing of ~10 candidate rule sets we measured:

  • remove → delete by price; the level field on removes is window bookkeeping (reads 10) — ignore it. A miss is a no-op (measured miss rate ~2–4%).
  • add → dedupe the price, then insert sorted (bids descending, asks ascending). An add is "a level entered the visible window" — do not insert at the level index (bottom entries report as level 9).
  • update at level L with price P — three cases vs. the current occupant of slot L: same price → size update; P better (closer to the touch) → insert at L (upward ladder shift); P worse → overwrite slot L (downward shift — the displaced level dies implicitly, no remove is sent for it). Always drop any other slot holding P.
  • Apply no cap and no re-sort of your own — the window maintains itself through the feed's add/remove flow (depth settles at ~9 per side).

Measured on full-day replays (2025-03-03 / 2025-06-13): whole-book consistency 72% / 61% of observations, top-3 levels clean 89% / 82%. The residual inconsistency lives in the lower ranks and is inherent to the vendor tape; for a guaranteed-consistent view, optionally drop any level that breaks strict monotonicity (top-down walk). Rows are stored and served in exact event order; replay each day from its first row (each day opens with an add-sequence snapshot, L1…L9 per side).

Archive window caveat. In the archive era the depth window sits behind the touch: the vendor streams best bid/ask separately, and the book stream's level 1 is typically one tick behind the true best (mode +1 tick, ~75% of the time). Treat the archive book as depth/liquidity structure, not as an exact top-of-book reference — for touch-sensitive work use the trade prints from the tick dataset alongside it, or the June-2026+ snapshot era, which is exact.

GET /history/options

Option-chain snapshot archive with full greeks. Options plan.

ParamRequiredDescription
underlyingyesOption underlying — historical archive covers QQQ, SPY, DIA, IWM.
curl "https://api.tick-stream.xyz/v1/history/options?underlying=QQQ&start=2024-01-10&end=2024-01-11" \
  -H "Authorization: Bearer sk_live_…"
{
  "underlying": "QQQ", "count": 8800, "truncated": false,
  "options": [
    { "ts": 1704902400, "expiry": "2024-01-19", "strike": 410, "right": "C",
      "bid": 2.41, "ask": 2.44, "last": 2.42, "oi": 15234, "volume": 812,
      "iv": 0.142, "delta": 0.55, "gamma": 0.04, "theta": -0.08, "vega": 0.21 }
  ]
}

Each row: ts, expiry, strike, right ("C"/"P"), bid, ask, last, oi, volume, iv, and Black-76 greeks delta, gamma, theta, vega.

tip

Pulling a large range? Page in chunks (e.g. one trading day at a time) and watch truncated. For continuous live data use the WebSocket stream; for recent backfill without the archive plan use /v1/ticks.