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 have the same length. StockChart.setData uses
normalizeOHLCVData to resolve the effective length from the timestamp column
and validate finite, monotonically ascending or descending timestamps. Equal
timestamps are accepted for static history. 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). Capacities and the line series count must be
positive integers. 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 retain
their order relative to bulk appends. Line addVector copies its values before
queuing them, so a scalar values array can be reused immediately.
Line appends require finite timestamps and aligned series columns. Keep X ascending and represent gaps only in the Y columns. Stock appends additionally require strictly increasing timestamps across calls, queued candles, and every chunk; repeating a timestamp is not an update operation.
Bulk validation runs before flushing queued samples or transferring input.
Rejected lengths or timestamps leave pending samples unchanged and caller
buffers attached; addCandleBatches validates all chunks before transferring
any of them. These checks do not replace application-side validation of units,
prices, volumes, or other feed semantics. See Line streaming
and Stock streaming for the method-specific contracts.