Skip to content

Financial sessions and trading toolbar

candlestick, ohlc and volumePrice support an explicit session policy on a time X axis. Omit axes.x.sessions to retain the existing continuous-time behavior. No exchange, weekday, holiday or extended-hours calendar is inferred. This is a chart projection policy; prices, volumes, category IDs and source timestamps do not change.

import {
createChart, createChartSessionCalendar,
type ChartFinancialSessionPolicy,
} from '@revolist/charts';
// Illustrative supplied sessions, not an exchange calendar service.
const calendar = createChartSessionCalendar({
timeZone: 'America/New_York',
sessions: [
{ date: '2024-03-08', open: '09:30', close: '16:00' },
{ date: '2024-03-11', open: '09:30', close: '16:00' },
{ date: '2024-03-12', open: '09:30', close: '13:00' },
],
});
const policy: ChartFinancialSessionPolicy = { mode: 'session', calendar };
const chart = await createChart({
container,
chartType: 'candlestick',
data: prices,
mapping: {
category: { field: 'timestamp' },
series: ['open', 'high', 'low', 'close'].map(field => ({ field })),
},
bindings: { open: ['open'], high: ['high'], low: ['low'], close: ['close'] },
axes: { x: { scale: 'time', sessions: policy } },
navigation: {
enabled: true, tradingToolbar: true, navigator: true, crosshair: true,
},
annotations: { editable: true },
});
OptionContract
axes.x.sessions?Persistable ChartFinancialSessionPolicy. Also supported on each axes.xAxes[id]. Financial families and explicit scale: 'time' only.
sessions.modesession: elapsed open-session time, with all supplied closures removed. ordinal: equal spacing of explicitly supplied observation anchors, independent of elapsed time or loaded pages.
sessions.calendarRequired ChartSessionCalendar: { timeZone, sessions: [{ open, close }] }. open/close are actual epoch milliseconds.
calendar.timeZoneRequired valid IANA zone (including UTC). Used for compressed-axis tick display; it does not reinterpret already stored instants.
calendar.sessions1–100,000 ordered, nonoverlapping, positive-duration intervals. Each boundary is a safe integer within JavaScript Date limits; summed open duration must be a safe integer. Adjacent intervals are allowed.
sessions.instantsRequired only for ordinal mode: 2–100,000 strictly increasing actual timestamps, each inside a supplied interval and at a distinct open-time coordinate. Full-source anchors, not the current loaded page. Every observed timestamp must appear in this list. Repeated observations at the same timestamp may share one anchor.

Intervals are half-open [open, close) for observations. A bar timestamp equal to close is outside that interval. Supply boundaries matching the source’s timestamp convention, including extended hours or close-stamped bars, rather than relabeling their timestamps. Data outside the calendar or ordinal anchor set is rejected; it is never silently discarded. The last close is permitted as a domain endpoint, though it is not an observation timestamp.

Session mode preserves proportional spacing within open intervals. Ordinal mode assigns anchor i to coordinate i, interpolating between anchors in open-session time. Both modes collapse closures to a seam. The inverse at an exact seam chooses the next supplied open (the final seam resolves to the last close). Consequently, a time window endpoint authored inside a closure remains an actual stored instant, but an endpoint generated by navigation at that seam can resolve to the next open. Neither behavior invents an activated observation.

Ordinal anchors are global and explicit so switching detail pages cannot move the same timestamp to a different slot. Without full-source domain metadata, the first/last global anchors own the ordinal domain, even for a partially loaded frame. Explicit remote full-domain limits take precedence. Do not regenerate them from each page. A single seam cannot own two distinct ordinal anchors: for example, an interval close and the next interval open are not two different open-time positions. Use a calendar consistent with the source’s bar timestamp convention. Policy changes deliberately change geometry; they do not change source records.

createChartSessionCalendar(input) returns the serializable instant calendar above. Public docs and applications use the Charts API; civil arithmetic remains owned by the shared dates package.

Helper optionContract
timeZoneRequired named zone.
sessionsExplicit ordered civil sessions, 1–100,000 entries. No recurrence or holiday inference.
Entry dateOpening civil date, YYYY-MM-DD, including years below 100. Invalid/skipped dates reject.
Entry open, closeHH:mm or HH:mm:ss, 00–23 hours, 00–59 minutes/seconds.
Entry endDate?Explicit closing civil date for overnight sessions. Omission uses date; a non-increasing interval rejects.
disambiguation?reject (default), earlier, later. Ambiguous fold boundaries require an explicit choice. Gap/skipped boundaries always reject, including with earlier/later.

DST changes affect the resolved actual instants and open duration. Short/long sessions and market closures must be explicitly supplied. The helper never generates missing dates or shifts a nonexistent clock forward. The chosen civil disambiguation is already resolved into stored boundaries; persist the returned calendar, not a runtime callback.

Assign the policy independently to a primary or named X axis. Bind a financial group through its close-owned seriesOverrides[closeSeriesId].xAxis, or the existing paired volume-price assignments. Set navigation.xAxis to select the controlled axis. Existing axis reversal is honored by marks, crosshairs, navigator handles and viewport inversion. Price/volume panes share the same session projection.

All viewports remain { scale: 'time', min, max } in actual epoch milliseconds, including viewport.xAxes[id]. Never persist ordinal indices or session elapsed offsets as timestamps. Authored window bounds inside a closure are retained. A closed-only window displays an empty finite frame; it does not fabricate a nearest candle. Without larger full-domain metadata, a one-observation session frame has zero time extent and disables range selection. missingPeriods continues to describe authored path gaps; session policy controls spacing.

Crosshairs and raw activation use the existing canonical datum inspection owner. CSV/data views/export values retain actual source category timestamps and raw OHLC/volume values. Images and vectors retain the displayed compressed geometry. Tick callbacks receive actual instants and can override the calendar-zone fallback label. Existing calendar range presets keep their own explicit rangeSelector.timeZone policy; select the same zone when civil control boundaries should match session display.

Existing drawing controls persist time coordinates and named X identity. Pointer-to-time conversion uses the same inverse as navigation; authored annotations survive restore. Points in a closure project to its collapsed seam. Coordinates outside calendar coverage extrapolate for clipping; observations and full domains outside coverage still reject. No Fibonacci, channel tool or arbitrary pane composition is included.

navigation.tradingToolbar?: boolean opts financial charts into a shared management strip with the existing zoom, pan and reset actions. The existing annotation editor joins that strip when annotations.editable is enabled. Omission keeps the existing SVG navigation controls. It does not enable a new navigation/drawing model or automatically enable gestures: use existing navigation.enabled, navigator, action policies and annotation options.

Mouse, touch and keyboard use ordinary buttons. Actions retain the existing navigation.actions hidden/disabled settings, selected X axis, cancellation and rollback behavior. Keyboard action focus is retained after repaint. Drawing tools retain their own keyboard/Escape/Save behavior and annotation UI policies. uiControls['navigation.tradingToolbar'] hides/disables navigation buttons; annotation controls continue to follow annotations.editable and their own policies. Preview mode omits interactive controls. Toolbar DOM is outside SVG and excluded from normal image/vector exports.

localeText.navigation.tradingToolbar? overrides the group label (default Trading toolbar). Existing navigation labels/button texts and annotation editor locale options remain authoritative. No additional toolbar callback or saved DOM is required.

The complete supplied calendar must cover the full remote source domain, not only returned rows. Full-domain limits, including named X domains, are validated against calendar coverage. An uncovered response fails and retains the previous committed frame. Returned observations must satisfy the calendar/ordinal list. No browser-local weekday arithmetic or loaded-page inference changes the remote domain.

ChartDataSourceRequest.timePolicies? is an optional record keyed by primary or named X ID containing each explicit policy. viewport remains actual timestamp ranges. Existing providers that do not need the hints can ignore them, but their responses must still satisfy the policy. Request/cache identity includes axis policies; replacement cancels stale work through the existing abort/generation owner. Detail and overview responses must use source timestamps consistent with the same global policy; synthetic overview timestamps missing from an ordinal anchor list reject.

Pivot forwards these hints as PivotChartViewportDataRequest.chart.timePolicies. Existing Pivot semantic scope/query/correlation checks remain in force. A financial time policy changes projection and source window hints; it does not change grouping, record identity or drill-through.

Both createStandalonePivotChart and PivotChartsPlugin reuse the shared policy, toolbar and inverse projection. Pivot exports createPivotChartSessionCalendar, PivotChartSessionCalendar, PivotChartSessionCalendarInput and PivotChartFinancialSessionPolicy from its root and /charts entries.

import { createPivotChartSessionCalendar } from '@revolist/pivot/charts';
const calendar = createPivotChartSessionCalendar({
timeZone: 'UTC', sessions: [{ date: '2024-01-02', open: '09:00', close: '17:00' }],
});
// Pass axes/navigation/annotations through the existing chart create/update APIs.

Save the ordinary chart model: policies, returned calendars, ordinal anchors, named timestamp windows, toolbar flag and authored annotations are serializable. Restoring requires the same explicit calendar coverage and actual source timestamps. Runtime source handles still need reattachment. Update rejection retains the previous model; cancelled or stale source work cannot replace the current committed instants or policy.

This contract covers native financial SVG rendering and its existing exports. It makes no GPU, third-party-adapter, exchange-calendar-service or arbitrary trading-tool equivalence claim.