Advanced Features
This tutorial covers the SDK capabilities beyond a basic chart and trading setup: multi-chart layouts, the runtime chart API, chart marks, tailoring the UI surface, real-time streaming, and state persistence.
Prerequisites
- A working chart from the Quick Start Guide
- Familiarity with the datafeed interface from Basic Integration
- For the streaming and persistence sections: the
appCallbackbasics from Trading Integration
Multi-Chart Layouts & Sync
The SDK terminal supports up to 4 charts in a single widget. Users switch layouts from the layout chooser in the bottom bar — one chart, two charts (stacked or side-by-side), and all three- and four-chart grid variants.
Below the layout grid, the same menu exposes six SYNC toggles that link the charts together:
| Toggle | Effect |
|---|---|
| SYNC Cursors | Crosshair position mirrors across all charts |
| SYNC Time | Visible time range pans/zooms together |
| SYNC All Symbols | Changing the symbol on one chart changes all |
| SYNC All Intervals | Changing the interval on one chart changes all |
| SYNC Chart Types | Candlestick/line/bar type applies to all charts |
| SYNC Drawings | Drawings replicate across charts |
Layout changes are reported to your app — see the Layout Change Events guide for the event payloads if you need to react to them (e.g. resizing surrounding UI).
Runtime Chart API
createChart() returns a handle you can use to drive the chart after creation — no need to recreate it:
const chart = GoChartingSDK.createChart("#chart-container", {
symbol: "BYBIT:FUTURE:BTCUSDT",
interval: "1D",
datafeed: myDatafeed,
licenseKey: "your-license-key",
});
// Later, from your own UI:
await chart.setSymbol("BYBIT:FUTURE:ETHUSDT"); // switch instrument
await chart.setInterval("15m"); // switch timeframe
await chart.setChartType("Line"); // change series type
chart.setTheme("light"); // "light" | "dark"In multi-chart layouts, the per-chart variants target a specific pane by index:
await chart.setIntervalAtIndex("1h", 1); // second chart only
await chart.setChartTypeAtIndex("Area", 2); // third chart onlyWhen you’re done with the chart (for example on a SPA route change), always destroy it so streaming subscriptions and observers are cleaned up:
chart.destroy();Chart Marks & Timescale Marks
Implement getMarks and/or getTimescaleMarks on your datafeed to render event badges on the chart. getMarks draws labeled dots on the price series (earnings, news, signals); getTimescaleMarks draws markers on the time axis.
const datafeed = {
// ...getBars, resolveSymbol, etc.
async getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) {
onDataCallback([
{
id: 1,
time: 1767139200, // unix seconds
color: "red",
label: "E", // letter inside the badge
labelFontColor: "white",
minSize: 25,
text: ["Earnings Report", "Q3 results", "Beat by 15%"], // tooltip lines
},
]);
},
async getTimescaleMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) {
onDataCallback([
{
id: 1,
time: 1767139200,
color: "blue",
label: "T1",
minSize: 30,
tooltip: ["Economic Data", "GDP release"],
},
]);
},
};The chart requests marks for the visible range and re-requests as the user scrolls. If your datafeed doesn’t implement these methods, no marks are drawn — they’re fully optional.
Customizing the UI Surface
Embedders rarely want the whole terminal. The exclude option and a few top-level flags let you trim it:
GoChartingSDK.createChart("#chart-container", {
// ...
exclude: {
leftPanel: true, // hide the drawing tools sidebar
rightPanel: false, // keep the right icon bar
topBar: false, // keep the top bar
bottomBar: false, // keep durations/timezone bar
// Remove specific indicators from the Study menu by type:
indicators: ["VWAP", "SMA", "ONBALANCEVOLUME"],
},
disableSearch: true, // no symbol search in the top bar
disableCompare: true, // no Compare button
showCrosshairPlusIcon: false, // hide the "+" quick-action on the crosshair
});Indicator types in exclude.indicators are the internal type codes (e.g. "SMA", "MACD", "VWAP"), not display names.
Real-Time Streaming
For live updates the chart calls subscribeTicks on your datafeed once a symbol resolves, and unsubscribeTicks when it no longer needs the stream. Push each trade to the callback and the chart builds bars from ticks itself:
const datafeed = {
subscriptions: new Map(),
subscribeTicks(symbolInfo, resolution, onRealtimeCallback, subscriberUID) {
const ws = new WebSocket("wss://stream.bybit.com/v5/public/linear");
const topic = `publicTrade.${symbolInfo.symbol}`;
ws.onopen = () => ws.send(JSON.stringify({ op: "subscribe", args: [topic] }));
ws.onmessage = (event) => {
const { topic: t, data } = JSON.parse(event.data);
if (t !== topic || !data) return;
data.forEach(({ T, s, S, p, i, v }) => {
onRealtimeCallback({
type: "trade",
productId: `BYBIT:FUTURE:${s}`,
symbol: s,
exchange: "BYBIT",
segment: "FUTURE",
timeStamp: new Date(T),
tradeID: i,
price: Number(p),
quantity: Number(v),
amount: Number(p) * Number(v),
side: S.toUpperCase(), // "BUY" | "SELL"
});
});
};
this.subscriptions.set(subscriberUID, ws);
},
unsubscribeTicks(subscriberUID) {
this.subscriptions.get(subscriberUID)?.close();
this.subscriptions.delete(subscriberUID);
},
};A complete, runnable version of this (including reconnect handling and shared sockets across charts) is in the Advanced Trading Demo on CodePen and examples/codepen-advanced2.html in the SDK package.
State Persistence & Templates
Auto-save is on by default: the chart persists its state (symbol, interval, indicators, drawings) to sessionStorage and restores it on reload. Disable it if you manage state yourself:
GoChartingSDK.createChart("#chart-container", {
// ...
autoSave: false,
});For durable, server-side persistence, listen for the save events in appCallback:
appCallback: ({ eventType, message }) => {
switch (eventType) {
case "SAVE_CONFIGURATION_STORE":
// Chart state changed — snapshot it to your backend
break;
case "SAVE_TEMPLATE":
// User saved an indicator/drawing template
break;
case "DELETE_TEMPLATE":
// User deleted a template
break;
}
},Configuration Extras
Localization
The UI ships with 20 locale keys. Pass one at creation:
GoChartingSDK.createChart("#chart-container", {
// ...
locale: "de-DE",
});Available: en-US, zh-CN, zh-TW, fr-FR, br-BR, ja-JP, jp-JP, pl-PL, es-ES, it-IT, ru-RU, de-DE, ar-AR, il-IL, th-TH, vn-VN, id-ID, my-MY, kr-KR, tr-TR. (ja-JP and jp-JP both resolve to Japanese.)
Theme overrides
Beyond theme: "dark" | "light", you can seed the initial chart configuration and accent color:
GoChartingSDK.createChart("#chart-container", {
theme: "dark",
themeColor: "#1e222d", // base UI color override
defaultInitialChartConfig: { /* initial chart config overrides */ },
});Mobile & native hosts
Use touchMode for the full JS mobile Chart-tab shell, or isNativeApp when a native WebView owns chrome and listens on the sendToNative bridge.
GoChartingSDK.createChart("#chart-container", {
isNativeApp: true, // canvas only; events → RN / Flutter / Android / iOS
});See Mobile Integration for bridge setup, message shapes, and platform snippets (React Native, Flutter, Android, iOS).
Debug logging
Production bundles are console-silent by design. To see the SDK’s internal logging during development:
GoChartingSDK.createChart("#chart-container", {
debugLog: true, // prefixes output with [GoCharting SDK]
});Related Documentation
- Trading Integration — orders, positions, and broker events
- Layout Change Events — reacting to layout switches
- Configuration API — every
createChartoption - Datafeed API — the full datafeed interface