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
Simple Function Call (Recommended)
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
| Parameter | Type | Required | Description |
|---|---|---|---|
container | HTMLElement | string | DOM element or CSS selector for chart container | |
config | ChartConfig | Chart configuration object |
Configuration Object
| Parameter | Type | Required | Description |
|---|---|---|---|
datafeed | object | Datafeed object with required methods | |
symbol | string | Initial symbol to display | |
interval | string | Initial time interval | |
licenseKey | string | Your SDK license key | |
theme | string | Chart theme (‘light’ or ‘dark’, default: ‘light’) | |
locale | string | Locale for translations (default: ‘en-US’) | |
autosize | boolean | Enable AutoFit (default: true) | |
width | number | string | Chart width (default: ‘100%‘) | |
height | number | string | Chart height (default: ‘100%‘) | |
trading | object | Trading configuration (trading.enableTrading, …) | |
appCallback | function | Callback for trading and app events | |
onReady | function | Callback when chart is ready | |
onError | function | Callback 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:
| Category | Methods |
|---|---|
| Lifecycle | destroy(), isDestroyed(), getChartInstance() |
| Widget façade | activeChart(), 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 control | setSymbol(), 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 & settings | addIndicator(), addDrawing(), deleteObject(), updateSettings(), getChartState(), setChartState() |
| Templates | saveTemplate(), applyTemplate(), getTemplates(), deleteTemplate() |
| Trading data | setBrokerAccounts(), updatePositions() |
| Data / connection | resubscribeAll() |
| OI Profile | setOIProfile(), getOIProfileSettings() |
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
Example (Simplified API - Recommended)
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 visibleExample (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
componentWillUnmountoruseEffectcleanup
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 orgetChartInstance().
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:
Phase 1B lab (live)
Shapes / studies façade — create, list, remove, and related chart APIs:
Phase 1C lab (live)
Order / position / execution lines and related trading overlays:
Phase 1D lab (live)
Viewport, marks, export, and related chart APIs:
Phase 1E lab (live)
Drawing tools, magnet, lock, and related line-tool APIs:
Phase 2 lab (live)
Layout APIs — setLayout, layout, pane sizes, and related multi-chart controls:
Phase 4 lab (live)
Constructor / chart config options (features, overrides, favorites, adapters, …):
Phase 5 lab (live)
Persistence — save / load, server chart CRUD, and related adapters:
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| Method | Returns | Description |
|---|---|---|
chartsCount() | number | Charts in the current layout |
activeChartIndex() | number | 0-based index of the selected chart |
setActiveChart(index) | void | Select 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| Method | Returns | Description |
|---|---|---|
layout() | string | Current GoCharting layout id |
setLayout(layout) | void | Apply layout; emits layout / CHART_MODE_CHANGED |
layoutName() | string | null | Current 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): s→1, 2h→2, 2v→1|1, 3h→3, 3v→1|1|1, 4h→4, 4v→1|1|1|1, 2-2→2|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| Method | Notes |
|---|---|
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"| Method | Notes |
|---|---|
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());| Method | Returns | Notes |
|---|---|---|
save(callback?) | layout blob | Full 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 | null | Current named layout title |
showSaveAsChartDialog() / showLoadChartDialog() | void | Host 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" });| Method | Notes |
|---|---|
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();| Method | Notes |
|---|---|
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 id | Effect |
|---|---|
topBar | Desktop top bar |
drawingToolbar | Left drawings menu |
symbolSearch | Top-bar search |
compare | Compare button |
bottomBar / leftPanel / rightPanel | Feature 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));| Method | Notes |
|---|---|
takeClientScreenshot(options?) | Promise<HTMLCanvasElement> — native canvases + ChartBrandLogo, then html2canvas |
takeScreenshot() | Promise<string> — POST to config.snapshot_url; emits onScreenshotReady |
| Top-bar camera | Built-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 alonegetStudiesList / 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 onReady → supported_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");navigationButtonsVisibility / paneButtonsVisibility / dateFormat / timeHoursFormat
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| Method | Returns | Notes |
|---|---|---|
symbolSync() | ISyncApi | value() / setValue(boolean) / subscribe(cb) → unregister |
intervalSync() | ISyncApi | Same 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).
| Method | layoutStore key | Notes |
|---|---|---|
drawOnAllChartsEnabled() | syncDrawings | TV alias for draw-on-all |
crosshairSync() | syncCursors | Crosshair / cursor sync |
dateRangeSync() | syncDateRange | Visible range sync |
timeSync() | syncTime | Time / 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);| Event | Source | Notes |
|---|---|---|
activeChartChanged | CHART_SELECTED | Active pane changed |
layout | CHART_MODE_CHANGED | Multichart layout changed |
onAutoSaveNeeded | persistence | Debounced dirty — call saveChartToServer |
onChartLoaded | persistence | After load / restore |
onGrayedObjectClicked | GRAYED_OBJECT_CLICKED | A locked/grayed drawing was clicked — payload { objectId, chartId } |
| (raw string) | any appCallback eventType | e.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).
| Method | Description |
|---|---|
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)
| Method | Semantics |
|---|---|
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/appearancefrom the drawing catalog. visibledefaults totrue(required for the drawing to mount).- Time fields on
shapeuse 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/createAnchoredShapethrow.
| Shape | type / name | Key shape fields |
|---|---|---|
| Horizontal line | HORIZONTAL_LINE or STRAIGHT_LINE + name "Horizontal Line" | shape.y = price |
| Trend line | TRENDLINE + name "Line" | p1 / p2: .x = epoch ms, .y = price |
| Text | TEXT + 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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
bringToFront / bringForward / sendToBack / sendBackward | Reorder a drawing by objectId |
availableZOrderOperations(objectId, chartId?) | { bringToFront, bringForward, sendToBack, sendBackward } booleans |
selection() | IGraphicSelectedApi — get() / 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? }).
| Method | Description |
|---|---|
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)usingStudyInfo.chartIdfromgetAllStudies/getStudyById. PreferremoveEntityfor drawings. deleteObject/removeEntitysearch all panes whenchartIdis omitted, and throw if the id is not found.- After
applyStudyTemplate/loadChartTemplate, prefergetStudyById(or re-list withgetAllStudies) — 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 restoreInteractive 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).
| Method | Returns | Notes |
|---|---|---|
createOrderLine() | IOrderLineApi | Fluent: setPrice / setText / setQuantity / setTooltip, onModify / onMove / onCancel, remove() |
createPositionLine() | IPositionLineApi | Same setters + onClose / onReverse / onModify, remove() |
createExecutionShape() | IExecutionShapeApi | setPrice / 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().
| Method | Returns / args | Notes |
|---|---|---|
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) | void | One-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) | void | Allowlist only (throws otherwise) — see below |
requestSelectBar() | Promise<{ index, time }> | Resolves on next chart click; move crosshair over a bar first |
cancelSelectBar() | void | Rejects 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 (typicallyEXCHANGE: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 rangeParameters:
date(string | Date |{ date1, date2 }): Date to navigate to — aDateobject, 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 withtypeandidproperties
Access control: if construct-time
study_count_limitis set,addIndicator(here, onactiveChart(), and*AtIndex) throws once the pane already has that many studies.studies_access(whitelist/blacklist) is enforced earlier by excluding disallowed types fromgetStudiesList().
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 propertieschartId(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 deletechartId(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:
| Method | Description |
|---|---|
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 exactorderBook/tradeBook/positionsformats
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 positionkey
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:
- 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.
- WebSocket reconnection — After a network drop.
- 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);Related Documentation
- Configuration —
ChartConfigoptions - Chart Widget — convenience helpers (
setSymbol,*AtIndex, …) - GoCharting React Component — declarative React API
- Events —
appCallbackandsubscribechannels - Datafeed — custom data sources
- Themes — theme /
themeColor/ CSS variables - Framework integrations — React, Next, Vue, …
- Examples — working demos
For more examples and advanced usage, see the tutorials section.