Skip to main content
Time in quantform must stay consistent across live execution and replay. If you mix wall-clock time with simulated backtest time, logs, ordering, and signals will disagree with what actually happened in the run.

Single source of truth: useTimestamp

useTimestamp is the hook you should use whenever you need “now” inside strategy or adapter code that runs in both real environments and replay.
  • Live and paper - returns wall-clock time (Date.now()), aligned with real execution.
  • Replay (backtest) - returns the current replay clock: the timestamp advanced by the replay scheduler as historical samples are processed, aligned to your backtest window and event order.
That means during backtest, useTimestamp does not return the real wall clock. It returns the simulated time for the sample currently being handled, so logging, correlation IDs, and any logic that branches on “current time” stay coherent with the replayed data.

Why not use Date.now() directly?

Using Date.now() or new Date() for strategy decisions or event tagging breaks replay:
  • In replay, events happened in the past; wall clock is unrelated to the backtest period.
  • You get inconsistent ordering, misleading logs, and logic that behaves differently in replay vs live.
Reserve raw Date.now() for code that truly must know the wall clock (for example diagnostics outside the strategy pipeline). For anything that participates in strategy semantics or event correlation, use useTimestamp.

What Core already does

Several helpers attach timestamps using useTimestamp so downstream code stays consistent:
  • useLogger prefixes log lines with a time derived from useTimestamp
  • withRequest and WebSocket helpers tag responses with useTimestamp()
Following the same rule in your components keeps your custom streams aligned.

Practical pattern

When you emit or transform events, prefer tagging with the replay-aware clock when the event is produced in your pipeline:
import { map } from 'rxjs';
import { useTimestamp } from '@quantform/core';

export function withEventTime<T>(source: Observable<T>) {
  return source.pipe(map(payload => ({ timestamp: useTimestamp(), payload })));
}
When an external feed already includes a trusted exchange timestamp, you can keep that field for market semantics and still use useTimestamp for “when this was observed in the run” if you need both.

Summary

ContextWhat useTimestamp returns
Live / paperWall-clock milliseconds (Date.now())
ReplayCurrent replay time, aligned to the backtest stream
Use useTimestamp everywhere strategy-relevant time matters so live and replay stay comparable and your backtest period is reflected correctly in time-based logic.

Replay workflow

See how replay windows and storage interact with scheduled time.