vike
Concepts

Freshness

How current each Data API answer is: the provisional hourly row, the freshness block, the position-match gate, snapshot age and the archive manifest.

Data reaches the API a little behind the clock, and some answers carry an old value in exactly the shape of a current one. Each section here is the field or rule that tells the two apart. The WebSocket's own latency is on /v1/stream.

The hourly series: the provisional row

Every row carries provisional, and it is true on at most one of them

The newest row covers the hour still in progress. The hourly rollup lands 60–120 minutes late, so without that row a "current positioning" read would be silently that stale. Its ts is a snapshot instant rather than an hour boundary and it changes on every poll: drop it when persisting a series. It is present only on the first page of a window reaching the present.

Cohort-metrics: the freshness block

Read the age off freshness.behind_hours, never off a number in prose

On any window that reaches the present the envelope carries {newest_ts, behind_hours, settled_lag_ceiling_hours, stale}. stale is the pre-computed verdict, so a consumer does not have to re-derive the rollup's cadence.

It exists because prose was not enough. grading=realized-pit reads a frozen research artefact: nothing has written to it since 2026-08-16 19:00 UTC. Ask it for an explicit recent window and it honestly answers with zero rows — but ask it the way a poller does (?grading=realized-pit&hours=1, no start) and it returns its own newest bucket, identical in shape to a current one, and days old. That gap is not a constant: it grows by 24 hours a day.

For live trading use grading=realized with labelBasis=point_in_time — honest labels, and one hour behind the clock rather than days.

A window ending in the past gets no freshness block at all: "the newest bar is four months old" answers a question a historical query did not ask, and would make every backtest fetch look broken.

Position matching: a 15-minute gate

A 15-minute freshness gate is why /positions/match returns fewer rows than the position history holds

Only positions seen within 15 minutes of the newest snapshot batch are matched. The latest-state view keeps a wallet's last-known row forever — 89.8% of it measured more than a day stale, the oldest ghost 2026-04-02 — so without the gate this matched months-closed positions as open. The gate is anchored on the newest snapshot batch rather than on the wall clock, so ingestion lag cannot empty the result.

A snapshot is as old as as_of_ts

On /orderbook, as_of_ts is the snapshot's own timestamp, not the ts you asked for — read it, because the nearest snapshot may be considerably older than your request.

The archive: the manifest is what is true today

Read generated_at in /archive/manifest.json before trusting a coverage figure. Anything below is a snapshot; the manifest is what is true today.

Recorder gaps are marked, not hidden

In the archive's book_events stream, status carries gap_start and live_resume markers where the recorder lost and regained the feed. Filter on them before treating a stretch of the book as continuous — silence in a full-L2 stream is otherwise indistinguishable from a quiet market.

On this page