Stock Chart.

PRO

Combine price history with financial exploration controls.

Live preview13 feature examples

LIVE EXAMPLE

Explore prices

Match the page theme
Interact with the chart to see selection and range-change results here.
OptionsChanges are reflected in the preview and code.
Appearance and style9
Title and dimensions3

Browse price history with Navigator and the range selector. All values are sample data.

View code
Current preview
<div id="chart-container" style="width: 100%; min-width: 0;"></div>

<script type="module">
  import { defineCustomElement as define0 } from '@syidax/advanced-pro/components/sy-stock-chart.js';
  define0();

  // Pro: complete registerLicense at app startup using your issued certificate.
  // The website preview certificate is not for use in customer apps.
  const specs = [
    {
      "id": "example-chart",
      "tag": "sy-stock-chart",
      "props": {
        "data": [
          {
            "time": 1767225600000,
            "open": 100,
            "close": 95,
            "high": 103,
            "low": 92,
            "volume": 1200
          },
          {
            "time": 1767312000000,
            "open": 104,
            "close": 106,
            "high": 109,
            "low": 101,
            "volume": 1337
          },
          {
            "time": 1767398400000,
            "open": 107,
            "close": 105,
            "high": 110,
            "low": 102,
            "volume": 1474
          },
          {
            "time": 1767484800000,
            "open": 109,
            "close": 114,
            "high": 117,
            "low": 106,
            "volume": 1611
          },
          {
            "time": 1767571200000,
            "open": 108,
            "close": 109,
            "high": 112,
            "low": 105,
            "volume": 1748
          },
          {
            "time": 1767657600000,
            "open": 106,
            "close": 103,
            "high": 109,
            "low": 100,
            "volume": 1885
          },
          {
            "time": 1767744000000,
            "open": 102,
            "close": 106,
            "high": 109,
            "low": 99,
            "volume": 2022
          },
          {
            "time": 1767830400000,
            "open": 100,
            "close": 100,
            "high": 103,
            "low": 97,
            "volume": 2159
          },
          {
            "time": 1767916800000,
            "open": 98,
            "close": 94,
            "high": 101,
            "low": 91,
            "volume": 2296
          },
          {
            "time": 1768003200000,
            "open": 99,
            "close": 102,
            "high": 105,
            "low": 96,
            "volume": 2433
          },
          {
            "time": 1768089600000,
            "open": 101,
            "close": 100,
            "high": 104,
            "low": 97,
            "volume": 2570
          },
          {
            "time": 1768176000000,
            "open": 105,
            "close": 100,
            "high": 108,
            "low": 97,
            "volume": 2707
          },
          {
            "time": 1768262400000,
            "open": 109,
            "close": 111,
            "high": 114,
            "low": 106,
            "volume": 2844
          },
          {
            "time": 1768348800000,
            "open": 113,
            "close": 111,
            "high": 116,
            "low": 108,
            "volume": 2981
          },
          {
            "time": 1768435200000,
            "open": 115,
            "close": 120,
            "high": 123,
            "low": 112,
            "volume": 1318
          },
          {
            "time": 1768521600000,
            "open": 115,
            "close": 116,
            "high": 119,
            "low": 112,
            "volume": 1455
          },
          {
            "time": 1768608000000,
            "open": 114,
            "close": 111,
            "high": 117,
            "low": 108,
            "volume": 1592
          },
          {
            "time": 1768694400000,
            "open": 111,
            "close": 115,
            "high": 118,
            "low": 108,
            "volume": 1729
          },
          {
            "time": 1768780800000,
            "open": 108,
            "close": 108,
            "high": 111,
            "low": 105,
            "volume": 1866
          },
          {
            "time": 1768867200000,
            "open": 105,
            "close": 101,
            "high": 108,
            "low": 98,
            "volume": 2003
          },
          {
            "time": 1768953600000,
            "open": 105,
            "close": 108,
            "high": 111,
            "low": 102,
            "volume": 2140
          },
          {
            "time": 1769040000000,
            "open": 107,
            "close": 106,
            "high": 110,
            "low": 103,
            "volume": 2277
          },
          {
            "time": 1769126400000,
            "open": 110,
            "close": 105,
            "high": 113,
            "low": 102,
            "volume": 2414
          },
          {
            "time": 1769212800000,
            "open": 114,
            "close": 116,
            "high": 119,
            "low": 111,
            "volume": 2551
          },
          {
            "time": 1769299200000,
            "open": 119,
            "close": 117,
            "high": 122,
            "low": 114,
            "volume": 2688
          },
          {
            "time": 1769385600000,
            "open": 121,
            "close": 126,
            "high": 129,
            "low": 118,
            "volume": 2825
          },
          {
            "time": 1769472000000,
            "open": 123,
            "close": 124,
            "high": 127,
            "low": 120,
            "volume": 2962
          },
          {
            "time": 1769558400000,
            "open": 121,
            "close": 118,
            "high": 124,
            "low": 115,
            "volume": 1299
          },
          {
            "time": 1769644800000,
            "open": 119,
            "close": 123,
            "high": 126,
            "low": 116,
            "volume": 1436
          },
          {
            "time": 1769731200000,
            "open": 116,
            "close": 116,
            "high": 119,
            "low": 113,
            "volume": 1573
          },
          {
            "time": 1769817600000,
            "open": 113,
            "close": 109,
            "high": 116,
            "low": 106,
            "volume": 1710
          },
          {
            "time": 1769904000000,
            "open": 112,
            "close": 115,
            "high": 118,
            "low": 109,
            "volume": 1847
          }
        ],
        "session": "24x7",
        "seriesStyle": "candlestick",
        "showNavigator": true,
        "showRangeSelector": true,
        "width": 640,
        "height": 440,
        "brandPosition": "bottom-right",
        "brandLogo": ""
      }
    }
  ];
  const container = document.querySelector('#chart-container');
  const elements = specs.map(({ tag, id, props }) => {
    const element = document.createElement(tag);
    element.id = id;
    Object.assign(element, props);
    element.setAttribute('aria-label', 'stock-chart example chart');
    return element;
  });
  container.replaceChildren(...elements);
  const chart = elements.at(-1);
  const onEvent = event => {
    console.log('flagClick', event.detail);
  };
  chart.addEventListener('flagClick', onEvent);
  const observer = new ResizeObserver(([entry]) => {
    const width = Math.max(160, Math.floor(entry.contentRect.width));
    elements.forEach(element => { element.width = width; });
  });
  observer.observe(container);

  // In an SPA, call this function when the view is disposed.
  function disposeChart() {
    observer.disconnect();
    chart.removeEventListener('flagClick', onEvent);
    container.replaceChildren();
  }
</script>

Usage and data

#

Build financial interfaces with range selection, Navigator, and flags.

Align date time zones and trading sessions. The example uses fictional data to demonstrate display features.

Data contract

PropertyInput format
dataChronological OHLCV records.
session24x7 or a trading session.
flagsEvents with time, text, and title.
seriesStyleHow prices are drawn.

Updating data

Assign a new array or object to the property instead of mutating values inside an array. Chart events provide selection results through event.detail. When disposing of the view, clean up ResizeObserver and event listeners registered by your app.

Add to your interface

#

The code tabs below the preview contain the full data, options, event bindings, and responsive sizing for the current example. Copy them into an app project, such as Vite, that can resolve the installed packages.

Connect helper components to their target chart and shared data as shown in the example.

API reference

#

The full public API for sy-stock-chart. Pass objects and arrays as JavaScript properties. Select a name to view usage code and type definitions.

Key properties

Attribute / PropertyType / DefaultDescription
numberDefault: 760Chart width in pixels. Update with ResizeObserver when the container changes.
numberDefault: 420Chart height in pixels.
brandLogostringDefault: undefinedThe default is the Syidax logo. With the Pro chart.branding entitlement, use none or a PNG, JPEG, or WebP data URL.
brandPosition'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'Default: 'bottom-right'The corner where the logo is anchored. Applies equally to Community and Pro, on screen and in image exports.
StockDataInputDefault: undefinedChronological OHLCV records.
'24x7' | 'us-equity' | StockSessionInputDefault: '24x7'24x7 or a trading session.
showNavigatorbooleanDefault: falseSet as an HTML attribute or JavaScript property. type: boolean.
showRangeSelectorbooleanDefault: falseSet as an HTML attribute or JavaScript property. type: boolean.
StockResolutionDefault: '1d'Tape resolution: `1d` raw / `1w` / `1M` calendar roll-ups.
seriesStyleStockSeriesStyle | DerivedStockStyleDefault: 'candlestick'How prices are drawn.
upColorstringDefault: '#16a34a'Up/down candle colours (close ≥ open → up).
downColorstringDefault: '#dc2626'Set as an HTML attribute or JavaScript property. type: string.
booleanDefault: trueSet as an HTML attribute or JavaScript property. type: boolean.
showLegendbooleanDefault: trueSet as an HTML attribute or JavaScript property. type: boolean.
ReadonlyArray<StockFlagInput>Default: undefinedEvents with time, text, and title.
showToolbarbooleanDefault: falseSet as an HTML attribute or JavaScript property. type: boolean.
chartTitlestringDefault: undefinedThe title inside the chart. Explain the data's unit and meaning alongside it.
chartSubtitlestringDefault: undefinedThe subtitle inside the chart.
Other properties 24
Attribute / PropertyType / DefaultDescription
visibleFromnumberDefault: undefinedVisible bar range (indices; defaults to everything).
visibleTonumberDefault: undefinedSet as an HTML attribute or JavaScript property. type: number.
dataGroupingstringDefault: 'auto'View-density grouping: `auto` (default) / `off` / a forced factor.
historyLoader(oldestTime: number, count: number) => Promise<ReadonlyArray<StockBarInput>> | ReadonlyArray<StockBarInput>Default: undefinedPass as a JavaScript property. type: (oldestTime: number, count: number) => Promise<ReadonlyArray<StockBarInput>> | ReadonlyArray<StockBarInput>.
historyThresholdnumberDefault: 30Bars from the head that trigger a history load (default 30).
ReadonlyArray<PaneSpecInput>Default: undefinedPass as a JavaScript property. type: ReadonlyArray<PaneSpecInput>.
brickSizenumberDefault: undefinedRenko brick size in price units (default auto — close range/50, nice).
reversalPctnumberDefault: 4Kagi reversal, percent (default 4).
boxSizenumberDefault: undefinedPoint & Figure box size (default auto) and reversal boxes (default 3).
reversalBoxesnumberDefault: 3Set as an HTML attribute or JavaScript property. type: number.
lineBreakCountnumberDefault: 3Line Break lookback (default 3-line break).
baselineValuenumberDefault: undefinedBaseline anchor for `series-style="baseline"` (default first visible close).
lineColorstringDefault: '#2563eb'Line/area/hilo ink.
priceScaleModestringDefault: 'linear'Right-scale space: `linear` (default) / `log` / `percent` / `indexed`.
referenceLinesstringDefault: undefinedReference lines, comma list: `current,previous-close,high,low,bid,ask`.
numberDefault: undefinedQuotes for the `bid`/`ask` reference lines.
numberDefault: undefinedSet as an HTML attribute or JavaScript property. type: number.
compareSymbolsReadonlyArray<CompareSymbolInput>Default: undefinedPass as a JavaScript property. type: ReadonlyArray<CompareSymbolInput>.
ReadonlyArray<StockIndicatorInput>Default: undefinedPass as a JavaScript property. type: ReadonlyArray<StockIndicatorInput>.
ReadonlyArray<StockDrawingInput>Default: undefinedPass as a JavaScript property. type: ReadonlyArray<StockDrawingInput>.
exportScalenumberDefault: 2Set as an HTML attribute or JavaScript property. type: number.
stringDefault: 'en-US'Set as an HTML attribute or JavaScript property. type: string.
ReadonlyArray<StockTradeInput>Default: undefinedPass as a JavaScript property. type: ReadonlyArray<StockTradeInput>.
ReadonlyArray<StockPositionInput>Default: undefinedPass as a JavaScript property. type: ReadonlyArray<StockPositionInput>.
Events 19
EventsDetail typeDescription
{ bars: number; visibleBars: number; renderMs: number }Emits rendering results in detail when chart drawing completes.
{ panes: Array<{ id: string; weight: number }> }The pane stack changed (drag, add/remove/reorder, weight set).
{ from: number; to: number }The visible window changed (navigator/scrollbar; fires on release).
{ range: StockRangeKey; from: number; to: number }A range button was applied.
{ resolution: StockResolution }The resolution changed.
{ oldestTime: number; count: number }A history load started / finished.
{ added: number; exhausted: boolean }CustomEvent.detail type: { added: number; exhausted: boolean }. Event names are case-sensitive.
{ index: number; time: number; price: number } | nullThe crosshair moved to a bar (`null` on leave).
{ ids: string[] }The compare set changed.
{ id: string; time: number; text: string; title?: string }A flag was clicked / hovered (`null` on hover leave).
{ id: string; time: number; text: string; title?: string } | nullCustomEvent.detail type: { id: string; time: number; text: string; title?: string } | null. Event names are case-sensitive.
{ ids: string[] }The indicator set changed (add/remove/update).
{ count: number; canUndo: boolean; canRedo: boolean }The drawing document changed (add/update/move/remove/undo/redo/load).
{ id: string } | nullA drawing was selected (`null` on deselect).
{ tool: string | null }The active placement tool changed (`null` = the cursor).
{ appended: boolean; time: number; close: number; bars: number }A live tick was applied (`appended` = a new bar opened).
{ id: string; time: number; side: 'buy' | 'sell'; price: number; quantity?: number }A trade marker was clicked.
{ applied: string[] }A template was imported (`applied` names the fields that landed).
{ format: string; filename: string }An export finished (`png` | `svg` | `csv`).
Methods 45

Stencil methods return Promises. Use await within an async function to read the result.

Method / ArgumentsReturn typeDescription
symbol: CompareSymbolInputPromise<void>Add a compare overlay (duplicate ids replace).
id: stringPromise<void>Remove a compare overlay by id.
spec: StockIndicatorInputPromise<StockIndicatorInput>Add an indicator instance (an explicit duplicate id replaces). A missing id is minted HERE and persisted into the spec, so later removals never re-number method-added instances.
id: stringPromise<void>Remove an indicator by resolved id (its synthesized pane goes with it).
id: string, params: Record<string, number | string>Promise<void>Merge params into an instance (by resolved id).
Promise<Array<{ id: string; kind: string; params: Record<string, number>; linkedTo: string; paneId: string | null; label: string; }>>Resolved indicator list (serialisable — no definition objects).
definition: IndicatorDefinitionPromise<{ ok: boolean; errors: string[] }>An asynchronous method. Check the argument and return types below.
kind: stringPromise<{ removed: boolean }>Remove a definition; live instances of the kind resolve away.
Promise<string[]>Registered indicator kinds (built-ins + custom), sorted.
id: stringPromise<Record<string, Array<number | null>> | null>Computed columns for one instance over the current render tape.
input: StockDrawingInputPromise<StockDrawing | null>Add a drawing (data-coordinate anchors); returns it with the minted id.
id: string, patch: Partial<Omit<StockDrawing, 'id'>>Promise<void>Merge a patch (anchors/style/meta/visible/locked) into a drawing.
id: string, deltaTime: number, deltaPrice: numberPromise<void>Translate a drawing by data-space deltas (locked drawings hold).
id: stringPromise<void>An asynchronous method. Check the argument and return types below.
Promise<void>An asynchronous method. Check the argument and return types below.
Promise<{ count: number; canUndo: boolean; canRedo: boolean }>An asynchronous method. Check the argument and return types below.
Promise<{ count: number; canUndo: boolean; canRedo: boolean }>An asynchronous method. Check the argument and return types below.
Promise<StockDrawing[]>The current document (deep-copied, serialisable).
Promise<string>Versioned JSON export of the document.
json: stringPromise<number>Restore a serialized document (undoable — it goes through the history).
id: stringPromise<Array<{ x: number; y: number }> | null>Projected css-px points for one drawing on the CURRENT render tape.
tool: string | nullPromise<void>Activate a placement tool (`null` = the select cursor).
Promise<string | null>An asynchronous method. Check the argument and return types below.
scale: number, anchorFraction?: numberPromise<{ from: number; to: number }>Zoom programmatically around an anchor fraction (default centre).
bars: numberPromise<{ from: number; to: number }>Pan programmatically by (ungrouped) bars.
data: StockDataInputPromise<void>Replace the bar set.
tick: StockTickInputPromise<{ appended: boolean; time: number } | null>An asynchronous method. Check the argument and return types below.
ticks: ReadonlyArray<StockTickInput>Promise<{ appended: boolean; time: number } | null>Batch ticks in ONE repaint (returns the last applied result).
Promise<string>An asynchronous method. Check the argument and return types below.
json: stringPromise<{ ok: boolean; applied: string[] }>Apply a template (per-field whitelist; drawings land undoably).
Promise<string | null>The composed standalone SVG snapshot (canvas raster + SVG chrome + the brand).
Promise<string>The tape as a CSV table (ISO time, OHLC, volume).
Promise<void>Download the composed snapshot as a PNG at `export-scale`. The grant is confirmed again after the rasterisation await: one lost (or changed) meanwhile rejects with the §4.1 `stale` refusal — no download, no `exported`.
Promise<void>Download the composed snapshot as an SVG file (composed and saved in one turn, under a confirmed grant).
Promise<void>Download the tape as a CSV file (under a confirmed grant; getCSV stays the ungated read).
Promise<void>Print view with the inlined snapshot (the facade `print` mirror), opened under a confirmed grant.
Promise<{ bars: number; from: number; to: number }>Normalised bar count + visible range (diagnostics/tooling).
Promise<{ panes: Array<{ id: string; top: number; height: number }> }>Current pane rects (layout-local px).
pane: PaneSpecInput, at?: numberPromise<void>Append a pane (default at the bottom).
id: stringPromise<void>Remove a pane by id (the last pane stays).
id: string, to: numberPromise<void>Move a pane to a new stack position.
id: string, weight: numberPromise<void>Set a pane's weight directly.
count?: numberPromise<number>Pull older bars through `historyLoader` and keep the view anchored. chart.stock: when the grant ends (or changes) while the loader runs, nothing merges into the frozen tape and the call rejects with the §4.1 `stale` refusal. The licenseFeatureRefused event (code `stale`, method `loadOlderHistory`) is dispatched FIRST; the request then still ends with `historyLoaded { added: 0, exhausted: false }` so a loading state the app shows for historyRequested clears.
range: StockRangeKeyPromise<{ from: number; to: number }>Apply a range button: window the CURRENT tape by calendar maths.
resolution: StockResolutionPromise<void>Switch the tape resolution (resets the window — indices change).