Skip to content

@livefolio/sdk / runLive

Function: runLive()

runLive<F, S>(opts): AsyncIterable<LiveEvent<F, S>>

Defined in: strategy/run-live.ts:174

Drives a Strategy against a streaming market-data source and yields a unified event stream that consumer charts can append to historical snapshots without code branching.

Lifecycle on each tick:

  1. Resolve the tick's session date via the supplied Calendarcalendar.previous(calendar.next(tick.t)). This correctly handles after-hours ticks (NYSE 17:00 ET stays in the same session) and DST transitions.
  2. If the tick crosses a session boundary, finalize the just-closed bar: append it to the streaming FeatureRuntime, run strategy.build for REAL (committing state), submit orders to the executor, apply fills, and yield a snapshot event identical in shape to BacktestSnapshot.
  3. Record the tick into the current session's accumulating bar.
  4. Re-run strategy.features and strategy.build in PREVIEW mode (state is snapshot/restored — committed state is untouched). Yield a mark event with the recomputed features and preview orders.

State semantics: preview-build always operates on a deep clone of the committed state. Only the boundary-crossing commit branch advances committed state. This guarantees that 1000 ticks within a single session produce 1000 marks but leave state exactly where the prior session-close commit left it.

FeatureRuntime: if the strategy was built via fromSpec it captures its own runtime in the features closure. Pass that same instance via RunLiveOptions.streamingRuntime so appendBar calls land on the runtime the strategy actually reads. When omitted, runLive constructs its own streaming runtime seeded from history.bars — this works for hand-rolled strategies whose features method consults the runtime directly, but it leaves a fromSpec strategy reading a stale captured runtime.

Bar lineage: the streaming FeatureRuntime (provided or constructed) is seeded from history.bars, so indicators with warmup periods (SMA(200), etc.) work on the first live tick.

Universe: captured once at startup from strategy.universe(anchorTime, portfolio), where anchorTime is the last historical snapshot's timestamp (or epoch zero for empty history). Dynamic universes are not yet supported in live mode.

Termination: the iterable terminates when the underlying StreamingDataFeed.subscribe iterable terminates. Real adapters yield forever; tests use bounded iterables to assert specific event sequences.

Type Parameters

Type ParameterDefault type
F extends Readonly<Record<string, unknown>>Readonly<Record<string, unknown>>
Sunknown

Parameters

ParameterTypeDescription
optsRunLiveOptions<F, S>Live-runtime configuration. See RunLiveOptions.

Returns

AsyncIterable<LiveEvent<F, S>>

An open-ended AsyncIterable<LiveEvent>. Consumers for await the stream and dispatch on ev.type.

Example

ts
for await (const ev of runLive({ strategy, history, dataFeed, executor, calendar })) {
  if (ev.type === 'mark') {
    chart.updateLastBar({ t: ev.t, prices: ev.prices, previewOrders: ev.previewOrders });
  } else {
    chart.appendBar(ev); // BacktestSnapshot-shaped
  }
}

Released under the MIT License.