Number of logical indices (distinct time points across all series).
The calendar the time axis follows past the last bar, or null.
Upsert bars into a series by time (used for history paging / backfill / out-of-order corrections, ARCHITECTURE.md §4.2). Existing times are replaced; new times are inserted; the result stays time-sorted.
Prepending older bars shifts every existing logical index up by the
inserted count: callers preserve the viewport by re-reading baseIndex
(the invariant rightEdge − index is unchanged, so visible bars don't move).
All bars of a series paired with their shared logical index.
Fractional logical index to UTC seconds, interpolating between bars and extrapolating past either edge.
indexToTime only answers for indices that have a bar. Anything anchored to
an arbitrary x (a drawing endpoint, a cursor readout, a projection to the
right of the last bar) needs a time for positions between bars too, which
the gapless axis (§5.3) makes common: everything a weekend or a session
break collapsed away lands there. Returns NaN when there is no data.
Past the last bar the whole indices are the bar times still to come: from
the session calendar when one is set (setSessionCalendar), otherwise one
median recent spacing apart. Never the last gap alone, which is the gap most
likely to be a night or a weekend. Left of the first bar the first gap
applies.
The last bar of a series with its shared logical index, in O(1).
Bulk-load (full replace) one series' data. Input is sorted and
de-duplicated by time by a private sortedUniqueByTime.
The shared index is rebuilt only when the set of times changes, and then only where it changed. Most whole writes do not change the set: a study's plots carry the source's own times, which the source put in the index before any study recomputed, and a colour overlay on the source keeps its times. Ten studies on a long history used to pay for the index two dozen times per tick while it came out unchanged.
Trading hours for the time axis to the right of the last bar, or null for none. With a calendar, the bar after a session's last one is the next session's first, across a night, a weekend or a closed date, so an anchor placed there lands on a time the market will print. Without one, or when the recent bars do not sit in its sessions, the axis continues at the median of the recent bar spacing.
This changes where times fall but asks for no frame: the data layer has
no way to reach the chart, so a drawing already placed past the last bar
stays where it was painted until something repaints. chart.setSessionCalendar
sets the same and repaints, and so do SessionCalendar.applyTo and
Instrument.applyTo, which go through it; call this directly only where
bars or a view change follow anyway.
Apply a single live bar (ARCHITECTURE.md §4.2 hot path). Returns the kind of change so the chart auto-scrolls only on a genuine right-edge append:
'append': newer than the last bar (advances baseIndex)'replace': same time as the last bar (intra-bar tick) or an existing time'insert': an older time inserted into history (late / out-of-order)Bars of a series whose logical index lies within [fromIndex, toIndex]. Binary-searches the (time-sorted) series into the visible time window instead of scanning all bars, so a full repaint costs O(log n + visible) per series, not O(total bars) - the hot path called for autoscale and drawing every frame.
Logical index of the latest real bar (length - 1), or -1 if empty.