bigint) for storage, replay windows, and ordering. Sticking to ns end-to-end avoids drift between live runs and backtests.
Why nanoseconds
- Single precision — Internal APIs (replay bounds, event ordering, storage queries) expect
Timestamp<'ns'>. Values in other units are tagged ('us' | 'ms' | 's') so you cannot mix units by accident. - Conversion, not guessing — Anything you read from the outside world (milliseconds from
Date, microseconds from an exchange) should be wrapped with the right helper andconvert(..., from, 'ns')before passing it into core that require ns.
useTimestamp: one clock for strategy code
Call useTimestamp() when you need “now” inside code that must agree with replay and live/paper.
It returns { timestamp: Timestamp<'ns'> }:
- Live and paper — Uses
now(): wall time expressed in nanoseconds, stabilized withprocess.hrtimeso the clock is monotonic within the process. - Replay — Uses the replay scheduler’s current sample time (the event being processed), not wall clock. That keeps logs, ordering, and time-based branches aligned with the backtest stream.
Date.now() or new Date() for strategy semantics: in replay, wall clock has nothing to do with the simulated period.
Helpers: tag values and convert to ns
Fromuse-timestamp.ts:
| Helper | Meaning |
|---|---|
ns(n), us(n), ms(n), s(n) | Tag a bigint or number as that unit (not a conversion by itself). |
convert(value, from, to) | Scale between ns / us / ms / s. Use this to produce Timestamp<'ns'> for core APIs. |
add(a, b) | Add two timestamps in the same unit. |
now() | Wall-clock-aligned nanoseconds (when you need explicit time outside useTimestamp, still inside a valid runtime context). |
Replay and “backend” time
Replay options (from / to) are Timestamp<'ns'>. The CLI builds those from date strings by converting wall-clock bounds into ns before run.
While a replay is executing, useTimestamp().timestamp tracks the current replay sample, not the machine clock. Treat that as the authoritative “current time” for anything that should behave the same in live and replay.
Practical pattern
Tag events with the replay-aware clock when the observation happens in your pipeline (must run under the module / strategy context):useTimestamp() when you need run time (when this node saw the event in this execution).
Summary
| Context | What you get from useTimestamp().timestamp |
|---|---|
| Live / paper | Nanoseconds, wall-aligned via now() |
| Replay | Nanoseconds for the current replay event |
useTimestamp() anywhere strategy behavior depends on “now.”
Quickstart
See replay execution and npm scripts in the guided walkthrough.