Skip to main content

SciFinanceChart: the Trading Chart Component

The chart itself: a candlestick chart of one symbol, with a pane for each indicator that needs one, live data, and zoom and pan. It comes in two forms, with the same config and the same API:

Plain TypeScriptReact
The componentSciFinanceChartPanel<SciFinanceChartView>, from scichart-scitrader-react
Create itawait SciFinanceChartPanel.create(element, config)<SciFinanceChartView config={config} />
Its APIWhat create resolves withonInit, or ref
Remove itfinanceChartPanel.cleanup()Unmount it

Both create:

  • the panes: the price pane, and a pane for each study that needs one, with dividers to resize them and a control bar on each;
  • a data feed for the symbol, from the exchange you name, which loads older candles as the user pans back and adds live ones;
  • the chart's interaction: zoom, pan, axis drag, crosshair and legend, by mouse or by touch.

The config is an ISciFinanceChartPanelConfig, and the API an ISciFinanceChartPanelApi, called financeChartPanel in these docs. Its financeApi is the chart, a SciFinanceChart, and its paneGroupApi the panes.

TypeScript Example: Creating a Chart​

SciFinanceChartPanel.create builds the chart inside an element. The element needs a size: the chart fills it, and follows it when it resizes.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
OHLCStudy,
SciFinanceChartPanel,
VolumeStudy,
} from "scichart-scitrader";

// 1. Register a data source, once, at app startup.
// idbPriceStore caches candles in IndexedDB, so a reload only fetches what is new.
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

// 2. Create the chart inside an element that has a size, e.g. <div id="chart" style="height: 600px">
async function createChart(elementId: string) {
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById(elementId), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD", // Coinbase's symbol format
interval: CandleInterval.ONE_HOUR, // Coinbase offers 1m, 5m, 15m, 1h, 6h and 1d candles
// OHLCStudy draws the candles; VolumeStudy adds volume columns along the bottom of the price pane
studies: [new OHLCStudy(), new VolumeStudy()],
});

// 3. When the element goes away, free the chart's resources with financeChartPanel.cleanup()
return financeChartPanel;
}

createChart("chart");

React Example: Creating a Chart​

<SciFinanceChartView> takes the same config, and fills its parent, so give the parent a height. It is in the React package, scichart-scitrader-react, along with React versions of the other UI components. It needs the core package and its peer dependencies too:

npm install scichart-scitrader-react scichart-scitrader scichart scichart-financial-tools rxjs react react-dom

See Installation for the versions, the stylesheet and serving SciChart's WebAssembly.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
ADXStudy,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
IStudy,
MACDStudy,
OHLCStudy,
RSIStudy,
VolumeStudy,
} from "scichart-scitrader";
import { SciFinanceChartView } from "scichart-scitrader-react";

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

export function TradingChart() {
// The same ISciFinanceChartPanelApi that SciFinanceChartPanel.create returns
const chartRef = React.useRef<ISciFinanceChartPanelApi>(null);
// The studies on the chart, kept in state so the buttons re-render when they change
const [studies, setStudies] = React.useState<readonly IStudy[]>([]);
const [ready, setReady] = React.useState(false);

// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "ETH-USD", // Coinbase's symbol format
interval: CandleInterval.ONE_DAY,
period: "1Y",
studies: [new OHLCStudy(), new VolumeStudy(), new RSIStudy()],
}),
[]
);

// financeApi throws until the chart has initialised, so only use it from onInit
const onInit = (api: ISciFinanceChartPanelApi) => {
const chart = api.financeApi;
setReady(true);
setStudies(chart.studies); // studies returns a new array each time, so React sees the change
// Also fires when the user closes a study's pane from the chart.
// The chart is deleted when this component unmounts, so there's no need to unsubscribe.
chart.studiesChanged.subscribe(() => setStudies(chart.studies));
};

// Detach the study of this type if the chart has one, otherwise attach a new one
const toggleStudy = (StudyType: new () => IStudy) => {
const chart = chartRef.current;
if (!chart?.isInitialized) return;
const existing = chart.financeApi.studies.find((study) => study instanceof StudyType);
if (existing) {
chart.financeApi.detachStudy(existing);
} else {
chart.financeApi.attachStudy(new StudyType());
}
};

const hasMacd = studies.some((study) => study instanceof MACDStudy);
const hasAdx = studies.some((study) => study instanceof ADXStudy);

// Fills its parent, so give the parent a height
return (
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
<div style={toolbarStyle}>
<button style={buttonStyle(hasMacd, ready)} disabled={!ready} onClick={() => toggleStudy(MACDStudy)}>
{hasMacd ? "Remove MACD" : "Add MACD"}
</button>
<button style={buttonStyle(hasAdx, ready)} disabled={!ready} onClick={() => toggleStudy(ADXStudy)}>
{hasAdx ? "Remove ADX" : "Add ADX"}
</button>
</div>
<div style={{ flex: 1, minHeight: 0 }}>
<SciFinanceChartView ref={chartRef} config={config} onInit={onInit} />
</div>
</div>
);
}

// The toolbar uses SciTrader's UI colours: its --st-ui-* CSS variables, with the stylesheet's defaults
const toolbarStyle: React.CSSProperties = {
display: "flex",
gap: 8,
padding: 8,
background: "var(--st-ui-background, #2b2839)",
borderBottom: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
};

const buttonStyle = (active: boolean, enabled: boolean): React.CSSProperties => ({
padding: "6px 14px",
fontSize: 14,
fontFamily: "var(--st-font-family, sans-serif)",
color: "var(--st-ui-text, #ffffff)",
background: active ? "var(--st-ui-accent, #7464ff)" : "var(--st-ui-surface, #373447)",
border: "1px solid var(--st-ui-divider, rgba(255,255,255,0.1))",
borderRadius: 4,
cursor: enabled ? "pointer" : "default",
opacity: enabled ? 1 : 0.5,
});
  • Wait for onInit. ref.current is set as soon as the view mounts, but its financeApi throws until the chart has initialised. Use onInit, or check isInitialized, first.
  • config is read once. Changing it doesn't rebuild the chart: change a live chart through financeApi, or remount it with a new key to start again.
  • paneControls is live. Unlike config, a change to the paneControls prop applies to the running chart.
  • Unmounting cleans up. The view calls cleanup() itself.

Pane Sizes, and Pane State in Code​

Set each pane's size when you create the chart with paneSizing, by pane id. Afterwards, paneGroupApi reads and sets the same state the pane control bars do: size, hidden, maximised and closed. financeApi sets each pane's Y-axis autorange.

const RSI_PANE = new PaneId("rsi");

const financeChartPanel = await SciFinanceChartPanel.create(element, {
// …
studies: [new OHLCStudy(), new VolumeStudy(), new RSIStudy({ paneId: RSI_PANE })],
paneSizing: {
[PaneId.DEFAULT.value]: { grow: 3 }, // the price pane takes 3 shares of the height
[RSI_PANE.value]: { size: 110 }, // the RSI pane is 110 px high
},
});

financeChartPanel.paneGroupApi.setExpanded(RSI_PANE.value); // maximise the RSI pane
financeChartPanel.financeApi.getYAxisAutoRangeController(RSI_PANE).isYAxisAutoRangeEnabled = false;

Pane Sizes and Pane State covers each of them, with live examples.

Mobile and Desktop Modes​

The chart works by mouse and by touch, but some parts have a touch layout, which your app turns on: the chart doesn't detect touch screens. Decide from your app's own breakpoint, and pass it in:

const touch = matchMedia("(pointer: coarse)").matches; // or your app's breakpoint

const financeChartPanel = await SciFinanceChartPanel.create(element, { /* … */ paneControls: { touch } });
const drawing = DrawingToolsController.attach(financeChartPanel.financeApi, { touch, selectFinishedDrawing: !touch });

Mobile and Desktop Modes lists what changes, and how the SciTrader app decides.

Pages in This Section​

PageWhat it covers
Pane Sizes and Pane StatePane sizes; Y-axis autorange, maximising, hiding and closing panes in code
Mobile and Desktop ModesTouch and mouse layouts, and how your app chooses
Layout, Panes and PaneGroupSub-chart and multi-chart modes, pane control bars, loading states, and the layout underneath
Finance Chart APIISciFinanceChartPanelApi, and the SciFinanceChart class
Chart Config ObjectEvery ISciFinanceChartPanelConfig option