Data model and ownership

Typed-array shapes, validation rules, gaps, and worker transfer ownership.

Sixtyfold receives each numeric field in its own Float64Array instead of as millions of row objects. This column layout makes transfer to a worker and rendering predictable.

The shapes below are the inputs accepted by the line methods and stock methods.

Line data

A single-series dataset has one ordered X column and one Y column:

interface TimeSeriesData {
  x: Float64Array;
  y: Float64Array;
  length: number;
}

Multi-series data shares X across every series:

interface MultiSeriesData {
  x: Float64Array;
  series: Array<Float64Array | {
    low: Float64Array;
    high: Float64Array;
    y?: Float64Array;
  }>;
  length: number;
  seriesCount: number;
}

Use the range object only for a range or band series. low and high define the envelope; optional y supplies its explicit center stroke. Omit y, or set the series width to zero, when a synthesized midpoint would be misleading.

X values must be finite and ascending. Timestamps are ordinary numbers; epoch milliseconds are conventional but not mandatory. minViewportRange, viewport values, marker timestamps, and every other X-domain option use the same unit as X.

Use NaN in Y, range-low, or range-high arrays for a real missing observation. Connected renderers break the path instead of drawing through the gap.

OHLCV data

interface OHLCVData {
  timestamp: Float64Array;
  open: Float64Array;
  high: Float64Array;
  low: Float64Array;
  close: Float64Array;
  volume: Float64Array;
  length: number;
}

All six columns must be aligned and have at least length entries. normalizeOHLCVData accepts ascending or descending timestamps. Ascending input retains its arrays; descending input is copied and reversed without mutating the caller.

Do not synthesize exchange closures or absent feed intervals merely to make timestamps regular. timeScale: "market" compresses absent intervals visually while labels, events, and markers keep their real timestamps.

Buffer ownership

In worker mode, bulk setData, setMultiSeriesData, addVectors, StockChart.setData, and stock batch APIs transfer typed-array buffers to the renderer for the fastest path. Transferred buffers become detached and must not be read or reused by the caller.

Clone explicitly when the application must retain its own copy:

chart.setData({
  x: sourceX.slice(),
  y: sourceY.slice(),
  length: sourceX.length,
});

Do not rely on main-thread fallback behavior to retain ownership. Treat bulk inputs as transferred regardless of the resolved renderer so switching browsers or CSP policies cannot change application correctness.

Streaming

Line streaming uses a fixed-size ring buffer initialized with initStreaming(seriesCount, maxPoints). Stock streaming uses initStreaming(maxCandles). Once capacity is reached, the oldest observations are replaced while chronological rendering is preserved.

Use vector or candle batch methods when data already arrives in columns. Single-observation methods batch through requestAnimationFrame and are convenient for modest live rates.