FastChart Integration Guide
Version 1.0.0 · For web & mobile app developers ·
This guide walks you through integrating the prebuilt FastChart SDK package into your application — you receive a zip archive containing a self-contained SDK folder; unzip it, serve it as static files, add one <script> tag, and the global FastChart object becomes available to your app. Each section builds on the previous one; a working quick-start takes about ten minutes.
1. Overview
FastChart is a GPU-accelerated financial charting library. It is framework-agnostic — the entire chart is driven through a single class, FastChartWidget, so it works equally well inside React, Angular, Vue, a plain HTML page, or a mobile WebView.
This guide covers the SDK package: you receive a zip archive containing a prebuilt, self-contained SDK folder. Unzip it, serve the folder as static files, add one <script> tag, and the global FastChart object becomes available to your application.
1.1 What you receive
| Item | Description |
|---|---|
| fastchart.js | The complete charting library as a single self-contained file. Exposes the global FastChart. |
| assets/ | Off-main-thread compute workers, the WebAssembly module, and the icon set. Must be served alongside fastchart.js. |
| monaco/ | Local copy of the Monaco code editor. Present in the FULL tier only (powers the FCScript IDE). |
| version.json | Build identity — version, git SHA, build timestamp. Quote this when raising a support ticket. |
| LICENSE.txt | Tier and licensing statement for the package you received. |
| types/ + fastchart.d.ts | TypeScript declarations for the SDK. fastchart.d.ts makes the FastChart global fully typed (section 18). |
| RELEASE-NOTES.md | Release notes for this package — review before upgrading (section 12). |
1.2 Technical characteristics
- Rendering backend is selected automatically: WebGPU → WebGL2 → Canvas2D. No configuration needed.
- Runs on any modern browser; heavy computation is moved off the main thread into workers and WebAssembly.
- Ships as a classic browser script (IIFE) — no bundler, no build step, no module loader required.
- 12 UI languages included; light and dark themes built in.
No bundler needed. The SDK is delivered as a prebuilt script. You do not need Webpack, Vite, Rollup or esbuild to consume it, and you do not need to add FastChart to your package.json.
2. Choosing your SDK tier
FastChart is licensed in three nesting tiers — each one is a strict superset of the tier before it. Your zip contains exactly one tier, agreed at the time of licensing.
| Tier | What it contains | Use this when |
|---|---|---|
| core | Chart, built-in indicators, drawing tools, panels | You need charting only. |
| fcs | core + the FCScript runtime engine | Your users must run custom scripted indicators that you supply. |
| full | fcs + the Monaco-based FCScript IDE, script gallery, debugger and profiler | Your users must author their own scripts inside your app. |
Because the tiers nest, the integration steps in this guide are identical for all three. The only tier-specific step is serving the monaco/ folder, which exists in the FULL tier only (see section 4.3).
Graceful degradation. Calling a feature above your licensed tier does not crash the chart — the call becomes a logged no-op, and any user data saved under a higher tier is preserved untouched. A custom indicator saved on a licensed build reappears intact when that profile is later opened by a licensed build again.
3. Unpacking and deploying the SDK
3.1 Extract the archive
Unzip the archive you received. The extracted folder is already the complete, deployable SDK:
fastchart-full-1.0.0/
├── fastchart.js ← the library (global: FastChart)
├── fastchart.d.ts ← global type declaration (section 18)
├── types/ ← full TypeScript declaration tree
├── RELEASE-NOTES.md
├── assets/
│ ├── ComputeWorker.js
│ ├── IndicatorWorker.js
│ ├── fcs.worker.js (fcs + full tiers)
│ ├── fcsValidate.worker.js (full tier only)
│ ├── fastchart_wasm.js
│ ├── fastchart_wasm_bg.wasm
│ ├── fastchart_wasm.version.json
│ └── fc-icons/ ← UI icon set
├── monaco/vs/ (full tier only — FCScript IDE editor)
├── version.json
└── LICENSE.txtKeep the folder intact. fastchart.js locates its workers and WebAssembly module relative to its own URL. Do not flatten the tree, rename assets/, or move fastchart.js away from it — if you must, configure the base URL explicitly as shown in section 4.2.
3.2 Copy it into your application
Place the extracted folder anywhere your web server publishes static files. Typical locations by stack:
| Stack | Copy the folder to | Resulting URL |
|---|---|---|
| Plain HTML / Apache / Nginx | /var/www/html/vendor/fastchart/ | /vendor/fastchart/fastchart.js |
| React (CRA / Vite) | public/vendor/fastchart/ | /vendor/fastchart/fastchart.js |
| Angular | src/assets/fastchart/ (or public/) | /assets/fastchart/fastchart.js |
| Vue | public/vendor/fastchart/ | /vendor/fastchart/fastchart.js |
| ASP.NET / Spring / Django | the static/wwwroot directory | /static/fastchart/fastchart.js |
| Mobile WebView | bundled app assets (see section 11) | file:///android_asset/... |
Angular note: files under src/assets/ are copied to the build output automatically. If you place the SDK elsewhere, add it to the "assets" array in angular.json so it is published with your build.
3.3 Server requirements
FastChart is served entirely as static files, but three server behaviours matter:
| Requirement | Why it matters | How to satisfy it |
|---|---|---|
| Correct MIME type for .wasm | The WebAssembly module fails to instantiate if served as text/plain or octet-stream. | Serve .wasm as application/wasm. |
| assets/ is publicly reachable | Workers and WASM are fetched at runtime by URL. If blocked, indicators and scripts never compute. | Do not place assets/ behind auth that blocks plain GET. |
| Same-origin hosting (recommended) | Workers are subject to cross-origin restrictions. | Serve the SDK from your own origin. If you must use a CDN, enable CORS on it. |
Example Nginx snippet, if your server does not already know the WASM type:
types { application/wasm wasm; }3.4 Content-Security-Policy
Broker platforms typically run a strict CSP. FastChart needs: script-src 'self' 'wasm-unsafe-eval' (the WebAssembly module; older Chrome needs 'unsafe-eval' instead), worker-src 'self' (workers are same-origin module scripts loaded by URL — no blob: needed when assets/ is served from your origin), style-src 'self' 'unsafe-inline' (the chart and Monaco inject inline styles), img-src 'self' data:, and connect-src covering your datafeed endpoints. When the SDK is served from a CDN, add that origin to script-src, worker-src and connect-src, and enable CORS on the CDN (section 3.3).
Tip. Serving the SDK same-origin keeps the policy smallest — the checklist above assumes it.
4. Loading the SDK
4.1 Add the script tag
A single classic script tag loads the entire library and defines the global FastChart:
<script src="/vendor/fastchart/fastchart.js"></script>Do not add type="module" and do not use import. The SDK build is a classic script; every export named in this guide is reached through the FastChart global — for example FastChart.FastChartWidget and FastChart.configureFastChartAssets.
For convenience, destructure once at the top of your bootstrap code:
const { FastChartWidget, configureFastChartAssets } = FastChart;4.2 Asset resolution (workers and WebAssembly)
FastChart resolves its workers and WASM module from the URL of its own <script> tag. As long as assets/ sits beside fastchart.js, this works with zero configuration. Declare the base URL explicitly whenever that assumption does not hold — a CDN, a hashed/versioned asset path, or an assets folder deployed separately from the script. It is also simply good practice in production, because it removes all guesswork:
const { configureFastChartAssets } = FastChart;
// Call ONCE at bootstrap, BEFORE creating the first chart.
configureFastChartAssets({
baseUrl: '/vendor/fastchart/assets/',
});| Option | Points at | Required? |
|---|---|---|
| baseUrl | The folder containing the worker scripts and fastchart_wasm.* files — i.e. the SDK's assets/ folder. | Optional; recommended in production. |
| monacoBaseUrl | The folder containing the vs directory — i.e. the SDK's monaco/ folder. | FULL tier only, when serving Monaco locally. |
Icons follow baseUrl too. The toolbar and context-menu icon set (assets/fc-icons/) resolves from the configured baseUrl exactly like the workers and WASM module (SDK 0.2.0+). Without a configured base, icons resolve relative to the host page, which only works when the page sits beside the SDK folder.
Order matters. configureFastChartAssets must run before the first new FastChartWidget(...). Configuring it afterwards has no effect on charts that already exist.
4.3 Monaco editor — FULL tier only
The FULL tier ships a local copy of the Monaco editor under monaco/vs/ so the FCScript IDE works with no internet access. Point the library at it — note the path is the parent of vs, not vs itself:
configureFastChartAssets({
baseUrl: '/vendor/fastchart/assets/',
monacoBaseUrl: '/vendor/fastchart/monaco/', // contains vs/
});- Omit monacoBaseUrl and the IDE falls back to loading Monaco from a public CDN — which fails in an air-gapped or offline deployment.
- The core and fcs tiers have no IDE, so this option is irrelevant to them.
5. Quick start — a working chart
A complete, self-contained page. Substitute your own datafeed and license key.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FastChart</title>
<style>
html, body { margin: 0; height: 100%; }
#chart { width: 100%; height: 100vh; }
</style>
</head>
<body>
<div id="chart"></div>
<!-- 1. Load the SDK -->
<script src="/vendor/fastchart/fastchart.js"></script>
<!-- 2. Your datafeed implementation (see section 6) -->
<script src="/js/my-datafeed.js"></script>
<script>
const { FastChartWidget, configureFastChartAssets } = FastChart;
// 3. Tell the library where its workers and WASM live.
configureFastChartAssets({
baseUrl: '/vendor/fastchart/assets/',
});
// 4. Mount the chart.
const widget = new FastChartWidget({
container: document.getElementById('chart'),
symbol: 'TCS',
interval: '5m',
datafeed: myDatafeed,
theme: 'dark',
autosize: true,
licenseKey: '<your license key>',
});
// 5. Run your code once the first data load completes.
widget.onChartReady(() => {
console.log('chart is ready');
});
</script>
</body>
</html>The container must have height. FastChart fills its container. A <div> with no height renders a blank chart and reports no error. Give it an explicit height, or a sized parent when using autosize: true.
5.1 Loading inside a framework
Frameworks that compile your source still serve the SDK as a plain static script. Load it once in index.html, then reference the global from your component. A React example:
import { useEffect, useRef } from 'react';
export function Chart({ symbol }) {
const hostRef = useRef(null);
const widgetRef = useRef(null);
useEffect(() => {
const { FastChartWidget, configureFastChartAssets } = window.FastChart;
configureFastChartAssets({ baseUrl: '/vendor/fastchart/assets/' });
widgetRef.current = new FastChartWidget({
container: hostRef.current,
symbol,
interval: '5m',
datafeed: myDatafeed,
autosize: true,
licenseKey: LICENSE_KEY,
});
// Always destroy on unmount — releases GPU buffers and workers.
return () => widgetRef.current?.remove();
}, []);
return <div ref={hostRef} style={{ width: '100%', height: 600 }} />;
}If your toolchain type-checks against window.FastChart, the SDK ships its declarations — add the package's fastchart.d.ts to your tsconfig and the global is fully typed (section 18).
6. Providing market data — the datafeed
FastChart never fetches data itself. You supply a plain object implementing the standard charting datafeed convention, and the chart calls into it. This is the main piece of integration work.
6.1 Methods to implement
| Method | Called when | Your implementation must |
|---|---|---|
| onReady(callback) | Once at startup | Call callback({ supported_resolutions: [...] }) with the intervals you support. |
| resolveSymbol(name, onResolve, onError) | A symbol is loaded | Call onResolve(symbolInfo). The fields listed in section 17.2 are required — name, session, timezone, pricescale, minmov, supported_resolutions and the rest. |
| getBars(symbolInfo, resolution, periodParams, onResult, onError) | History load and pagination | Return bars inside periodParams.from..to (unix seconds) via onResult(bars, { noData }). On backend failure call onError(reason) — see section 17.1. |
| subscribeBars(symbolInfo, resolution, onTick, guid) | After history loads | Start your live stream, calling onTick(bar) on every update. |
| unsubscribeBars(guid) | Symbol or interval changes | Stop the live stream for that guid. |
| searchSymbols(query, exchange, type, onResult) | User types in symbol search | NOTE: the built-in UI does not call this method — implement the onSearchSymbols widget option instead (section 17.3); this datafeed method exists only for convention compatibility. |
6.2 Bar format
Note the unit: time is the bar's start in milliseconds since the Unix epoch, while periodParams.from/to are in seconds.
{
time: 1720845000000, // bar start — MILLISECONDS since epoch
open: 2195.4,
high: 2198.0,
low: 2194.1,
close: 2196.7,
volume: 48210
}Resolution notation. Whatever notation your application passes for intervals, the datafeed always receives the canonical suffix form in resolution — '1m', '5m', '1h', '1D', '1W' — never the TV-style numeric form. Custom resolutions the SDK does not recognise are passed through verbatim.
6.3 Live updates
- Updating the forming candle — call onTick with the same time and revised high/low/close/volume.
- Starting a new candle — call onTick with a new time; the chart appends it automatically.
- Returning from background — nothing to do. FastChart detects the visibility change and backfills the bars missed while the app was suspended.
6.4 Symbol search
The toolbar's search popup is fed by the onSearchSymbols widget option. Supply it, or the widget falls back to a built-in sample list of US tickers:
onSearchSymbols: async (query) => {
const results = await myBackend.search(query);
return results.map(s => ({
symbol: s.symbol,
name: s.name,
type: 'stock',
exchange: 'NSE',
}));
},7. Configuration options
Options passed to the FastChartWidget constructor:
| Option | Type | Purpose |
|---|---|---|
| container | element | id | Where the chart mounts. Required. |
| datafeed | object | Your data provider. Required. |
| licenseKey | string | Unlocks your licensed tier and features. |
| ai | { generate(req, ctx), cancel?, forget?, labels? } | Full tier only. Optional hook that adds a "Code with AI" panel to the FCScript IDE (Ctrl/Cmd+Shift+I). FastChart never calls an AI or the network itself — your generate() callback does, and nothing is applied to the editor until the user clicks Apply (one undo step). Omit it and the IDE has no AI button or DOM at all. |
| symbol | string | Initial symbol identifier. |
| interval | string | Initial interval — '1m', '5m', '15m', '1h', '1D', '1W'. TV-style numeric notation ('1', '5', '60', 'D') is also accepted and normalised (SDK 0.2.0+). |
| theme | 'dark' | 'light' | Initial colour theme. |
| autosize | boolean | Track the container's size automatically. |
| width / height | number | Fixed pixel dimensions — an alternative to autosize. |
| locale | string | UI language; 12 are bundled (en, hi, ar, zh, …). |
| timezone | string | Timezone for the time axis. |
| layout | 'auto' | object | Responsive mode. 'auto' detects phone/tablet/desktop; { force: 'phone' } pins it. |
| load_last_chart | boolean | Restore the user's last symbol and interval from local storage. |
| enabled_features / disabled_features | string[] | Turn individual UI features on or off (section 16.1). |
| overrides | object | Fine-grained style overrides — colours, grid, candles (section 16.2). |
| onSearchSymbols | function | Hook feeding the symbol-search popup (section 6.4). |
| compare_symbols | array | Preset instrument list for the Compare dialog. |
| screenshotUsername | string | Name stamped onto exported screenshots. |
| storageKey | string | localStorage key for this widget's saved view (symbol, interval, range, indicators). The default is shared by every widget on the origin — set a distinct key per widget when a page hosts several independent charts (SDK 0.5.7+). |
| dockItems / dockRestore | array / boolean | Entries for the top-bar panels menu, and whether a half dock is remembered and reopened on the next chart (default true). See section 8.2 (SDK 0.4.0+). |
| heightMode | 'fix' | 'grow' | 'grow' makes the chart emit contentHeightChanged when a sub-panel is added or removed, so a scroll-embedded host can resize the container (SDK 0.4.0+). |
| onLoadError | function | Called when the main data reload fails. Return false to suppress the built-in error toast; the dataLoadError event still fires (SDK 0.6.1+). |
| fcsAllowedActions / fcsFetchAllowlist | string[] | Host policy for FCScript — which actions scripts may forward to your app and which hosts they may fetch from. See section 8.4 (SDK 0.5.6+). |
Interval precedence at startup. An interval you pass explicitly wins on the first load: the chart opens on it and selects the matching range preset. Once the user has a persisted view — or when load_last_chart is true — their last choice wins over the constructor option, and the range bar's auto-linked interval takes over from there (SDK 0.2.0+; earlier packages always opened on the 5Y/1W preset).
8. Controlling the chart at runtime
| Method | Behaviour |
|---|---|
| widget.onChartReady(cb) | Run cb once initialisation and the first data load complete. |
| widget.setSymbol(symbol, interval?, cb?) | Switch instrument and/or interval. |
| widget.changeTheme('Light' | 'Dark') | Switch theme at runtime. |
| widget.getTheme() | Read the current theme. |
| widget.activeChart() | Get the chart API — symbol(), setResolution(res), setTimeFrame(range), indicator methods, and more (section 15). From SDK 0.2.0, setResolution and setTimeFrame drive the full chart pipeline — interval/range labels, the linked range or interval, and a data reload — exactly like the equivalent toolbar action. setTimeFrame accepts 1D, 5D, 1M, 3M, 6M, 1Y, 5Y (aliases: 12M→1Y, 60M→5Y). |
| widget.applyOverrides({...}) | Apply style overrides live. |
| widget.save(cb) / widget.load(state) | Serialise and restore full chart state. |
| widget.takeScreenshot() | Download a snapshot image of the chart. |
| widget.subscribe(event, handler) | Listen to a user-action event (section 9). Returns a disposer function that removes the handler (SDK 0.5.8+). |
| widget.unsubscribe(event, handler) | Detach an event handler. |
| widget.unsubscribeAll(event?) | Remove every handler subscribed through the widget, or only those for one event (SDK 0.5.8+). |
| widget.detach() / widget.attach(container) / widget.isAttached() | Take the live chart out of the page and put it into another container without rebuilding it (section 8.1). |
| widget.holdAutoRefresh() | Defer passive refreshes while you retarget a pooled widget; returns a release function (section 8.1). |
| widget.openDock(opts) / closeDock() / expandDock() / collapseDock() | Open, close and resize the host dock — your own content beside or over the chart (section 8.2). |
| widget.remove() | Destroy the widget and release GPU buffers and workers. |
Always call remove(). In a single-page app, failing to call widget.remove() when the view is destroyed leaks GPU buffers and worker threads across navigations.
8.1 Reusing a widget across containers (pooling)
Constructing a widget costs a WebGL context plus shader compilation. To reuse one across a panel close and reopen cycle — a different host component or container — hand the live widget over instead of calling remove() (SDK 0.5.8+):
// panel closes
widget.unsubscribeAll(); // or call each disposer subscribe() returned
widget.detach(); // out of the DOM; GL context, shaders and state stay alive
pool.push(widget);
// panel reopens (possibly a different container)
const w = pool.pop();
w.attach(containerEl); // element or id, same document; re-measures and repaints
w.setSymbol('TCS', '5'); // retarget it
w.subscribe('buyClick', onBuy); // fresh handlers for the new owner- attach() moves the widget's own DOM — do not appendChild its root yourself. getElement(), getContainer() and isAttached() report where it is. A container in another document (a popout window) is rejected.
- While detached the chart does not paint, but feeds keep updating it: setSymbol() it on reuse, or remove() it when the pool drops it.
- attach() opens a short settle window in which the burst of intermediate sizes a docking layout (GoldenLayout and similar) delivers is coalesced; the final size always applies.
- Host theme colours are read once per host theme. If you change your theme variables without calling changeTheme(), call FastChartWidget.invalidateAppColors().
- Retargeting to a datafeed that does not know the previous symbol: setSymbol() already holds passive refreshes until the switch settles. If you swap the datafeed before calling setSymbol(), wrap the swap in const release = widget.holdAutoRefresh(); … release(); so a refresh cannot reload the old symbol against the new feed and show a false 'Could not load data' toast.
8.2 Host dock — your content beside or over the chart
FastChart no longer draws any order dialog. Order entry, depth, option chains and similar panels are your application's content, shown in a dock that FastChart opens and sizes for you (SDK 0.4.0+). Subscribe to dockOpen, fill the container you are given, and dispose your content on dockClose.
const widget = new FastChart.FastChartWidget({
// …
dockItems: [
{ id: 'depth', label: 'Market Depth', mode: 'half' },
{ id: 'chain', label: 'Option Chain', mode: 'full' },
],
});
widget.subscribe('dockOpen', ({ type, container, mode, context, restored }) => {
// type: 'depth' | 'chain' | 'quick-order' | 'full-order' | …
// context: { side, price, symbol } for the order types
mountMyPanel(type, container, context);
});
widget.subscribe('dockClose', ({ type }) => unmountMyPanel(type));
widget.openDock({ type: 'depth', mode: 'half' }); // programmatic open
widget.closeDock();- mode 'half' shrinks the chart beside (wide screens) or above (narrow) your panel; the top toolbar stays reachable. mode 'full' lays the dock over the chart — the whole viewport on phones — while the chart keeps running underneath, so nothing is lost when it closes.
- Order triggers need no dockItems entry: a Buy / Sell marker drop, a right-click order and an OI-bar long-press open the dock automatically (quick-order as half, full-order as full) and fire dockOpen with { side, price, symbol } as context. If no dockOpen listener exists, the older chartContextOrder event fires instead.
- A half dock is remembered and reopened on the next chart; dockOpen then carries restored: true — render it exactly like a user-opened one. Set persist: false on an item, or dockRestore: false on the widget, to opt out. Closing the dock forgets it.
- One dock is open at a time: opening another switches to it, and opening the same half item again closes it. A full dock displaces a remembered half dock and brings it back when the full dock closes.
8.3 Plot-only mode — a chart as a background
To use a chart purely as a backdrop, construct the engine class with plotOnly: true (SDK 0.7.0+). It draws the plot and nothing else — no axes, grid, crosshair, legends, volume bars, toolbars, menus or keyboard shortcuts — and never reads or writes localStorage, sessionStorage or IndexedDB, so it cannot affect or be affected by any other chart. It is available on the engine class FastChart, not on FastChartWidget.
// the engine class is FastChart.FastChart on the global (FastChart.FastChartWidget is the full UI)
const chart = new FastChart.FastChart(el, {
plotOnly: true,
theme: 'dark',
chartType: 'area',
// interactive: true, // optional: pan and zoom, still no chrome
});
chart.setData(bars); // framed edge to edge; appendBar() / updateLastBar() for live data- Inert by default: the canvases ignore pointer events, so clicks and wheel events reach whatever sits above or behind the chart.
- Every setData is a new plot: it fits the whole dataset to the box and returns Y to autoscale, so one chart can be reused for another instrument. appendBar() and updateLastBar() keep the viewport.
- The container needs a non-zero size (give a bare custom element display: block).
- Compute is plain TypeScript on the main thread unless you pass disableWASM: false — no WASM module or worker is fetched. An unlicensed build still shows its community notice; a valid licenseKey removes it.
8.4 FCScript host policy
Scripts talk to your app through host actions (place_order, cancel_order, modify_order, set_alert, navigate, export, screenshot, toast, …) and host.fetch_url / host.fetch_json. Two widget options restrict that surface (SDK 0.5.6+):
new FastChart.FastChartWidget({
// …
// Only these action kinds reach your app; others are dropped with one console warning per kind.
// undefined (default) = allow every kind; [] = none.
fcsAllowedActions: ['set_alert', 'toast'],
// Hosts host.fetch_* may reach: 'api.example.com', '*.example.com', 'host:port', '*'.
// undefined (default) = any http(s) URL; [] = none. Non-http(s) URLs are always refused.
fcsFetchAllowlist: ['*.example.com'],
});Regardless of these options every script is limited to 20 actions per second, timers of at least 50 ms (64 per script) and 64 distinct fetch requests per run. Resource limits stop a runaway script with a clear error instead of freezing the page: 128 nested calls, 4,000,000 collection elements, 1 MiB strings and 25,000,000 loop iterations per bar.
9. Listening to user actions
Subscribe to chart events to connect the chart to the rest of your application:
widget.subscribe('buyClick', ({ symbol }) => {
openOrderScreen({ side: 'BUY', symbol });
});
// Detach when you no longer need it.
widget.unsubscribe('buyClick', handler);| Event | Fired when | Payload |
|---|---|---|
| buyClick | The user taps the BUY button | { side: 'B', symbol } |
| sellClick | The user taps the SELL button | { side: 'S', symbol } |
| chartContextOrder | The user picks an order from the chart context menu and no dockOpen listener exists (with one, the order opens in the dock instead — section 8.2) | { side: 'B' | 'S', price, symbol } — price is the chart price the menu was opened at |
| backClick | The back arrow is tapped (mobile header) | — |
| dockOpen | FastChart opened the host dock (panels menu, order trigger, openDock() or a restored half dock) | { type, container, mode, placement, cover?, context?, restored? } — fill container (section 8.2) |
| dockClose | The dock closed — dispose your content | { type } |
| contentHeightChanged | A sub-panel was added or removed and heightMode is 'grow' | { height } — resize your container |
| dataLoadError | The main data reload failed, or the chart rejected every bar the datafeed returned. The chart is cleared rather than left showing another symbol's candles. | { symbol, error } |
| chartInitFailed | The widget could not start (datafeed init, symbol resolve or chart construction). A message is also shown. | { error } |
Typical flow: on buyClick or sellClick, your app opens its order screen for the active symbol (or, with a dockOpen listener, FastChart opens the dock for you — section 8.2). Combined with load_last_chart: true, the chart restores the user's latest symbol when they navigate back.
Alert events. chartContextAlert { price, symbol } fires when the user picks “Add Alert” from the chart context menu — open your alert-creation dialog with the price prefilled. Once alerts are on the chart (setAlerts, section 15.3): alertModified { alert, newPrice, oldPrice } fires when the user drags an alert line (call your edit API), alertRemoved { alert } on the pill's trash icon, alertEditRequested { alert } on double-click, and alertTriggered { alert } when the chart's local price check crosses the alert. Each alert object carries { id, price, meta } where meta is your own passthrough payload from setAlerts.
10. Theming
- Set the starting theme with the theme option; switch later with widget.changeTheme('Light') or changeTheme('Dark').
- Casing. Theme values are case-insensitive everywhere (theme: 'dark', changeTheme('Light') and changeTheme('DARK') all work); getTheme() always reports 'Light' or 'Dark'.
- The whole UI follows the theme — panels, dialogs, axes, minimap and the drawing toolbar.
- Use overrides for brand-specific colours. Because the SDK is a prebuilt bundle, overrides is the supported customisation path — do not edit fastchart.js by hand.
widget.applyOverrides({
'mainSeriesProperties.candleStyle.upColor': '#0EA371',
'mainSeriesProperties.candleStyle.downColor': '#E0483B',
'paneProperties.background': '#0B0E11',
});11. Mobile and WebView checklist
| Concern | What to do |
|---|---|
| Bundling the SDK | Ship the SDK folder in your app assets — Android src/main/assets/, iOS app bundle — and load it from the local WebView URL. |
| Asset base URL | Set baseUrl to the WebView-visible path of assets/, e.g. file:///android_asset/fastchart/assets/. |
| Android WebView setup | Enable JavaScript and DOM storage. Allow file access if loading from file://. |
| Restoring state | Pass load_last_chart: true so the last symbol returns after back-navigation. |
| Backgrounding | Nothing to do — missed bars are backfilled automatically when the app becomes visible. |
| Touch interaction | Touch drawing, long-press editing and the magnifier loupe are built in; the toolbar adapts to narrow screens. |
| Responsive layout | Leave layout: 'auto' to let the library detect the device, or pin it with { force: 'phone' }. |
| Teardown | Call widget.remove() when the screen is destroyed. |
Offline WebViews. A WebView with no network still works, but only if every asset is local: bundle assets/, and on the FULL tier bundle monaco/ and set monacoBaseUrl too — otherwise the IDE tries to reach a CDN.
12. Upgrading to a new SDK package
Because the SDK is a folder of static files, upgrading is a folder swap:
- 1. Read version.json in the new zip and record the version you are moving to.
- 2. Review RELEASE-NOTES.md inside the package for any breaking changes and upgrade notes.
- 3. Replace the whole folder — do not merge new files into the old one. Stale workers or a mismatched .wasm left behind from the previous version are a common source of subtle breakage.
- 4. Bust any caches: hard-reload the browser, or serve the SDK from a versioned path such as /vendor/fastchart-1.0.0/.
- 5. Verify the chart renders, live ticks arrive, and indicators compute — indicators exercise the worker and WASM path.
12.1 Upgrading from 0.3.0 or earlier to 1.0.0
- Request a re-issued signed licenseKey if you still hold an old FC-… key.
- Order entry is yours: the in-chart Quick Order dialog and the onQuickOrder, orderMode, defaultOrderQty and defaultLotSize options were removed (0.4.0). Subscribe to dockOpen and render your order screen (section 8.2), or keep handling buyClick / sellClick / chartContextOrder.
- FCScript follows Pine v6 (0.8.0): x = inside an if / for / while / switch / function body declares a new local — use := to change the outer variable; only var / varip values persist across bars; a name declared in a block is not visible after it. / is always real division (wrap in int() for truncation). Re-test every script you ship.
- If you serve restApiBase yourself, symbols containing / (for example NIFTY/BANK) now arrive percent-encoded (%2F) in the /historical, /orders and /events paths — decode the symbol segment.
- A failed symbol or interval reload now clears the chart and fires dataLoadError instead of leaving the previous candles on screen; datafeed calls time out after 30 seconds.
- Saved views, drawings and scripts survive the upgrade; the datafeed contract is unchanged.
Versioned paths make rollback trivial. Deploying to /vendor/fastchart-<version>/ and switching the <script> src lets you roll back by changing one line, and sidesteps browser caching entirely.
13. Licensing
- License keys are issued by Teligenz and passed via the licenseKey widget option. Keys are cryptographically signed (format FCL1.<claims>.<signature>); the chart verifies the signature, tier, expiry and domain lock itself, offline. Keys in the older FC-… format are no longer accepted — request a re-issued key.
- A key encodes the licensed tier, the permitted domain(s) and an expiry date. localhost, 127.0.0.1 and 0.0.0.0 always pass the domain lock. Pages loaded from file:// (app-bundled WebViews) have no hostname and need a wildcard-domain key.
- Without a valid key — absent, malformed, expired or locked to another domain — the chart never throws: it runs as the Community tier (Canvas2D rendering, TypeScript compute, no FCScript, Compare or Replay), draws a visible 'FastChart Community — unlicensed' badge, and logs to the console exactly why. Gated actions also show an on-screen notice.
- The chart warns ahead of expiry, and the License Details dialog shows tier, licensee and expiry. Renew before the date — keys are checked against the client clock and cannot be revoked remotely.
- Features above your licensed tier degrade to a logged no-op rather than throwing.
- LICENSE.txt in your package records the tier and version you received; the SDK is proprietary and licensed per agreement.
- Do not redistribute, publish or re-host the SDK outside the terms of your agreement.
- To change tier — for example core → full — request a new package and a matching key; the integration code does not change.
14. Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
| FastChart is not defined | The script tag failed, or your code ran before it. Confirm the src path returns 200, and that your code runs after the script tag. |
| Chart renders but indicators and scripts never compute | Workers or WASM are unreachable. Check the Network tab for 404s under assets/, and verify baseUrl in configureFastChartAssets. |
| Console error about the WASM module | .wasm is being served with the wrong MIME type. Serve it as application/wasm (section 3.3). |
| Blank chart, no errors | The container has zero height. Set an explicit height, or use a sized parent with autosize: true. |
| Live candle frozen after a symbol switch | Check your unsubscribeBars / subscribeBars sequence — the new subscription must start after the symbol change. |
| Old symbol shown after back-navigation (mobile) | Enable load_last_chart: true. |
| A licensed feature is missing | Verify licenseKey, that your tier includes the feature, that the domain matches, and that the key has not expired. |
| FCScript IDE opens blank or stalls (FULL tier) | Monaco was not found. Set monacoBaseUrl to the folder containing vs, and confirm monaco/vs/ is being served. |
| 'FastChart Community — unlicensed' badge on the chart | The licenseKey is missing, malformed, expired, an old FC-… key, or locked to another domain — the console message states which. file:// WebViews need a wildcard-domain key. |
| Order dialog no longer appears (after upgrading from 0.3.0) | Order entry moved to the host in 0.4.0. Subscribe to dockOpen and render your order screen (section 8.2). |
| Script that worked before now reports 'Undeclared identifier' or different values | FCScript follows Pine v6 scoping since 0.8.0 — use := to assign an outer variable inside a block, and declare accumulating collections with var (section 12.1). |
| Worked before an upgrade, broken after | Mixed old and new files. Delete the folder and re-extract the new package in full (section 12). |
| Toolbar or context-menu icons missing — 404s under assets/fc-icons/ | SDK packages before 0.2.0 resolve icons relative to the host page. Upgrade the package and set baseUrl in configureFastChartAssets — icons then resolve from it like workers and WASM. |
14.1 Information to include in a support request
- The contents of version.json from your SDK folder.
- Your tier (core, fcs or full) and the browser plus OS version.
- The full browser console output and the Network tab, filtered to failing requests.
- How the SDK is served — URL path, same-origin or CDN — and your configureFastChartAssets call.
Support: info@teligenz.in
15. Trading and runtime APIs
The widget exposes a substantially larger API surface than the everyday methods in section 8. This section documents the parts a trading application typically needs. Widget-level methods are called on the widget instance; chart-level methods on widget.activeChart().
15.1 Orders on the chart
Order markers render at their price on the chart and follow the symbol: FastChart shows only the orders whose symbol matches the chart's current instrument, so you can pass your full blotter.
| Method | Behaviour |
|---|---|
| widget.setOrders(orders) | Replace the full set of order markers. Pass an array of OrderMarker objects. |
| widget.addOrder(order) | Add a single order marker. |
| widget.modifyOrder(id, updates) | Update price, status, label and/or quantity of an existing marker. |
| widget.removeOrder(id) | Remove one marker by its id. |
| widget.getOrder(id) | Read back a marker by id (undefined if not present). |
OrderMarker fields: id (string, your unique id), symbol (string — markers are filtered to the chart's symbol), side ('B' | 'S'), price (number), timestamp (ms epoch), and optionally label, quantity, status, color, tooltip.
15.2 Position, price band and last price
| Method | Behaviour |
|---|---|
| widget.setPosition({ qty, avgPrice, symbol? }) | Show the open position line. Include symbol to scope it to an instrument — the marker auto-clears when the chart moves to a different symbol and reappears when the user returns. Omit symbol and it binds to the symbol current at call time. Pass null to clear. |
| widget.setDailyLimits({ upper, lower }) | Draw the day's circuit-limit band; null/undefined clears it. |
| widget.setPriceFormat({ minMove, precision }) | Override tick size / decimal precision for the active symbol. |
| widget.getLastPrice() | The last traded price the chart currently knows. |
15.3 Alerts
widget.setAlerts(alerts) renders your server's alert list on the chart (bell badges at the alert price) and keeps every pane of a multi-chart layout in sync. The chart is display-only: creating, modifying and triggering alerts stays in your backend.
15.4 News, earnings, dividends and custom events
| Method | Behaviour |
|---|---|
| widget.setEvents(events) | Replace all event markers in one call (mixed types). |
| widget.setNews(events) / setEarnings(events) / setDividends(events) | Replace only the markers of that type, leaving the others untouched. |
| widget.toggleMarkerVisibility(category, visible?) | Show/hide a marker category ('orders', 'news', 'earnings', 'dividends', …). Returns the new state. |
| widget.getMarkerVisibility() | Current visibility map for all marker categories. |
EventMarker fields: id, type, timestamp (ms epoch), label, and optionally description, color, icon, tooltip, url.
15.5 Indicators, programmatically
| Method | Behaviour |
|---|---|
| activeChart().createStudy(name, forceOverlay?, lock?, inputs?) | Add a built-in indicator by name. Accepts the display name or the short id, case-insensitive ('RSI', 'relative strength index', 'bb', …). Returns an entity id. |
| activeChart().getAllStudies() | List the active indicators with their entity ids. |
| activeChart().removeEntity(entityId) | Remove one indicator (also removes shapes by id). |
| activeChart().removeAllStudies() | Clear every indicator. |
Built-in indicator ids (82): ADLine, ADX, ALMA, Aroon, ATR, AveragePrice, AwesomeOscillator, BollingerBands, BollingerBandwidth, BollingerPercentB, CCI, ChaikinOscillator, ChandeKrollStop, ChopZone, CMF, CMO, ConnorsRSI, Coppock, CumulativeVolumeDelta, DEMA, DonchianChannels, DPO, ElderRay, EMA, EMACross, EMV, Envelope, FisherTransform, ForceIndex, GuppyMMA, HistoricalVolatility, HullMA, Ichimoku, KAMA, KeltnerChannels, KST, LinearRegressionSlope, LinReg, MACD, MACross, MADouble, MajorityRule, MassIndex, MATriple, MAwithEMACross, McGinleyDynamic, MedianPrice, MFI, Momentum, NVI, OBV, ParabolicSAR, PivotPoints, PPO, PriceChannel, PVI, PVO, ROC, RSI, RVI, SMA, SMIErgodic, SMMA, SqueezeMomentum, StandardError, StandardErrorBands, StdDev, Stochastic, StochasticRSI, Supertrend, TEMA, TRIX, TSI, TypicalPrice, UltimateOscillator, Volume, VWAP, VWMA, WilliamsR, WMA, ZigZag.
15.6 Shapes and drawings
| Method | Behaviour |
|---|---|
| activeChart().createShape(point, options) | Place a single-point drawing (e.g. a horizontal line) at { time, price }. |
| activeChart().createMultipointShape(points, options) | Place a multi-point drawing (trend line, rectangle, …). |
| activeChart().getAllShapes() | List active drawings with entity ids. |
| activeChart().removeEntity(id) / removeAllShapes() | Remove one / all drawings. |
15.7 Data, viewport and screenshots
| Method | Behaviour |
|---|---|
| activeChart().exportData(options?) | Export the loaded series for CSV/JSON handling in your app. Returns { schema, data } where each row is [time, open, high, low, close, volume]; time is milliseconds since epoch (same unit as the bars you supplied). |
| activeChart().getVisibleRange() / setVisibleRange({from, to}) | Read or move the visible time window (unix seconds). |
| widget.takeScreenshot() | Download a snapshot image (stamped with screenshotUsername). |
| widget.takeClientScreenshot() | Same snapshot as an HTMLCanvasElement, for your own upload/share flow. |
| widget.undo() / redo() / canUndo() / canRedo() | Programmatic access to the chart's undo history. |
15.8 Chart events (in addition to section 9)
The chart API exposes subscription objects: each returns an object with subscribe(null, handler) / unsubscribe(handler).
| Subscription | Fires when |
|---|---|
| activeChart().onDataLoaded() | A history load completes. |
| activeChart().onSymbolChanged() | The instrument changes. |
| activeChart().onIntervalChanged() | The interval changes. |
| activeChart().onVisibleRangeChanged() | The user scrolls or zooms. |
| activeChart().crossHairMoved() | The crosshair moves (params include time/price). |
| activeChart().onChartTypeChanged() | The series style changes (candles → line, …). |
15.9 Multi-chart and multi-timeframe layouts
Multi-chart (different symbols side by side) and multi-timeframe (one symbol at several intervals) are user-driven: the header's layout buttons switch layouts, per-pane symbol/interval state persists across reloads, and host-pushed orders, positions and alerts are automatically scoped to the matching pane (sections 15.1–15.3). There is currently no public API to switch layouts programmatically — widget.setLayout() is a compatibility stub — so treat layouts as an end-user feature. Both layout families are Enterprise-tier features.
16. Configuration reference
16.1 Feature flags (enabled_features / disabled_features)
Both options take an array of flag names. Everything below is ON by default; list a flag in disabled_features to turn it off. For example, disabled_features: ['header_buy_sell', 'left_toolbar'] hides the Buy/Sell header buttons and the drawing toolbar.
- Header toolbar: header_widget, header_symbol_search, header_resolutions, header_chart_type, header_settings, header_indicators, header_compare, header_undo_redo, header_screenshot, header_fullscreen_button, header_markers, header_buy_sell.
- Toolbars and panels: left_toolbar, control_bar, timeframes_toolbar, legend_widget, edit_buttons_in_legend, side_toolbar_in_fullscreen_mode.
- Context menus: context_menus, pane_context_menu, scales_context_menu, legend_context_menu, chart_crosshair_menu.
- Display and interaction: display_market_status, border_around_the_chart, main_series_scale_menu, star_some_intervals_by_default, chart_scroll, chart_zoom, countdown, caption_buttons_text_if_possible, adaptive_logo, go_to_date, high_density_bars, shift_visible_range_on_new_bar, right_bar_stays_on_scroll.
- Dialogs, templates and storage: property_pages, show_chart_property_page, study_dialog_search_control, show_object_tree, constraint_dialogs_movement, drawing_templates, study_templates, use_localstorage_for_settings, symbol_search_hot_key, datasource_copypaste, items_favoriting, compare_symbol, volume_force_overlay, create_volume_indicator_by_default.
Buy/Sell buttons. The floating Buy/Sell price-axis markers are separate from the header buttons: toggle them at runtime with widget.toggleMarkerVisibility('orders', false).
16.2 Overrides reference
applyOverrides / the overrides option accept the following keys (values are colors unless noted):
- Candles: mainSeriesProperties.candleStyle.upColor, .downColor, .wickUpColor, .wickDownColor, .borderUpColor, .borderDownColor.
- Line / area / bars / baseline: mainSeriesProperties.lineStyle.color, .linewidth (number); mainSeriesProperties.areaStyle.color1, .color2, .linecolor, .linewidth (number), .transparency (0–100); mainSeriesProperties.barStyle.upColor, .downColor; mainSeriesProperties.baselineStyle.topLineColor, .bottomLineColor.
- Pane: paneProperties.background, .backgroundType ('solid' | 'gradient'), .backgroundGradientStartColor, .backgroundGradientEndColor, .vertGridProperties.color, .horzGridProperties.color, .crossHairProperties.color, .crossHairProperties.width (number), .separatorColor.
- Legend: paneProperties.legendProperties.showSeriesTitle, .showStudyTitles, .showStudyValues (booleans).
- Scales and misc: scalesProperties.textColor, .lineColor, .fontSize (number); mainSeriesProperties.showPriceLine (boolean); volumePaneSize ('large' | 'medium' | 'small' | 'tiny').
17. Datafeed reference
17.1 Error handling
resolveSymbol and getBars each take an error callback after the success callback. Call it with a reason string when your backend fails — the chart stops the loading state and surfaces the failure instead of waiting forever:
| Method (full signature) | On failure |
|---|---|
| resolveSymbol(name, onResolve, onError) | Call onError('reason'). The symbol load is abandoned. |
| getBars(symbolInfo, resolution, periodParams, onResult, onError) | Call onError('reason'). The pending history request rejects; pagination stops for that request. |
HTTP errors. For a backend 500, catch it in your datafeed and invoke the error callback — do not call onResult with an empty array, which the chart reads as “no data exists” and caches as end-of-history.
periodParams fields. from and to (unix seconds) bound the requested window; countBack is the minimum number of bars the chart needs (honour it when your storage is sparse — return at least countBack bars ending at to); firstDataRequest is true on the first history request after a symbol or interval change, false for pagination requests.
17.2 resolveSymbol — full field reference
- Required fields: name, full_name, description, type, session (e.g. '0915-1530' or '24x7'), timezone (IANA name), exchange, listed_exchange, format ('price' | 'volume'), pricescale (e.g. 100 = 2 decimals), minmov (tick size in pricescale units — minTick = minmov / pricescale), supported_resolutions, has_intraday, has_daily, has_weekly_and_monthly.
- Optional fields: ticker, has_seconds, seconds_multipliers, intraday_multipliers, daily_multipliers, has_ticks, visible_plots_set, volume_precision, data_status, expired, expiration_date, sector, industry, currency_code, logo_urls.
- Per-symbol resolutions. supported_resolutions is per-symbol: the interval picker offers only what the resolved symbol supports.
17.3 Symbol search — which hook wins
The search popup (toolbar, Compare dialog, multi-chart pane search) is fed exclusively by the onSearchSymbols widget option; if it is absent but restApiBase is set, the widget calls GET {restApiBase}/search?q=. The datafeed's searchSymbols method exists for datafeed-convention compatibility but is not consulted by the UI — implement onSearchSymbols.
17.4 Failures, timeouts and encoding
- A datafeed call that never answers times out after 30 seconds and returns an empty result instead of waiting forever.
- A failed symbol or interval reload clears the chart, shows an error message and fires dataLoadError { symbol, error }; use onLoadError to veto the toast. If the datafeed returns rows with non-numeric time or price, they are ignored; if every row is rejected the chart reports the same error.
- When you use restApiBase, symbols containing / are percent-encoded (%2F) in the /historical, /orders and /events paths — decode the symbol segment on your server.
18. TypeScript declarations
The package ships its type declarations — no need to request them separately:
| Item | Purpose |
|---|---|
| types/ | The full generated .d.ts tree for the SDK's public API. |
| fastchart.d.ts | Global declaration for script-tag consumers: makes the FastChart global (and window.FastChart) fully typed. |
Add the SDK folder's fastchart.d.ts to your tsconfig “include” (or reference it from a declaration file). The section 5.1 workaround — declare const FastChart: any — is no longer needed.
A. Appendix A — Integration checklist
| # | Step |
|---|---|
| 1 | Extracted the SDK zip with its folder structure intact |
| 2 | Copied the folder into a static-served location in the app |
| 3 | Server returns application/wasm for .wasm files |
| 4 | assets/ is publicly reachable — no 404s, no auth wall |
| 5 | Added the <script src=".../fastchart.js"> tag |
| 6 | Called configureFastChartAssets({ baseUrl }) before the first chart |
| 7 | FULL tier only: set monacoBaseUrl and served monaco/ |
| 8 | Implemented the datafeed — history, live ticks, symbol resolution |
| 9 | Passed a valid licenseKey |
| 10 | Container has a real height; chart renders |
| 11 | Indicators compute — confirms the worker and WASM path |
| 12 | widget.remove() is called on teardown (or detach() when pooling the widget) |
| 13 | Order entry wired to dockOpen (or buyClick / sellClick / chartContextOrder) |
| 14 | FCScript scripts reviewed against Pine v6 rules if you ship any |
FastChart SDK Integration Guide — © Teligenz Tech Solutions. Proprietary and licensed per agreement. Support: info@teligenz.in
Need a hand with an integration? Write to info@teligenz.in.