JavaScript Candlestick Chart

Demonstrates how to create a JavaScript Candlestick Chart using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

binanceRestClient.ts

ExampleDataProvider.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1// SCICHART EXAMPLE
2import {
3    CursorModifier,
4    CursorTooltipSvgAnnotation,
5    DateTimeNumericAxis,
6    DiscontinuousDateAxis,
7    EAutoRange,
8    EDataSeriesType,
9    EFillPaletteMode,
10    ENumericFormat,
11    ESeriesType,
12    FastCandlestickRenderableSeries,
13    FastColumnRenderableSeries,
14    FastLineRenderableSeries,
15    FastMountainRenderableSeries,
16    FastOhlcRenderableSeries,
17    GradientParams,
18    IFillPaletteProvider,
19    IPointMetadata,
20    IRenderableSeries,
21    MouseWheelZoomModifier,
22    NumberRange,
23    NumericAxis,
24    OhlcDataSeries,
25    OhlcSeriesInfo,
26    parseColorToUIntArgb,
27    Point,
28    SciChartOverview,
29    SciChartSurface,
30    SeriesInfo,
31    XyDataSeries,
32    XyMovingAverageFilter,
33    ZoomExtentsModifier,
34    ZoomPanModifier,
35} from "scichart";
36import { appTheme } from "../../../theme";
37import { simpleBinanceRestClient } from "../../../ExampleData/binanceRestClient";
38import { ExampleDataProvider, TPriceBar } from "../../../ExampleData/ExampleDataProvider";
39import {
40    DEFAULT_LABEL_THRESHOLDS,
41    ETradeChartLabelFormat,
42} from "scichart/Charting/Visuals/Axis/LabelProvider/SmartDateLabelProvider";
43
44const Y_AXIS_VOLUME_ID = "Y_AXIS_VOLUME_ID";
45
46export const drawExample = (dataSource: string) => async (rootElement: string | HTMLDivElement) => {
47    // Create a SciChartSurface
48    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
49        theme: appTheme.SciChartJsTheme,
50    });
51
52    // We have a hybrid DiscontinuousDateAxis which 'magically' solves problems of different # of points in stock market datasetd with gaps
53    const xAxis = new DiscontinuousDateAxis(wasmContext, {
54        // autoRange.never as we're setting visibleRange explicitly below. If you dont do this, leave this flag default
55        autoRange: EAutoRange.Never,
56        cursorLabelFormat: ENumericFormat.Date_HHMM,
57        // Increase this threshold as the default value is right on our default range
58        labelThresholds: { [ETradeChartLabelFormat.Minutes]: 60 * 60 * 24 * 10 },
59    });
60    sciChartSurface.xAxes.add(xAxis);
61
62    // Create a NumericAxis on the YAxis with 2 Decimal Places
63    sciChartSurface.yAxes.add(
64        new NumericAxis(wasmContext, {
65            growBy: new NumberRange(0.1, 0.1),
66            labelFormat: ENumericFormat.Decimal,
67            labelPrecision: 2,
68            labelPrefix: "$",
69            autoRange: EAutoRange.Always,
70        })
71    );
72
73    // Create a secondary YAxis to host volume data on its own scale
74    sciChartSurface.yAxes.add(
75        new NumericAxis(wasmContext, {
76            id: Y_AXIS_VOLUME_ID,
77            growBy: new NumberRange(0, 4),
78            isVisible: false,
79            autoRange: EAutoRange.Always,
80        })
81    );
82
83    const xValues: number[] = [];
84    const openValues: number[] = [];
85    const highValues: number[] = [];
86    const lowValues: number[] = [];
87    const closeValues: number[] = [];
88    const volumeValues: number[] = [];
89
90    // Fetch data from now to 300 1hr candles ago
91    const endDate = new Date(Date.now());
92    const startDate = new Date();
93    startDate.setHours(endDate.getHours() - 300);
94    let priceBars: TPriceBar[];
95    if (dataSource !== "Random") {
96        priceBars = await simpleBinanceRestClient.getCandles("BTCUSDT", "1h", startDate, endDate, 500, dataSource);
97    } else {
98        priceBars = ExampleDataProvider.getRandomCandles(300, 60000, startDate, 60 * 60, true);
99    }
100
101    // Maps PriceBar { date, open, high, low, close, volume } to structure-of-arrays expected by scichart
102    priceBars.forEach((priceBar: any) => {
103        xValues.push(priceBar.date);
104        openValues.push(priceBar.open);
105        highValues.push(priceBar.high);
106        lowValues.push(priceBar.low);
107        closeValues.push(priceBar.close);
108        volumeValues.push(priceBar.volume);
109    });
110    // Zoom to the latest 100 candles
111    const lastBar = priceBars[priceBars.length - 1];
112    const firstVisiblebar = priceBars[priceBars.length - 100];
113    xAxis.visibleRange = new NumberRange(firstVisiblebar.date, lastBar.date);
114
115    // Create and add the Candlestick series
116    // The Candlestick Series requires a special dataseries type called OhlcDataSeries with o,h,l,c and date values
117    const candleDataSeries = new OhlcDataSeries(wasmContext, {
118        xValues,
119        openValues,
120        highValues,
121        lowValues,
122        closeValues,
123        dataSeriesName: dataSource === "Random" ? "Random" : "BTC/USDT",
124    });
125    const candlestickSeries = new FastCandlestickRenderableSeries(wasmContext, {
126        dataSeries: candleDataSeries,
127        stroke: appTheme.ForegroundColor, // used by cursorModifier below
128        strokeThickness: 1,
129        brushUp: appTheme.VividGreen + "77",
130        brushDown: appTheme.MutedRed + "77",
131        strokeUp: appTheme.VividGreen,
132        strokeDown: appTheme.MutedRed,
133    });
134    sciChartSurface.renderableSeries.add(candlestickSeries);
135
136    // Add an Ohlcseries. this will be invisible to begin with
137    const ohlcSeries = new FastOhlcRenderableSeries(wasmContext, {
138        dataSeries: candleDataSeries,
139        stroke: appTheme.ForegroundColor, // used by cursorModifier below
140        strokeThickness: 1,
141        dataPointWidth: 0.9,
142        strokeUp: appTheme.VividGreen,
143        strokeDown: appTheme.MutedRed,
144        isVisible: false,
145    });
146    sciChartSurface.renderableSeries.add(ohlcSeries);
147
148    //Add some moving averages using SciChart's filters/transforms API
149    // when candleDataSeries updates, XyMovingAverageFilter automatically recomputes
150    sciChartSurface.renderableSeries.add(
151        new FastLineRenderableSeries(wasmContext, {
152            dataSeries: new XyMovingAverageFilter(candleDataSeries, {
153                dataSeriesName: "Moving Average (20)",
154                length: 20,
155            }),
156            stroke: appTheme.VividSkyBlue,
157        })
158    );
159
160    sciChartSurface.renderableSeries.add(
161        new FastLineRenderableSeries(wasmContext, {
162            dataSeries: new XyMovingAverageFilter(candleDataSeries, {
163                dataSeriesName: "Moving Average (50)",
164                length: 50,
165            }),
166            stroke: appTheme.VividPink,
167        })
168    );
169
170    // Add volume data onto the chart
171    sciChartSurface.renderableSeries.add(
172        new FastColumnRenderableSeries(wasmContext, {
173            dataSeries: new XyDataSeries(wasmContext, { xValues, yValues: volumeValues, dataSeriesName: "Volume" }),
174            strokeThickness: 0,
175            // This is how we get volume to scale - on a hidden YAxis
176            yAxisId: Y_AXIS_VOLUME_ID,
177            // This is how we colour volume bars red or green
178            paletteProvider: new VolumePaletteProvider(
179                candleDataSeries,
180                appTheme.VividGreen + "77",
181                appTheme.MutedRed + "77"
182            ),
183        })
184    );
185
186    // Optional: Add some interactivity modifiers
187    sciChartSurface.chartModifiers.add(
188        new ZoomExtentsModifier(),
189        new ZoomPanModifier({ enableZoom: true }),
190        new MouseWheelZoomModifier(),
191        new CursorModifier({
192            crosshairStroke: appTheme.VividOrange,
193            axisLabelFill: appTheme.VividOrange,
194            tooltipLegendTemplate: getTooltipLegendTemplate,
195        })
196    );
197
198    // Add Overview chart. This will automatically bind to the parent surface
199    // displaying its series. Zooming the chart will zoom the overview and vice versa
200
201    //Exporting at the bottom by an object-
202    // const overview = await SciChartOverview.create(sciChartSurface, divOverviewId, {
203    //     theme: appTheme.SciChartJsTheme,
204    //     transformRenderableSeries: getOverviewSeries,
205    // });
206
207    return { sciChartSurface, candlestickSeries, ohlcSeries };
208};
209
210class VolumePaletteProvider implements IFillPaletteProvider {
211    fillPaletteMode: EFillPaletteMode = EFillPaletteMode.SOLID;
212    private ohlcDataSeries: OhlcDataSeries;
213    private upColorArgb: number;
214    private downColorArgb: number;
215
216    constructor(masterData: OhlcDataSeries, upColor: string, downColor: string) {
217        this.upColorArgb = parseColorToUIntArgb(upColor);
218        this.downColorArgb = parseColorToUIntArgb(downColor);
219        this.ohlcDataSeries = masterData;
220    }
221    onAttached(parentSeries: IRenderableSeries): void {}
222    onDetached(): void {}
223
224    // Return up or down color for the volume bars depending on Ohlc data
225    overrideFillArgb(
226        xValue: number,
227        yValue: number,
228        index: number,
229        opacity?: number,
230        metadata?: IPointMetadata
231    ): number {
232        const isUpCandle =
233            this.ohlcDataSeries.getNativeOpenValues().get(index) >=
234            this.ohlcDataSeries.getNativeCloseValues().get(index);
235        return isUpCandle ? this.upColorArgb : this.downColorArgb;
236    }
237
238    // Override stroke as well, even though strokethickness is 0, because stroke is used if column thickness goes to 0.
239    overrideStrokeArgb(
240        xValue: number,
241        yValue: number,
242        index: number,
243        opacity?: number,
244        metadata?: IPointMetadata
245    ): number {
246        return this.overrideFillArgb(xValue, yValue, index, opacity, metadata);
247    }
248}
249
250// Override the standard tooltip displayed by CursorModifier
251const getTooltipLegendTemplate = (seriesInfos: SeriesInfo[], svgAnnotation: CursorTooltipSvgAnnotation) => {
252    let outputSvgString = "";
253
254    // Foreach series there will be a seriesInfo supplied by SciChart. This contains info about the series under the house
255    seriesInfos.forEach((seriesInfo, index) => {
256        const y = 20 + index * 20;
257        const textColor = seriesInfo.stroke;
258        let legendText = seriesInfo.formattedYValue;
259        if (seriesInfo.dataSeriesType === EDataSeriesType.Ohlc) {
260            const o = seriesInfo as OhlcSeriesInfo;
261            legendText = `Open=${o.formattedOpenValue} High=${o.formattedHighValue} Low=${o.formattedLowValue} Close=${o.formattedCloseValue}`;
262        }
263        outputSvgString += `<text x="8" y="${y}" font-size="13" font-family="Verdana" fill="${textColor}">
264            ${seriesInfo.seriesName}: ${legendText}
265        </text>`;
266    });
267
268    return `<svg width="100%" height="100%">
269                ${outputSvgString}
270            </svg>`;
271};
272
273// Override the Renderableseries to display on the scichart overview
274const getOverviewSeries = (defaultSeries: IRenderableSeries) => {
275    if (defaultSeries.type === ESeriesType.CandlestickSeries) {
276        // Swap the default candlestick series on the overview chart for a mountain series. Same data
277        return new FastMountainRenderableSeries(defaultSeries.parentSurface.webAssemblyContext2D, {
278            dataSeries: defaultSeries.dataSeries,
279            fillLinearGradient: new GradientParams(new Point(0, 0), new Point(0, 1), [
280                { color: appTheme.VividSkyBlue + "77", offset: 0 },
281                { color: "Transparent", offset: 1 },
282            ]),
283            stroke: appTheme.VividSkyBlue,
284        });
285    }
286    // hide all other series
287    return undefined;
288};
289
290export const overviewOptions = {
291    theme: appTheme.SciChartJsTheme,
292    transformRenderableSeries: getOverviewSeries,
293};
294

Candlestick Chart Example using JavaScript

Overview

This example demonstrates a high-performance candlestick chart built with SciChart.js using JavaScript. It visualizes financial data using candlestick and OHLC series, complemented by moving averages and volume bars to provide a comprehensive view of market trends.

Technical Implementation

The chart is initialized by creating a SciChartSurface with WebAssembly rendering for optimal performance, following the guidelines from the Performance Tips & Tricks documentation. It sets up a DateTimeNumericAxis for time-based data and multiple NumericAxis for price and volume, with the latter serving as a secondary axis for additional data visualization. Data is fetched and mapped directly into the appropriate series types without using additional builder APIs, ensuring full control over the chart’s configuration.

Features and Capabilities

The example integrates both candlestick and OHLC series, as detailed in the OHLC Series Type documentation, allowing users to toggle between the two views. It further applies moving average filters using the XyMovingAverageFilter to smooth data trends, and implements a custom IFillPaletteProvider to dynamically color volume bars based on price movements, as described in the PaletteProvider API documentation. Additionally, interactive modifiers such as zooming, panning, and custom SVG tooltips enhance user engagement, with tooltip customization techniques available in this guide.

Integration and Best Practices

By using JavaScript, this implementation avoids reliance on framework-specific constructs, offering a lean and direct approach to building high-performance financial charts. Best practices for setting up axes, integrating multiple series, and enabling smooth interactivity are followed rigorously, as highlighted in the interactive zooming and panning documentation. This example serves as a solid foundation for developers looking to leverage SciChart.js in JavaScript environments without additional abstraction layers.

javascript Chart Examples & Demos

See Also: Financial Charts (9 Demos)

JavaScript OHLC Chart | Javascript Charts | SciChart.js Demo

JavaScript OHLC Chart

Easily create JavaScript OHLC Chart or Stock Chart using feature-rich SciChart.js chart library. Supports custom colors. Get your free trial now.

JavaScript Realtime Ticking Stock Chart | SciChart.js

JavaScript Realtime Ticking Stock Charts

Create a JavaScript Realtime Ticking Candlestick / Stock Chart with live ticking and updating, using the high performance SciChart.js chart library. Get free demo now.

NEW!
JavaScript Orderbook Heatmap | Javascript Charts | SciChart.js

JavaScript Orderbook Heatmap

Create a Javascript heatmap chart showing historical orderbook levels using the high performance SciChart.js chart library. Get free demo now.

JavaScript Multi-Pane Stock Chart using Subcharts | View JavaScript Charts

JavaScript Multi-Pane Stock Charts using Subcharts

Create a JavaScript Multi-Pane Candlestick / Stock Chart with indicator panels, synchronized zooming, panning and cursors. Get your free trial of SciChart.js now.

Tenor Curves Demo | Javascript Charts | SciChart.js Demo

Tenor Curves Demo

Demonstrating the capability of SciChart.js to create a composite 2D &amp; 3D Chart application. An example like this could be used to visualize Tenor curves in a financial setting, or other 2D/3D data combined on a single screen.

JavaScript Multi-Pane Stock Chart | View JavaScript Charts

JavaScript Multi-Pane Stock Charts using Sync Multi-Chart

Create a JavaScript Multi-Pane Candlestick / Stock Chart with indicator panels, synchronized zooming, panning and cursors. Get your free trial of SciChart.js now.

JavaScript Market Depth Chart | Javascript Charts | SciChart.js

JavaScript Market Depth Chart

Create a JavaScript Depth Chart, using the high performance SciChart.js chart library. Get free demo now.

JavaScript Chart Hoverable Buy Sell Marker Annotations

JavaScript Chart Hoverable Buy Sell Marker Annotations

Demonstrates how to place Buy/Sell arrow markers on a JavaScript Stock Chart using SciChart.js - Annotations API

JavaScript User Annotated Stock Chart | SciChart.js Demo

JavaScript User Annotated Stock Chart

This demo shows you how to create a <strong>{frameworkName} User Annotated Stock Chart</strong> using SciChart.js. Custom modifiers allow you to add lines and markers, then use the built in serialisation functions to save and reload the chart, including the data and all your custom annotations.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.