Skip to Content
API ReferenceChart API

Chart Creation API

The GoCharting SDK provides a simple createChart() function for creating professional trading charts with built-in AutoFit and real-time capabilities.

Usage

import { createChart } from "@gocharting/chart-sdk"; const chart = createChart("#chart-container", { symbol: "AAPL", interval: "1D", datafeed: myDatafeed, licenseKey: "YOUR_LICENSE_KEY", });

Declarative React Component

<GoCharting symbol="AAPL" interval="1D" datafeed={myDatafeed} licenseKey="YOUR_KEY" />

See the GoCharting React Component documentation for the declarative API.

API Reference

createChart(container, config)

Creates a new chart instance with the specified configuration.

Syntax

function createChart( container: HTMLElement | string, config: ChartConfig ): ChartInstance;

Parameters

ParameterTypeRequiredDescription
containerHTMLElement | stringDOM element or CSS selector for chart container
configChartConfigChart configuration object

Configuration Object

ParameterTypeRequiredDescription
datafeedobjectDatafeed object with required methods
symbolstringInitial symbol to display
intervalstringInitial time interval
licenseKeystringYour SDK license key
themestringChart theme (‘light’ or ‘dark’, default: ‘light’)
localestringLocale for translations (default: ‘en-US’)
autosizebooleanEnable AutoFit (default: true)
widthnumber | stringChart width (default: ‘100%‘)
heightnumber | stringChart height (default: ‘100%‘)
tradingobjectTrading configuration (trading.enableTrading, …)
appCallbackfunctionCallback for trading and app events
onReadyfunctionCallback when chart is ready
onErrorfunctionCallback for errors

See the Configuration API for the complete ChartConfig (Phase 4 construct options, Phase 5 persistence, trading, mobile, …).

Returns

Returns a ChartInstance object. All methods are listed here and documented in detail below:

CategoryMethods
Lifecycledestroy(), isDestroyed(), getChartInstance()
Widget façadeactiveChart(), chart(index), chartsCount(), activeChartIndex(), setActiveChart(index), layout(), setLayout(layout), layoutName(), setLayoutSizes(sizes), resetLayoutSizes(), unloadUnusedCharts(), save() / load(), getSavedCharts(), saveChartToServer() / loadChartFromServer() / removeChartFromServer(), showSaveAsChartDialog() / showLoadChartDialog(), applyOverrides(), applyStudiesOverrides(), applyTradingCustomization(), setCSSCustomProperty(), getCSSCustomPropertyValue(), addCustomCSSFile(), customThemes(), features(), setFeatureEnabled(), getFeatureEnabled(), getFeatures(), headerReady(), createButton(), createDropdown(), removeButton(), onShortcut(), onContextMenu(), closePopupsAndDialogs(), showConfirmDialog(), showNoticeDialog(), selectLineTool(), selectedLineTool(), hideAllDrawingTools(), lockAllDrawingTools(), magnetEnabled(), magnetMode(), takeClientScreenshot(), takeScreenshot(), clearUndoHistory(), undoRedoState(), resetCache(), getStudiesList(), getStudyInputs(), getStudyStyles(), supportedChartTypes(), getIntervals(), symbolInterval(), mainSeriesPriceFormatter(), currencyAndUnitVisibility(), customSymbolStatus(), navigationButtonsVisibility(), paneButtonsVisibility(), dateFormat(), timeHoursFormat(), symbolSync(), intervalSync(), drawOnAllChartsEnabled(), crosshairSync(), dateRangeSync(), timeSync(), subscribe(), unsubscribe(), getAllCharts()
Chart controlsetSymbol(), setInterval(), setTheme(), setChartType(), resize(), goToDate(), setTimezone(), getTimezonePresets(), getCurrentTimezone() — also Chart Widget
Multichart (by index)setChartSymbolAtIndex(), setIntervalAtIndex(), setChartTypeAtIndex(), addIndicatorAtIndex(), addDrawingAtIndex(), deleteObjectAtIndex(), updateSettingsAtIndex(), getChartStateAtIndex(), setChartStateAtIndex() — also Chart Widget
Objects & settingsaddIndicator(), addDrawing(), deleteObject(), updateSettings(), getChartState(), setChartState()
TemplatessaveTemplate(), applyTemplate(), getTemplates(), deleteTemplate()
Trading datasetBrokerAccounts(), updatePositions()
Data / connectionresubscribeAll()
OI ProfilesetOIProfile(), getOIProfileSettings()
Note

Prefer activeChart() / chart(index) for per-pane work. Convenience helpers (setSymbol, *AtIndex, …) are summarized on Chart Widget. Most methods throw if called after destroy() or before the chart is ready — wait for onReady or use the returned instance after mount.

Built-in AutoFit Features

  • Zero Configuration - Works out of the box
  • Fully Responsive - Adapts to any container size
  • Bulletproof Sizing - Handles all edge cases
  • Automatic CSS - No external stylesheets needed
  • Real-time Resizing - ResizeObserver integration
import { createChart } from "@gocharting/chart-sdk"; // Create your datafeed object (no inheritance!) const myDatafeed = { async getBars(symbolInfo, resolution, periodParams) { // Fetch your market data return { bars: [...] }; }, resolveSymbol(symbolName, onResolve, onError) { const parts = String(symbolName).split(":"); const exchange = parts[0] || "NASDAQ"; const segment = parts.length >= 3 ? parts[1] : "EQUITY"; const symbol = parts[parts.length - 1] || "AAPL"; const name = symbol; const validIntervals = ["1m", "5m", "15m", "1h", "1D"]; onResolve({ exchange, segment, symbol, name, asset_type: "EQUITY", source_id: symbol, tradeable: true, is_index: false, is_formula: false, delay_seconds: 0, data_status: "streaming", contract_size: 1, tick_size: 0.01, display_tick_size: 0.01, volume_size_increment: 1, max_tick_precision: 2, max_volume_precision: 0, quote_currency: "USD", supports: { footprint: false }, exchange_info: { name: exchange.toLowerCase(), code: exchange, country_cd: "US", zone: "America/New_York", hours: [ { open: false }, { open: true }, { open: true }, { open: true }, { open: true }, { open: true }, { open: false }, ], valid_intervals: validIntervals, }, ticker: symbol, full_name: `${exchange}:${segment}:${symbol}`, description: name, type: "stock", session: "0930-1600", timezone: "America/New_York", has_intraday: true, has_daily: true, supported_resolutions: validIntervals, }); }, searchSymbols(userInput, exchange, symbolType, callback) { // Search for symbols callback(searchResults); } }; // Create chart with one simple call! const chart = createChart('#chart-container', { symbol: "NASDAQ:AAPL", interval: "1D", datafeed: myDatafeed, licenseKey: "demo-550e8400-e29b-41d4-a716-446655440000", theme: "light", onReady: () => console.log("Chart ready!"), onError: (error) => console.error("Chart error:", error) }); // Always clean up when done chart.destroy();

Example (With Trading Features)

// Create chart with trading enabled const tradingChart = createChart("#trading-chart", { symbol: "BYBIT:FUTURE:BTCUSDT", interval: "1m", datafeed: myDatafeed, licenseKey: "demo-550e8400-e29b-41d4-a716-446655440000", theme: "dark", trading: { enableTrading: true, // Enable trading context menus }, onReady: () => console.log("Trading chart ready!"), onError: (error) => console.error("Chart error:", error), }); // Trading features now available: // - Right-click context menu shows Buy/Sell options // - CrossHair menu shows trading options // - Settings > Trading tab is visible

Example (Declarative React Component)

import { GoCharting } from "@gocharting/chart-sdk"; function App() { return ( <GoCharting symbol="NASDAQ:AAPL" interval="1D" datafeed={myDatafeed} licenseKey="demo-550e8400-e29b-41d4-a716-446655440000" theme="light" height="600px" /> ); }

See GoCharting React Component for the full props reference and ref-based imperative access.

Methods

Lifecycle

destroy()

Destroys the chart and cleans up all resources including active subscriptions.

chart.destroy();

What it cleans up:

  • Active tick subscriptions - Unsubscribes from all WebSocket streams
  • Event listeners - Removes all DOM event listeners
  • ResizeObserver - Disconnects resize monitoring
  • React tree - Unmounts the chart component from the container
  • Memory references - Prevents memory leaks

Important Notes:

  • Always call destroy() when removing the chart from the DOM
  • Calling destroy() on an already-destroyed chart logs a warning and returns (no error)
  • Required for proper cleanup when recreating charts
  • Should be called in React componentWillUnmount or useEffect cleanup

Example with React:

useEffect(() => { const chart = createChart("#chart", config); return () => chart.destroy(); // Cleanup on unmount }, []);

isDestroyed()

Returns true if the chart has been destroyed.

if (!chart.isDestroyed()) { chart.setSymbol("MSFT"); }

Returns: boolean

getChartInstance()

Returns the underlying chart component instance (advanced use only).

const instance = chart.getChartInstance();

Returns: The internal ProfessionalChart ref, or null if not mounted.

Widget façade

Widget entry points on the createChart return value.

Principles: Payloads use GoCharting field names. Prefer activeChart() / chart(index) over Redux or getChartInstance().

Shipped: Phase 0–1E + Phase 2 + Phase 3 + Phase 4 construct options + Phase 5 persistence. Convenience helpers (setSymbol, *AtIndex, setBrokerAccounts, …): also listed on Chart Widget.

Interactive labs: phase0-1a-api-lab.html, phase1b-api-lab.html, phase1c-api-lab.html, phase1d-api-lab.html, phase1e-api-lab.html, phase2-layout-lab.html, phase3-overrides-lab.html, phase4-constructor-lab.html, phase5-persistence-lab.html, phase6-subscribeBars-lab.html, phase6-searchSymbolsPaginated-lab.html, phase6-onReady-udf-lab.html, tv-parity-construct-lab.html, tv-parity-adapters-lab.html, leftovers-api-lab.html.

Phase 0–1A lab (live)

Widget façade basics — activeChart / chart(i), counts, sync, subscribe:

Open in CodePen  | Full screen 

Phase 1B lab (live)

Shapes / studies façade — create, list, remove, and related chart APIs:

Open in CodePen  | Full screen 

Phase 1C lab (live)

Order / position / execution lines and related trading overlays:

Open in CodePen  | Full screen 

Phase 1D lab (live)

Viewport, marks, export, and related chart APIs:

Open in CodePen  | Full screen 

Phase 1E lab (live)

Drawing tools, magnet, lock, and related line-tool APIs:

Open in CodePen  | Full screen 

Phase 2 lab (live)

Layout APIs — setLayout, layout, pane sizes, and related multi-chart controls:

Open in CodePen  | Full screen 

Phase 4 lab (live)

Constructor / chart config options (features, overrides, favorites, adapters, …):

Open in CodePen  | Full screen 

Phase 5 lab (live)

Persistence — save / load, server chart CRUD, and related adapters:

Open in CodePen  | Full screen 

See also Widget / IChartApi types for TypeScript definitions.

activeChart() / chart(index)

Returns an IChartApi bound to the active chart or a specific 0-based index.

const active = chart.activeChart(); console.log(active.symbol(), active.interval()); active.setSymbol("MSFT"); active.setInterval("5m"); // setResolution / resolution() remain as aliases of setInterval / interval chart.chart(1).setChartType("candle"); chart.chart(0).addIndicator({ type: "SMA", id: "sma-1" });

Returns: IChartApi

chartsCount() / activeChartIndex() / setActiveChart(index)

console.log(chart.chartsCount(), chart.activeChartIndex()); chart.setActiveChart(1); // emits activeChartChanged / CHART_SELECTED
MethodReturnsDescription
chartsCount()numberCharts in the current layout
activeChartIndex()number0-based index of the selected chart
setActiveChart(index)voidSelect chart; emits activeChartChanged

layout() / setLayout(layout)

Multi-chart grid arrangement. GoCharting layout ids are canonical; common layout aliases are accepted by setLayout.

console.log(chart.layout()); // e.g. "1" chart.subscribe("layout", (info) => { console.log(info.layout, info.charts.length, info.isMultichartingEnabled); }); chart.setLayout("1|1"); // two stacked charts chart.setLayout("2h"); // TV alias → GoCharting "2" console.log(chart.chartsCount()); // 2
MethodReturnsDescription
layout()stringCurrent GoCharting layout id
setLayout(layout)voidApply layout; emits layout / CHART_MODE_CHANGED
layoutName()string | nullCurrent named layout title (Phase 5), or null

GoCharting ids: 1, 1|1, 2, 1|1|1, 3, 1-2, 2|1, 1|2, 2-1, 2|2, 4, 1|1|1|1, 1-3, 3-1, 1|3, 3|1.

TV aliases (mapped): s1, 2h2, 2v1|1, 3h3, 3v1|1|1, 4h4, 4v1|1|1|1, 2-22|2. Ids that already match GoCharting (2-1, 1-2, 1-3, 3-1, 4) work as-is.

setLayoutSizes(sizes) / resetLayoutSizes()

Programmatic multi-chart pane sizes (P2-2). Same persistence as drag-resize (sessionStorage key chartLayoutState). Percentages should match the current layout’s split counts (e.g. "1|1"rows: [40, 60]; "2"columns: [30, 70]).

chart.setLayout("1|1"); chart.setLayoutSizes({ rows: [35, 65] }); chart.resetLayoutSizes(); // equal splits again
MethodNotes
setLayoutSizes({ rows?, columns? }, disableUndo?)At least one of rows / columns; values must be finite > 0. disableUndo ignored (TV parity).
resetLayoutSizes(disableUndo?)Clears persisted sizes; panes return to equal splits

unloadUnusedCharts()

Dispose non-visible charts soft-stashed after a layout shrink (P2-6 / TV unloadUnusedCharts). GoCharting already drops panes from the live chartComponentList on shrink; orphans are held until this call so hosts can free stores/observers. Also clears chart event observers beyond chartsCount() and flushes sessionStorage GoChartingSDK.CompleteChartLayout to the visible layout.

Expanding a layout still clones the last visible chart (no TV soft-restore of prior panes).

chart.subscribe("layout", () => { chart.unloadUnusedCharts(); }); chart.setLayout("1"); // after "2|2"
MethodNotes
unloadUnusedCharts()Idempotent; safe when there are no stashed orphans

Persistence (Phase 5)

Serialize / restore layouts and named charts. Construct options (save_load_adapter, auto_save_delay, load_last_chart, saved_data, snapshot_url) are documented under Configuration → Persistence. Lab: phase5-persistence-lab.html.

const blob = chart.save(); await chart.load(blob); chart.subscribe("onAutoSaveNeeded", () => { chart.saveChartToServer({ name: chart.layoutName() || "Autosave" }); }); const id = await chart.saveChartToServer({ name: "My layout" }); await chart.loadChartFromServer(id); console.log(chart.layoutName());
MethodReturnsNotes
save(callback?)layout blobFull multi-chart snapshot; optional callback
load(state)Promise<blob>Restore GC layout blob (or JSON string)
getSavedCharts()Promise<meta[]>Named charts via save_load_adapter
saveChartToServer({ name?, id? })Promise<string>Persist named chart; returns id
loadChartFromServer(id)Promise<blob>Load named chart
removeChartFromServer(id)Promise<void>Delete named chart
layoutName()string | nullCurrent named layout title
showSaveAsChartDialog() / showLoadChartDialog()voidHost prompts for save/load (adapter-backed)

Also subscribe to onAutoSaveNeeded, onChartLoaded, chart_load_requested — see Events.

applyOverrides() / applyStudiesOverrides() / applyTradingCustomization()

Runtime theming / study / trading merges (P3-1). TV-like method names; payloads use GoCharting nested objects (not TV dotted paths like paneProperties.background).

// Chart appearance — all live charts chart.applyOverrides({ background: { backgroundColor: "#1a1a2e" }, }); // or wrapped: chart.applyOverrides({ appearance: { background: { backgroundColor: "#1a1a2e" } }, }); // Studies by type — live SERIES + objectTemplates for future adds. // Flat `{ strokeStyle }` is nested under appearance.EMA / appearance.RSI automatically. chart.activeChart().addIndicator({ type: "EMA", name: "EMA" }); chart.applyStudiesOverrides({ EMA: { strokeStyle: "rgba(255, 159, 67, 1)" }, RSI: { appearance: { strokeStyle: "rgba(29, 209, 161, 1)" } }, }); // Root trading prefs (same shape as construct-time `trading`) chart.applyTradingCustomization({ enableTrading: true, boxAlignment: "left" });
MethodNotes
applyOverrides(partial)Deep-merges into every chart’s config.appearance
applyStudiesOverrides(map)Keys = indicator type ("EMA", …); flat plot styles nest under appearance[TYPE]; updates live SERIES + objectTemplates
applyTradingCustomization(partial)Deep-merges root trading via SDK config overrides

Lab: phase3-overrides-lab.html.

setCSSCustomProperty / getCSSCustomPropertyValue / addCustomCSSFile / customThemes()

Runtime CSS theming for the chart container (P3-2). Names must start with --. These APIs do not retheme the canvas series — use setTheme / applyOverrides for that.

chart.setCSSCustomProperty("--gc-accent", "#3d8bfd"); console.log(chart.getCSSCustomPropertyValue("--gc-accent")); // "#3d8bfd" chart.addCustomCSSFile("./phase3-custom-theme.css"); // removed on destroy const themes = await chart.customThemes(); themes.applyCustomThemes({ "--gc-panel-bg": "#1a2332", "--gc-accent": "#ff9f43", }); themes.resetCustomThemes();
MethodNotes
setCSSCustomProperty(name, value)Sets on chart container style
getCSSCustomPropertyValue(name)Inline or computed value ("" if unset)
addCustomCSSFile(url)Idempotent <link> inject; cleaned up on destroy()
customThemes()Promise{ applyCustomThemes, resetCustomThemes, getCustomThemes }

features() / setFeatureEnabled / getFeatureEnabled / getFeatures()

Runtime chrome toggles (P3-3) beyond construct-time exclude / disableSearch / disableCompare / hideDrawingToolBar. Construct-time TV featuresets (disabled_features / enabled_features) are wired in P4-1 — see Configuration.

chart.setFeatureEnabled("topBar", false); chart.setFeatureEnabled("header_symbol_search", false); // TV alias chart.features().setValue({ drawingToolbar: false, compare: false }); console.log(chart.getFeatures());
Feature idEffect
topBarDesktop top bar
drawingToolbarLeft drawings menu
symbolSearchTop-bar search
compareCompare button
bottomBar / leftPanel / rightPanelFeature map / exclude (not all shells render every panel)

TV aliases: header_widget, left_toolbar, drawing_toolbar, header_symbol_search, header_compare, bottom_toolbar.

headerReady() / createButton / createDropdown / removeButton

Custom top-toolbar controls (P3-4). Prefer headerReady() before createButton.

await chart.headerReady(); const btn = chart.createButton({ align: "left" }); btn.textContent = "Ping"; btn.addEventListener("click", () => console.log("ping")); const dd = await chart.createDropdown({ title: "TF", align: "right", items: [ { title: "5m", onSelect: () => chart.setInterval("5m") }, { title: "1h", onSelect: () => chart.setInterval("1h") }, ], }); chart.removeButton(btn);

onShortcut / onContextMenu

Keyboard shortcuts and chart context-menu injection (P3-5). Shortcuts are ignored while focus is in an input/textarea.

const unsub = chart.onShortcut("alt+q", () => console.log("alt+q")); // chart.onShortcut(["alt", 81], () => {}); chart.onContextMenu((unixtime, price) => [ { position: "top", text: "Alert at price", click: () => console.log(unixtime, price), }, { text: "-" }, { position: "bottom", text: "Host action", click: () => {} }, { text: "-Reset chart" }, // hide built-in (best-effort) ]);

closePopupsAndDialogs / showConfirmDialog / showNoticeDialog

Dismiss open UI and show host dialogs (P3-6).

chart.closePopupsAndDialogs(); const ok = await chart.showConfirmDialog({ title: "Accept terms?", body: "Continue only if you agree.", }); await chart.showNoticeDialog({ title: "Saved", body: "Layout stored locally.", });

selectLineTool / hide / lock / magnet

Drawing toolbar state (P3-7).

chart.selectLineTool("trend_line"); console.log(chart.selectedLineTool()); // "trend_line" chart.hideAllDrawingTools().setValue(true); chart.magnetEnabled().setValue(true); // magnetMode() is a 0/1 view over the same boolean — GC only supports // magnet on/off (no TV weak(0)/strong(1) engine). Prefer magnetEnabled().

takeClientScreenshot / takeScreenshot

Local capture and optional upload (P3-8).

const canvas = await chart.takeClientScreenshot(); const dataUrl = canvas.toDataURL("image/png"); // Requires construct-time snapshot_url const url = await chart.takeScreenshot(); chart.subscribe("onScreenshotReady", (imageUrl) => console.log(imageUrl));
MethodNotes
takeClientScreenshot(options?)Promise<HTMLCanvasElement> — native canvases + ChartBrandLogo, then html2canvas
takeScreenshot()Promise<string> — POST to config.snapshot_url; emits onScreenshotReady
Top-bar cameraBuilt-in button (hide with exclude.screenshot); Download PNG / Copy to clipboard

clearUndoHistory / undoRedoState / resetCache

console.log(chart.undoRedoState()); chart.clearUndoHistory(); chart.resetCache(); // invalidate cached bars; does not refetch alone

getStudiesList / getStudyInputs / getStudyStyles

Catalog metadata (not live instances — use getAllStudies for those).

const types = chart.getStudiesList(); // GC type ids, e.g. "RSI" console.log(chart.getStudyInputs("RSI")); console.log(chart.getStudyStyles("RSI")); chart.activeChart().addIndicator({ type: "RSI" });

supportedChartTypes / getIntervals / symbolInterval / getDatafeedConfiguration

Chart style ids are strings (not a numeric enum). See Enums — chart type strings.

getIntervals() prefers the active symbol’s valid_intervals, then datafeed onReadysupported_resolutions, then the built-in catalog.

console.log(chart.supportedChartTypes()); // ["CANDLESTICK", "LINE", …] console.log(chart.getIntervals()); // ["1m", "5m", "1D", …] console.log(chart.symbolInterval()); // { symbol, interval } console.log(chart.getDatafeedConfiguration()); // from datafeed onReady (P6-1)

mainSeriesPriceFormatter / currencyAndUnitVisibility / customSymbolStatus

currencyAndUnitVisibility and customSymbolStatus are painted as small chips next to the symbol search box (not just an in-memory API) — set a value and the chip appears/updates automatically.

console.log(chart.mainSeriesPriceFormatter().format(1234.5678)); chart.currencyAndUnitVisibility().setValue("alwaysOn"); // paints a "CCY" chip chart.customSymbolStatus().symbol("BTCUSDT").setVisible(true).setTooltip("Note");
chart.navigationButtonsVisibility().setValue("alwaysOn"); chart.paneButtonsVisibility().setValue("alwaysOff"); chart.dateFormat().setValue("yyyy_mm_dd"); chart.timeHoursFormat().setValue("12");

symbolSync() / intervalSync()

Cross-chart sync controllers over layoutStore (syncSymbols / syncIntervals). Same behavior as the layout chooser toggles: turning on fans out the active chart’s symbol or interval.

chart.setLayout("1|1"); const sym = chart.symbolSync(); console.log(sym.value()); // false sym.setValue(true); // all charts take the active chart symbol sym.subscribe((on) => console.log("symbol sync", on)); chart.intervalSync().setValue(true); chart.setInterval("1h"); // fans out while sync is on
MethodReturnsNotes
symbolSync()ISyncApivalue() / setValue(boolean) / subscribe(cb) → unregister
intervalSync()ISyncApiSame shape; maps to syncIntervals

drawOnAllChartsEnabled() / crosshairSync() / dateRangeSync() / timeSync()

Additional sync controllers (P2-5 / P2-4). Same ISyncApi shape; turning on only flips the flag — ChartWidget / drawing code already honor them live (no fan-out).

MethodlayoutStore keyNotes
drawOnAllChartsEnabled()syncDrawingsTV alias for draw-on-all
crosshairSync()syncCursorsCrosshair / cursor sync
dateRangeSync()syncDateRangeVisible range sync
timeSync()syncTimeTime / scroll sync
chart.drawOnAllChartsEnabled().setValue(true); chart.crosshairSync().setValue(true); chart.dateRangeSync().setValue(true); chart.timeSync().setValue(true);

subscribe(event, callback) / unsubscribe(event, callback)

const onActive = (msg) => console.log("active chart", msg.idx, msg.symbol); chart.subscribe("activeChartChanged", onActive); // also: chart.subscribe("layout", …) // from CHART_MODE_CHANGED // chart.subscribe("onAutoSaveNeeded", …) // Phase 5 // or raw: chart.subscribe("CHART_SELECTED", …) chart.unsubscribe("activeChartChanged", onActive);
EventSourceNotes
activeChartChangedCHART_SELECTEDActive pane changed
layoutCHART_MODE_CHANGEDMultichart layout changed
onAutoSaveNeededpersistenceDebounced dirty — call saveChartToServer
onChartLoadedpersistenceAfter load / restore
onGrayedObjectClickedGRAYED_OBJECT_CLICKEDA locked/grayed drawing was clicked — payload { objectId, chartId }
(raw string)any appCallback eventTypee.g. "CHART_SELECTED"

Full event catalog: Events API. Works alongside appCallback.

getAllCharts()

const { isMultichartingEnabled, charts } = chart.getAllCharts();

Returns: { isMultichartingEnabled: boolean, charts: ChartSelectedMessage[] }


IChartApi — Phase 0 (symbol / objects)

Per-chart API from activeChart() / chart(index).

MethodDescription
chartIndex()0-based index of this chart
symbol()Current symbol string, or null
interval() / resolution()Current interval (e.g. "1m", "1D"); resolution is an alias
chartType()Current chart type string, or null
symbolInterval(){ symbol, interval } or null
setSymbol(symbol)Change symbol on this chart
setInterval(interval) / setResolution(interval)Change interval; setResolution is an alias
setChartType(chartType)Change chart type
addIndicator(indicator)Add an indicator ({ type, id, … })
addDrawing(drawing, chartId?)Add a drawing (prefer Phase 1B createShape for new code)
deleteObject(objectId, chartId?)Delete drawing or indicator (prefer removeEntity for drawings)
updateSettings(settings)Patch chart settings
getChartState() / setChartState(state)Persist / restore full chart state
const api = chart.activeChart(); console.log(api.chartIndex(), api.symbol(), api.interval(), api.chartType()); api.setSymbol("NASDAQ:MSFT"); api.setInterval("5m"); api.addIndicator({ type: "SMA", id: "sma-1" }); const state = api.getChartState();

IChartApi — Phase 1A (viewport / panes / export)

MethodSemantics
getVisibleRange() / setVisibleRange({ from, to })Visible time window in Unix seconds
getVisibleBarsRange()Visible bar indices { from, to } in loaded data
goToDate(date)Jump to a date (string | Date | { date1, date2 })
setTimeFrame(timeframe)String presets like "1D", or a TimeFrameInput object
zoomOut() / canZoomOut()Zoom out one step; canZoomOut() reports whether zoom-out is available
resetData()Resets viewport/scales; also triggers a real data refetch (cache invalidation + resubscribe) when the host wires it, in addition to the widget’s own resetChart()
exportData({ includeVolume?, useFullData? })Returns { schema, data } or null
getPanes()PaneApi[] — pane info plus getHeight / setHeight, getMainSeries(), getSeries() (SeriesPaneApi), getStudies(), getOverlays(), moveTo (GC ids, not TV paneIndex)
getAllPanesHeight() / setAllPanesHeight(heights)Get/set pane height fractions (chartOrder order). Pass either independent panes only or the full chartOrder. Independent (stacked) panes are normalized to sum to 1; dependent overlays (e.g. VOLUME_CHART on MAIN_CHART) keep a separate container fraction so the stack does not leave a bottom gap. Accepts fractions or relative weights.
getPriceToBarRatio() / setPriceToBarRatio(ratio)Get/lock the price-to-bar aspect ratio (setPriceToBarRatio sets preserveAspectRatio = true)
getTimeScale(){ getVisibleRange(), barSpacing? }
getSeries()Primary series as ISeriesApi (id / type / title / symbol / interval / chart style / visibility / priceScale()) or null
maximizeChart() / isMaximized()Maximize / query maximized pane state
symbolExt()Extended symbol info — includes max_tick_precision, tick_size (not TV pricescale / minmov). Axis tick labels follow this symbol metadata — GoCharting does not expose a TV-style host-controlled pricescale.
marketStatus(){ isOpen, statusText, dataStatus, delaySeconds } or null
inactivityGaps()Whether inactivity gaps are shown
setScrollEnabled(enabled) / setZoomEnabled(enabled)Enable/disable drag panning and mouse-wheel/pinch/toolbar zoom. Default true
clearMarks() / refreshMarks()Clear the current symbol’s marks/events, or re-fetch them via datafeed.getMarks
Series / pane / price scale (adapters)

PriceScaleApi (via series.priceScale() / getPriceScale()) supports y-scale mode, axis visibility, and price-to-bar ratio. It does not let the host redefine axis tick formatting — that comes from symbol tick_size / max_tick_precision.

const api = chart.activeChart(); const series = api.getSeries(); series?.setChartStyle("candles"); series?.priceScale().setMode("log"); series?.priceScale().setVisible(true); const panes = api.getPanes(); const main = panes?.[0]; console.log(main?.id, main?.getMainSeries()?.symbol()); main?.getSeries()?.getPriceScale()?.setPriceToBarRatio(2);

Interactive lab: examples/tv-parity-adapters-lab.html (series / panes / studies / selection / groups / drawing events). Also examples/leftovers-api-lab.html (viewport, drawings reload, marks, trading updatePositions, access gates, UI chips, resize/magnet/search delay).

const api = chart.activeChart(); const range = api.getVisibleRange(); // { from, to } Unix seconds if (range) { api.setVisibleRange({ from: range.from - 86400, to: range.to }); } api.setTimeFrame("1D"); api.zoomOut(); console.log(api.getVisibleBarsRange()); console.log(api.symbolExt()?.max_tick_precision, api.symbolExt()?.tick_size); console.log(api.getPanes()?.[0]?.id); // e.g. MAIN_CHART console.log(api.getAllPanesHeight()); api.setAllPanesHeight([0.7, 0.3]); // independent panes only, or full chartOrder // e.g. [0.7, 0.15, 0.15] with VOLUME dependent → main+study fill 100%; volume overlays console.log(api.getPriceToBarRatio()); api.setPriceToBarRatio(2); // locks 1 price unit == 2 bars api.setScrollEnabled(false); // disable panning api.setZoomEnabled(false); // disable wheel/pinch/toolbar zoom console.log(api.exportData({ includeVolume: true })?.data?.length);

IChartApi — Phase 1B (shapes / z-order / groups)

Creating shapes

createShape / createMultipointShape / createAnchoredShape all accept CreateShapeInput and return an objectId string.

CreateShapeInput fields: type, name, shape, options, appearance, chartId, visible

  • Aliases fill empty options / appearance from the drawing catalog.
  • visible defaults to true (required for the drawing to mount).
  • Time fields on shape use epoch ms; values in the seconds era are auto-normalized to ms.
  • If construct-time drawings_access (whitelist/blacklist by drawing type or name) denies the resolved type, createShape / createMultipointShape / createAnchoredShape throw.
Shapetype / nameKey shape fields
Horizontal lineHORIZONTAL_LINE or STRAIGHT_LINE + name "Horizontal Line"shape.y = price
Trend lineTRENDLINE + name "Line"p1 / p2: .x = epoch ms, .y = price
TextTEXT + name "Text"shape: { x: ms, y: price }; label via appearance.text
const api = chart.activeChart(); const hlineId = api.createShape({ type: "HORIZONTAL_LINE", name: "Horizontal Line", shape: { y: 100 }, chartId: "MAIN_CHART", }); const lineId = api.createShape({ type: "TRENDLINE", name: "Line", shape: { p1: { x: Date.now() - 86400000, y: 98 }, p2: { x: Date.now(), y: 102 }, }, }); const textId = api.createShape({ type: "TEXT", name: "Text", shape: { x: Date.now(), y: 101 }, appearance: { text: "Support" }, });
Query / remove / persist
MethodDescription
getAllShapes(chartId?)List drawings as ShapeInfo[]
getShapeById(objectId, chartId?)Single ShapeInfo or null
removeEntity(objectId, chartId?)Remove one drawing — prefer over deleteObject for drawings
removeAllShapes(chartId?)Remove all drawings on a pane (or all panes)
getLineToolsState()Snapshot { charts: { [chartId]: { objects, objectGroups } } }
applyLineToolsState(state)Restore a line-tools snapshot
reloadLineToolsFromServer()Reloads the current named layout (drawings included) from save_load_adapter when one has been saved via saveChartToServer(); otherwise warns and leaves drawings unchanged (does not throw)

To restore drawings with a full layout, use load() / loadChartFromServer(id), or reloadLineToolsFromServer() to reload the last-saved named layout in one call (Phase 5).

Z-order, selection, groups
MethodDescription
bringToFront / bringForward / sendToBack / sendBackwardReorder a drawing by objectId
availableZOrderOperations(objectId, chartId?){ bringToFront, bringForward, sendToBack, sendBackward } booleans
selection()IGraphicSelectedApiget() / set() / clear() / isEmpty() / showPropertiesDialog() / bringToFront() / sendToBack()
showPropertiesDialog(objectId?, chartId?)Open the properties UI for a drawing
shapesGroupController(){ createGroup, ungroup, getGroups, getGidDescription, getGroupVisibility, setGroupVisibility, getGroupsVisibility }
onDrawingEvent()ISubscription<DrawingEventParams>create / remove (also widget.subscribe("drawing_event", …))
const sel = api.selection(); sel.set({ chartId: "MAIN_CHART", objectId: hlineId }); console.log(sel.get()); const groups = api.shapesGroupController(); const gid = groups.createGroup([hlineId, lineId]); groups.setGroupVisibility(gid, false); console.log(groups.getGidDescription(gid), groups.getGroupsVisibility()); api.onDrawingEvent().subscribe(({ type, objectId }) => { console.log("drawing", type, objectId); }); chart.subscribe("drawing_event", ({ type, objectId, chartId }) => { console.log("widget drawing_event", type, objectId, chartId); });
End-to-end example (viewport + shapes + z-order)
const api = chart.activeChart(); // Viewport const range = api.getVisibleRange(); if (range) { api.setVisibleRange({ from: range.from - 86400, to: range.to }); } api.setTimeFrame("1D"); // Shapes const hlineId = api.createShape({ type: "HORIZONTAL_LINE", name: "Horizontal Line", shape: { y: 100 }, }); const lineId = api.createShape({ type: "TRENDLINE", name: "Line", shape: { p1: { x: Date.now() - 3_600_000, y: 98 }, p2: { x: Date.now(), y: 102 }, }, }); const textId = api.createShape({ type: "TEXT", name: "Text", shape: { x: Date.now(), y: 101 }, appearance: { text: "Note" }, }); api.bringToFront(hlineId); console.log(api.availableZOrderOperations(hlineId)); console.log(api.getAllShapes().length, api.selection().get()); const groupId = api.shapesGroupController().createGroup([hlineId, lineId]); console.log(api.shapesGroupController().getGroups()); console.log(api.shapesGroupController().getGidDescription(groupId));

IChartApi — Phase 1C (studies / templates)

Studies are kind: "SERIES" objects excluding MAIN_SERIES / VOLUME_SERIES. Create studies with existing addIndicator({ type, name?, options?, appearance? }).

MethodDescription
getAllStudies(chartId?)List studies as StudyInfo[] (includes chartId pane id)
getStudyById(objectId, chartId?)IStudyApi or null — inputs/styles, visibility, remove() (searches all panes if chartId omitted)
removeAllStudies()Remove every study on this chart panel
createStudyTemplate(nameOrOptions?)Snapshot { id, name, indicators, createdAt } and persist by default to favourite.TEMPLATES (Templates menu). Pass { name, save: false } for a snapshot only (no menu save).
applyStudyTemplate(template)removeAllStudies then addIndicator each item (study ids change — re-resolve with getStudyById / getAllStudies)
loadChartTemplate(input)String → favourite TEMPLATES by name/id; { indicators } → apply study template; ChartState blob (getChartState()) → setChartState

Notes:

  • Remove a single study with deleteObject(id, chartId) using StudyInfo.chartId from getAllStudies / getStudyById. Prefer removeEntity for drawings.
  • deleteObject / removeEntity search all panes when chartId is omitted, and throw if the id is not found.
  • After applyStudyTemplate / loadChartTemplate, prefer getStudyById (or re-list with getAllStudies) — applied studies get new ids.
const api = chart.activeChart(); api.addIndicator({ type: "SMA", name: "SMA" }); api.addIndicator({ type: "RSI", name: "RSI" }); const studies = api.getAllStudies(); console.log(studies.map((s) => ({ id: s.id, type: s.type, chartId: s.chartId }))); // Single-study remove (pane-aware) const rsi = studies.find((s) => s.type === "RSI"); if (rsi) api.deleteObject(rsi.id, rsi.chartId); const tpl = api.createStudyTemplate("My Mix"); // persists to Templates menu api.createStudyTemplate({ name: "temp", save: false }); // snapshot only api.removeAllStudies(); api.applyStudyTemplate(tpl); // ids changed — re-resolve const afterApply = api.getAllStudies(); const sma = afterApply.find((s) => s.type === "SMA"); if (sma) console.log(api.getStudyById(sma.id, sma.chartId)); const state = api.getChartState(); api.loadChartTemplate(state); // full chart restore

Interactive lab: examples/phase1c-api-lab.html.


IChartApi — Phase 1D (trading lines, library-native)

Chart overlay lines independent of Broker / setBrokerAccounts. Fields use GoCharting shapes (size, side, shape.y).

Library order/position lines are tagged options.source: "library" / libraryNative: true so broker book refresh and DELETE_ALL_ORDERLINES do not wipe them.

Setters (setPrice, setText, …) preserve forTicker and related drawing fields so the line stays mounted after the first update (drawings only render when forTicker matches the chart symbol).

MethodReturnsNotes
createOrderLine()IOrderLineApiFluent: setPrice / setText / setQuantity / setTooltip, onModify / onMove / onCancel, remove()
createPositionLine()IPositionLineApiSame setters + onClose / onReverse / onModify, remove()
createExecutionShape()IExecutionShapeApisetPrice / setTime (unix sec or ms) / setDirection("buy"|"sell") / setText, remove()
const api = chart.activeChart(); const order = api .createOrderLine() .setPrice(65000) .setText("Limit buy") .setQuantity(1) .onMove(() => console.log("moved", order.getPrice())) .onCancel(() => console.log("cancel clicked")); const pos = api .createPositionLine() .setPrice(64000) .setQuantity(2) .setText("Long") .onClose(() => console.log("close")); const fill = api .createExecutionShape() .setPrice(64500) .setTime(Math.floor(Date.now() / 1000)) .setDirection("buy"); // order.remove(); pos.remove(); fill.remove();

Interactive lab: examples/phase1d-api-lab.html.


IChartApi — Phase 1E (events + actions)

TV-like subscription objects: subscribe(cb) returns an unregister function; unsubscribe(cb?) removes one or all listeners. Event observers are cleaned up on chart.destroy().

MethodReturns / argsNotes
onSymbolChanged()ISubscription<void>Fires when chart security symbol changes
onIntervalChanged()ISubscription<void>Fires when interval changes
onChartTypeChanged()ISubscription<void>Fires when chart type changes
onDataLoaded()ISubscription<void>Fires on loading true → false
dataReady(cb)voidOne-shot when data is ready (not loading + bars present)
onVisibleRangeChanged()ISubscription<{ from, to }>Unix seconds; polled ~200ms while subscribed
crossHairMoved()ISubscription<{ time, price }>Polled ~50ms while subscribed; fields may be null
onHoveredSourceChanged()ISubscription<HoveredSourceEvent>{ entityId, chartId?, type? } or null
executeActionById(id)voidAllowlist only (throws otherwise) — see below
requestSelectBar()Promise<{ index, time }>Resolves on next chart click; move crosshair over a bar first
cancelSelectBar()voidRejects the pending select-bar promise

executeActionById allowlist: chartReset, zoomIn, zoomOut, undo, redo, invertScale, logScale, magnet (ChartActionId). See Enums & literal unions.

const api = chart.activeChart(); const unsub = api.onSymbolChanged().subscribe(() => { console.log("symbol →", api.symbol()); }); api.dataReady(() => console.log("bars ready")); api.onVisibleRangeChanged().subscribe((r) => { console.log("range", r.from, r.to); }); api.crossHairMoved().subscribe(({ time, price }) => { // throttle in your UI if needed }); api.executeActionById("zoomIn"); api.executeActionById("magnet"); api.requestSelectBar() .then(({ index, time }) => console.log("bar", index, time)) .catch((e) => console.warn(e.message)); // api.cancelSelectBar(); // unsub();

Interactive lab: examples/phase1e-api-lab.html.

Chart Control

Convenience helpers on the createChart return value (active chart). Prefer activeChart() for per-pane APIs. Full convenience catalog: Chart Widget.

setSymbol(newSymbol)

Changes the displayed symbol on the currently selected chart.

chart.setSymbol("NASDAQ:MSFT"); chart.setSymbol("BYBIT:FUTURE:BTCUSDT");

Parameters:

  • newSymbol (string): Symbol name (typically EXCHANGE:SEGMENT:SYMBOL)

setInterval(newInterval)

Changes the chart time interval.

chart.setInterval("1h"); chart.setInterval("5m");

Parameters:

  • newInterval (string): Time interval (‘1m’, ‘5m’, ‘15m’, ‘1h’, ‘4h’, ‘1D’, etc.)

setTheme(newTheme)

Changes the chart theme.

chart.setTheme("dark"); chart.setTheme("light");

Parameters:

  • newTheme (string): Theme name (‘dark’ | ‘light’)

setChartType(chartType)

Changes the chart type (candlestick, line, area, bar, etc.) of the currently selected chart.

chart.setChartType("line");

Parameters:

  • chartType (string): The chart type to apply

resize(width, height)

Resizes the outer chart container directly (numbers are treated as px, strings are passed through as CSS values e.g. "100%"). The existing AutoFit ResizeObserver picks up the change and recalculates dimensions on the next render — you do not need to call anything else after resizing.

chart.resize(800, 600); chart.resize("100%", "50vh");

Parameters:

  • width (number | string): New container width (px if a number)
  • height (number | string): New container height (px if a number)

See also the AutoFit guide if you’d rather let the container’s own size drive the chart.

goToDate(date)

Jumps to a specific date on the chart.

chart.goToDate("2025-06-01"); chart.goToDate(new Date(2025, 5, 1)); chart.goToDate({ date1: "2025-06-01", date2: "2025-06-15" }); // date range

Parameters:

  • date (string | Date | { date1, date2 }): Date to navigate to — a Date object, an ISO string, or a { date1, date2 } object for a range

setTimezone(timezone)

Sets the chart timezone.

chart.setTimezone("America/New_York");

Parameters:

  • timezone (string): IANA timezone name

getTimezonePresets()

Returns the available timezone presets.

const presets = chart.getTimezonePresets(); // [{ key, name, label }, ...]

Returns: Array of timezone presets with key, name, and label

getCurrentTimezone()

Returns the current timezone setting.

const tz = chart.getCurrentTimezone();

Returns: string - Current timezone

Indicators, Drawings & Objects

addIndicator(indicator)

Adds an indicator to the currently selected chart.

chart.addIndicator({ type: "EMA", id: "ema-20" });

Parameters:

  • indicator (object): The indicator object with type and id properties

Access control: if construct-time study_count_limit is set, addIndicator (here, on activeChart(), and *AtIndex) throws once the pane already has that many studies. studies_access (whitelist/blacklist) is enforced earlier by excluding disallowed types from getStudiesList().

addDrawing(drawing, chartId?)

Adds a drawing to the currently selected chart.

chart.addDrawing({ type: "TREND_LINE", options: { /* coordinates */ }, });

Parameters:

  • drawing (object): The drawing object with type/name, options, and appearance properties
  • chartId (string, optional): The chart pane ID to add the drawing to (default: "MAIN_CHART")

deleteObject(objectId, chartId?)

Deletes an object (drawing or indicator) from the currently selected chart.

chart.deleteObject("ema-20");

Parameters:

  • objectId (string): The ID of the object to delete
  • chartId (string, optional): The chart pane ID to delete from (default: "MAIN_CHART")

updateSettings(settings)

Updates chart settings for the currently selected chart.

chart.updateSettings({ timezone: "America/New_York", showGrid: true });

Parameters:

  • settings (object): Settings object to update

Chart State

getChartState()

Returns the complete chart state for the currently selected chart (symbol, interval, indicators, drawings, settings). Useful for persisting and restoring charts.

const state = chart.getChartState(); localStorage.setItem("myChart", JSON.stringify(state));

Returns: object | null - The complete chart state, or null if unavailable

setChartState(newState)

Restores a complete chart state on the currently selected chart.

const state = JSON.parse(localStorage.getItem("myChart")); chart.setChartState(state);

Parameters:

  • newState (object): The chart state object to apply

Multichart Methods (by index)

In multichart layouts, every “current chart” method has an AtIndex variant targeting a specific chart by its 0-based index:

MethodDescription
setChartSymbolAtIndex(newSymbol, chartIdx)Change symbol of the chart at chartIdx
setIntervalAtIndex(newInterval, chartIdx)Change interval of the chart at chartIdx
setChartTypeAtIndex(chartType, chartIdx)Change chart type of the chart at chartIdx
addIndicatorAtIndex(indicator, chartIdx)Add an indicator to the chart at chartIdx
addDrawingAtIndex(drawing, chartIdx, chartId?)Add a drawing to the chart at chartIdx
deleteObjectAtIndex(objectId, chartIdx, chartId?)Delete an object from the chart at chartIdx
updateSettingsAtIndex(settings, chartIdx)Update settings of the chart at chartIdx
getChartStateAtIndex(chartIdx)Get state of the chart at chartIdx
setChartStateAtIndex(newState, chartIdx)Set state of the chart at chartIdx
// Change the second chart in a multichart layout chart.setChartSymbolAtIndex("NASDAQ:MSFT", 1); chart.setIntervalAtIndex("1h", 1); chart.addIndicatorAtIndex({ type: "RSI", id: "rsi-14" }, 1);

Use the CHART_SELECTED event (see Events API) to track which chart the user has selected.

Templates

saveTemplate(templateName)

Saves the current indicators as a named template.

const template = chart.saveTemplate("My Setup");

Parameters:

  • templateName (string): Name for the template

Returns: The created template object

applyTemplate(template)

Applies a template to the current chart (replaces all indicators).

chart.applyTemplate(template);

Parameters:

  • template (object): Template object with an indicators array

getTemplates()

Returns all saved templates.

const templates = chart.getTemplates();

Returns: Array of template objects

deleteTemplate(templateId)

Deletes a template by ID.

chart.deleteTemplate(templateId);

Parameters:

  • templateId (string): ID of the template to delete

Trading Data

setBrokerAccounts(data)

Sets trading account data (accounts, orders, trades, positions) for the chart.

chart.setBrokerAccounts({ accountList: [ { account_id: "ACCOUNT_001", currency: "USD", balance: 50000, }, ], orderBook: [ /* active orders */ ], tradeBook: [ /* executed trades */ ], positions: [ /* open positions */ ], });

Parameters:

  • data (object): Broker account data — see the Datafeed API for the exact orderBook/tradeBook/positions formats

updatePositions(positions)

Updates existing positions without a full setBrokerAccounts rebuild — merges partial updates (e.g. pnlMultiplier, bid, ask) into positions by key and redraws. Throws if the chart isn’t ready yet (same lifecycle as setBrokerAccounts).

chart.updatePositions([ { key: "demo-BYBIT:FUTURE:BTCUSDT-POS_001", bid: 50100, ask: 50101 }, ]);

Parameters:

  • positions (array|object): Partial position updates keyed by position key

Data / Connection

resubscribeAll(idToken?)

Resubscribes to all active subscriptions and refreshes OHLCV. Handles candles, real-time ticks, compare symbols, and LIPI indicators.

When to call:

  1. Tab reactivation — After the browser tab was hidden for a long time, WebSocket throughput is throttled and candles may form incorrectly. Call this when the tab becomes visible again.
  2. WebSocket reconnection — After a network drop.
  3. Auth token refresh — Pass the new token so subscriptions use updated credentials.
// Recommended: refetch bars when the user returns to the tab let hiddenAt = 0; const LONG_HIDDEN_MS = 30_000; document.addEventListener("visibilitychange", () => { if (document.hidden) { hiddenAt = Date.now(); return; } if (hiddenAt && Date.now() - hiddenAt < LONG_HIDDEN_MS) return; chart.resubscribeAll(); }); // After WebSocket reconnect websocket.onreconnect = () => { chart.resubscribeAll(freshIdToken); };

Parameters:

  • idToken (string, optional): Authentication token for resubscription

OI Profile (Futures/Options)

setOIProfile(metric)

Sets the OI Profile metric for futures/options charts.

chart.setOIProfile("oi");

Parameters:

  • metric (string): OI metric to display ('oi', 'volume', 'delta', 'gamma', 'theta', 'vega')

getOIProfileSettings()

Returns the current OI Profile settings.

const settings = chart.getOIProfileSettings();

Returns: object - Current OI profile settings

Events

Lifecycle and trading callbacks (onReady, onError, appCallback) live on ChartConfig. Runtime subscriptions (chart.subscribe(...), layout/persistence events, …) are documented under Events. The façade subscribe / unsubscribe methods are listed above under Widget façade.

Best Practices

1. Use onReady Callback

The chart instance doesn’t expose symbol, interval, or isReady properties. Instead, use the onReady callback in the configuration:

const chart = createChart("#chart", { symbol: "AAPL", interval: "1D", datafeed: myDatafeed, licenseKey: "YOUR_KEY", onReady: (chartInstance) => { // Chart is ready - perform operations here console.log("Chart is ready!"); // You can now safely call methods chartInstance.setSymbol("MSFT"); }, });

2. Handle Errors Gracefully

Use the onError callback in the configuration to handle errors:

const chart = createChart("#chart", { symbol: "AAPL", interval: "1D", datafeed: myDatafeed, licenseKey: "YOUR_KEY", onError: (error) => { console.error("Chart error:", error); // Handle the error appropriately }, });

3. Clean Up Resources (Critical!)

// When component unmounts or page unloads chart.destroy();

Why this is critical:

  • Prevents WebSocket subscription leaks
  • Avoids receiving data for destroyed charts
  • Prevents memory leaks and performance issues
  • Required when recreating charts with new symbols/intervals

Common scenarios:

// React hook cleanup useEffect(() => { const chart = createChart("#chart", config); return () => chart.destroy(); }, []); // Chart recreation function recreateChart() { // Always destroy before creating new chart if (currentChart) { currentChart.destroy(); } currentChart = createChart("#chart", newConfig); } // Page unload window.addEventListener("beforeunload", () => { if (chart) { chart.destroy(); } });

4. Use Batch Updates

// Instead of multiple calls chart.setBrokerAccounts({ accountList: [...], orderBook: [...], tradeBook: [...], positions: [...] }); // For frequent lightweight updates (prices, PnL), prefer: chart.updatePositions(partialUpdates);

For more examples and advanced usage, see the tutorials section.

Last updated on