JavaScript Multi-Pane Stock Charts using Sync Multi-Chart

Using the default multi-chart sync APIs, create a multi-pane stock chart example with indicator panels. Zooming, panning, cursors are synchronised between the charts. This is a simpler way to create charts than subcharts, but will have a performance hit on some browsers.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

ExampleDataProvider.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    SciChartVerticalGroup,
3    DiscontinuousDateAxis,
4    EAxisAlignment,
5    SciChartSurface,
6    EAutoRange,
7    NumberRange,
8    NumericAxis,
9    OhlcDataSeries,
10    FastCandlestickRenderableSeries,
11    XyDataSeries,
12    calcAverageForArray,
13    FastLineRenderableSeries,
14    ZoomPanModifier,
15    ZoomExtentsModifier,
16    MouseWheelZoomModifier,
17    RolloverModifier,
18    FastBandRenderableSeries,
19    XyyDataSeries,
20    FastColumnRenderableSeries,
21    EXyDirection,
22    EFillPaletteMode,
23    EStrokePaletteMode,
24    IFillPaletteProvider,
25    IStrokePaletteProvider,
26    IRenderableSeries,
27    parseColorToUIntArgb,
28    ENumericFormat,
29    SmartDateLabelProvider,
30    XyMovingAverageFilter,
31    EDataSeriesField,
32    ELabelAlignment,
33    SeriesInfo,
34    EDataSeriesType,
35    OhlcSeriesInfo,
36    RolloverLegendSvgAnnotation,
37    SciChartOverview,
38    ESeriesType,
39    FastMountainRenderableSeries,
40    GradientParams,
41    Point,
42    TextAnnotation,
43    ECoordinateMode,
44    EHorizontalAnchorPoint,
45    EVerticalAnchorPoint,
46    EAnnotationLayer,
47} from "scichart";
48import { fetchMultiPaneData } from "../../../ExampleData/ExampleDataProvider";
49import { appTheme } from "../../../theme";
50
51const getTradingData = async (startPoints?: number, maxPoints?: number) => {
52    const { dateValues, openValues, highValues, lowValues, closeValues, volumeValues } = await fetchMultiPaneData();
53
54    if (maxPoints !== undefined) {
55        return {
56            dateValues: dateValues.slice(startPoints, startPoints + maxPoints),
57            openValues: openValues.slice(startPoints, startPoints + maxPoints),
58            highValues: highValues.slice(startPoints, startPoints + maxPoints),
59            lowValues: lowValues.slice(startPoints, startPoints + maxPoints),
60            closeValues: closeValues.slice(startPoints, startPoints + maxPoints),
61            volumeValues: volumeValues.slice(startPoints, startPoints + maxPoints),
62        };
63    }
64
65    return { dateValues, openValues, highValues, lowValues, closeValues, volumeValues };
66};
67
68// Override the standard legend displayed by RolloverModifier
69const getTooltipLegendTemplate = (seriesInfos: SeriesInfo[], svgAnnotation: RolloverLegendSvgAnnotation) => {
70    let outputSvgString = "";
71
72    // Foreach series there will be a seriesInfo supplied by SciChart. This contains info about the series under the house
73    seriesInfos.forEach((seriesInfo, index) => {
74        const y = 20 + index * 20;
75        const textColor = seriesInfo.stroke;
76        let legendText = seriesInfo.formattedYValue;
77        if (seriesInfo.dataSeriesType === EDataSeriesType.Ohlc) {
78            const o = seriesInfo as OhlcSeriesInfo;
79            legendText = `Open=${o.formattedOpenValue} High=${o.formattedHighValue} Low=${o.formattedLowValue} Close=${o.formattedCloseValue}`;
80        }
81        outputSvgString += `<text x="8" y="${y}" font-size="13" font-family="Verdana" fill="${textColor}">
82            ${seriesInfo.seriesName}: ${legendText}
83        </text>`;
84    });
85
86    return `<svg width="100%" height="100%">
87                ${outputSvgString}
88            </svg>`;
89};
90
91// Override the Renderableseries to display on the scichart overview
92const getOverviewSeries = (defaultSeries: IRenderableSeries) => {
93    if (defaultSeries.type === ESeriesType.CandlestickSeries) {
94        // Swap the default candlestick series on the overview chart for a mountain series. Same data
95        return new FastMountainRenderableSeries(defaultSeries.parentSurface.webAssemblyContext2D, {
96            dataSeries: defaultSeries.dataSeries,
97            fillLinearGradient: new GradientParams(new Point(0, 0), new Point(0, 1), [
98                { color: appTheme.VividSkyBlue + "77", offset: 0 },
99                { color: "Transparent", offset: 1 },
100            ]),
101            stroke: appTheme.VividSkyBlue,
102        });
103    }
104    // hide all other series
105    return undefined;
106};
107
108export const getChartsInitializationAPI = () => {
109    // We can group together charts using VerticalChartGroup type
110    const verticalGroup = new SciChartVerticalGroup();
111
112    const dataPromise = getTradingData();
113
114    let chart1XAxis: DiscontinuousDateAxis;
115    let chart2XAxis: DiscontinuousDateAxis;
116    let chart3XAxis: DiscontinuousDateAxis;
117    let priceChartSurface: SciChartSurface;
118    let macdChartSurface: SciChartSurface;
119    let rsiChartSurface: SciChartSurface;
120    const axisAlignment = EAxisAlignment.Right;
121
122    const upCol = appTheme.VividGreen;
123    const downCol = appTheme.MutedRed;
124    const opacity = "AA";
125
126    // CHART 1
127    const drawPriceChart = async (rootElement: string | HTMLDivElement) => {
128        const [chart, data] = await Promise.all([
129            SciChartSurface.create(rootElement, {
130                // prevent default size settings
131                disableAspect: true,
132                theme: appTheme.SciChartJsTheme,
133            }),
134            dataPromise,
135        ]);
136        const { wasmContext, sciChartSurface } = chart;
137        const { dateValues, openValues, highValues, lowValues, closeValues, volumeValues } = data;
138
139        chart1XAxis = new DiscontinuousDateAxis(wasmContext, {
140            drawLabels: false,
141            drawMajorTickLines: false,
142            drawMinorTickLines: false,
143        });
144        sciChartSurface.xAxes.add(chart1XAxis);
145
146        const yAxis = new NumericAxis(wasmContext, {
147            maxAutoTicks: 5,
148            autoRange: EAutoRange.Always,
149            growBy: new NumberRange(0.3, 0.11),
150            labelFormat: ENumericFormat.Decimal,
151            labelPrecision: 4,
152            cursorLabelFormat: ENumericFormat.Decimal,
153            cursorLabelPrecision: 4,
154            labelPrefix: "$",
155            axisAlignment,
156        });
157        sciChartSurface.yAxes.add(yAxis);
158
159        // OHLC DATA SERIES
160        const usdDataSeries = new OhlcDataSeries(wasmContext, {
161            dataSeriesName: "EUR/USD",
162            xValues: dateValues,
163            openValues,
164            highValues,
165            lowValues,
166            closeValues,
167        });
168        const fcRendSeries = new FastCandlestickRenderableSeries(wasmContext, {
169            dataSeries: usdDataSeries,
170            stroke: appTheme.ForegroundColor, // Used for legend template
171            brushUp: upCol + "77",
172            brushDown: downCol + "77",
173            strokeUp: upCol,
174            strokeDown: downCol,
175        });
176        sciChartSurface.renderableSeries.add(fcRendSeries);
177
178        // MA1 SERIES
179        const maLowDataSeries = new XyMovingAverageFilter(usdDataSeries, {
180            dataSeriesName: "MA 50 Low",
181            length: 50,
182            field: EDataSeriesField.Low,
183        });
184        const maLowRenderableSeries = new FastLineRenderableSeries(wasmContext, {
185            dataSeries: maLowDataSeries,
186        });
187        sciChartSurface.renderableSeries.add(maLowRenderableSeries);
188        maLowRenderableSeries.rolloverModifierProps.tooltipColor = "red";
189        maLowRenderableSeries.rolloverModifierProps.markerColor = "red";
190        maLowRenderableSeries.stroke = appTheme.VividPink;
191        maLowRenderableSeries.strokeThickness = 2;
192
193        // MA2 SERIES
194        const maHighDataSeries = new XyMovingAverageFilter(usdDataSeries, {
195            dataSeriesName: "MA 200 High",
196            length: 200,
197            field: EDataSeriesField.High,
198        });
199        const maHighRenderableSeries = new FastLineRenderableSeries(wasmContext, {
200            dataSeries: maHighDataSeries,
201        });
202        sciChartSurface.renderableSeries.add(maHighRenderableSeries);
203        maHighRenderableSeries.stroke = appTheme.VividSkyBlue;
204        maHighRenderableSeries.strokeThickness = 2;
205
206        // VOLUME SERIES
207        const yAxis2 = new NumericAxis(wasmContext, {
208            id: "yAxis2",
209            isVisible: false,
210            autoRange: EAutoRange.Always,
211            growBy: new NumberRange(0, 3),
212        });
213        sciChartSurface.yAxes.add(yAxis2);
214
215        const volumeRenderableSeries = new FastColumnRenderableSeries(wasmContext, {
216            yAxisId: "yAxis2",
217            dataSeries: new XyDataSeries(wasmContext, {
218                dataSeriesName: "Volume",
219                xValues: dateValues,
220                yValues: volumeValues,
221            }),
222            dataPointWidth: 0.5,
223            strokeThickness: 1,
224            paletteProvider: new VolumePaletteProvider(usdDataSeries, upCol + opacity, downCol + opacity),
225        });
226        sciChartSurface.renderableSeries.add(volumeRenderableSeries);
227
228        // Add a watermark annotation
229        const watermarkAnnotation = new TextAnnotation({
230            x1: 0.5,
231            y1: 0.5,
232            xCoordinateMode: ECoordinateMode.Relative,
233            yCoordinateMode: ECoordinateMode.Relative,
234            horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
235            verticalAnchorPoint: EVerticalAnchorPoint.Center,
236            opacity: 0.17,
237            textColor: appTheme.ForegroundColor,
238            fontSize: 48,
239            fontWeight: "Bold",
240            text: "Euro / U.S. Dollar - Daily",
241        });
242        sciChartSurface.annotations.add(watermarkAnnotation);
243
244        // MODIFIERS
245        sciChartSurface.chartModifiers.add(new ZoomPanModifier({ enableZoom: true }));
246        sciChartSurface.chartModifiers.add(new ZoomExtentsModifier());
247        sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier());
248        sciChartSurface.chartModifiers.add(
249            new RolloverModifier({
250                modifierGroup: "cursorGroup",
251                showTooltip: false,
252                tooltipLegendTemplate: getTooltipLegendTemplate,
253            })
254        );
255
256        verticalGroup.addSurfaceToGroup(sciChartSurface);
257        priceChartSurface = sciChartSurface;
258        sciChartSurface.zoomExtentsX();
259
260        return { wasmContext, sciChartSurface };
261    };
262
263    // CHART 2 - MACD
264    const drawMacdChart = async (rootElement: string | HTMLDivElement) => {
265        const [{ wasmContext, sciChartSurface }, { dateValues, closeValues }] = await Promise.all([
266            SciChartSurface.create(rootElement, {
267                // prevent default size settings
268                disableAspect: true,
269                theme: appTheme.SciChartJsTheme,
270            }),
271            dataPromise,
272        ]);
273
274        chart2XAxis = new DiscontinuousDateAxis(wasmContext, {
275            drawLabels: false,
276            drawMajorTickLines: false,
277            drawMinorTickLines: false,
278        });
279        sciChartSurface.xAxes.add(chart2XAxis);
280
281        const yAxis = new NumericAxis(wasmContext, {
282            autoRange: EAutoRange.Always,
283            growBy: new NumberRange(0.1, 0.1),
284            axisAlignment,
285            labelPrecision: 2,
286            cursorLabelPrecision: 2,
287            labelStyle: { alignment: ELabelAlignment.Right },
288        });
289        yAxis.labelProvider.numericFormat = ENumericFormat.Decimal;
290        sciChartSurface.yAxes.add(yAxis);
291
292        const macdArray: number[] = [];
293        const signalArray: number[] = [];
294        const divergenceArray: number[] = [];
295        for (let i = 0; i < dateValues.length; i++) {
296            const maSlow = calcAverageForArray(closeValues, 12, i);
297            const maFast = calcAverageForArray(closeValues, 25, i);
298            const macd = maSlow - maFast;
299            macdArray.push(macd);
300            const signal = calcAverageForArray(macdArray, 9, i);
301            signalArray.push(signal);
302            const divergence = macd - signal;
303            divergenceArray.push(divergence);
304        }
305
306        const bandSeries = new FastBandRenderableSeries(wasmContext, {
307            dataSeries: new XyyDataSeries(wasmContext, {
308                dataSeriesName: "MACD",
309                xValues: dateValues,
310                yValues: signalArray,
311                y1Values: macdArray,
312            }),
313            stroke: downCol,
314            strokeY1: upCol,
315            fill: upCol + "77",
316            fillY1: downCol + "77",
317        });
318        sciChartSurface.renderableSeries.add(bandSeries);
319
320        const columnSeries = new FastColumnRenderableSeries(wasmContext, {
321            dataSeries: new XyDataSeries(wasmContext, {
322                dataSeriesName: "Divergence",
323                xValues: dateValues,
324                yValues: divergenceArray,
325            }),
326            paletteProvider: new MacdHistogramPaletteProvider(upCol + "AA", downCol + "AA"),
327            dataPointWidth: 0.5,
328        });
329        sciChartSurface.renderableSeries.add(columnSeries);
330
331        sciChartSurface.chartModifiers.add(
332            new ZoomPanModifier({ enableZoom: true, xyDirection: EXyDirection.XDirection })
333        );
334        sciChartSurface.chartModifiers.add(new ZoomExtentsModifier({ xyDirection: EXyDirection.XDirection }));
335        sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }));
336        sciChartSurface.chartModifiers.add(
337            new RolloverModifier({
338                modifierGroup: "cursorGroup",
339                showTooltip: false,
340                tooltipLegendTemplate: getTooltipLegendTemplate,
341            })
342        );
343
344        verticalGroup.addSurfaceToGroup(sciChartSurface);
345        macdChartSurface = sciChartSurface;
346
347        return { wasmContext, sciChartSurface };
348    };
349
350    // CHART 3 - RSI
351    const drawRsiChart = async (rootElement: string | HTMLDivElement) => {
352        const [{ wasmContext, sciChartSurface }, { dateValues, closeValues }] = await Promise.all([
353            SciChartSurface.create(rootElement, {
354                // prevent default size settings
355                disableAspect: true,
356                theme: appTheme.SciChartJsTheme,
357            }),
358            dataPromise,
359        ]);
360
361        chart3XAxis = new DiscontinuousDateAxis(wasmContext, {
362            autoRange: EAutoRange.Once,
363            labelProvider: new SmartDateLabelProvider(),
364        });
365        sciChartSurface.xAxes.add(chart3XAxis);
366
367        const yAxis = new NumericAxis(wasmContext, {
368            autoRange: EAutoRange.Always,
369            growBy: new NumberRange(0.1, 0.1),
370            labelPrecision: 0,
371            cursorLabelPrecision: 0,
372            axisAlignment,
373            labelStyle: { alignment: ELabelAlignment.Right },
374        });
375        yAxis.labelProvider.numericFormat = ENumericFormat.Decimal;
376        sciChartSurface.yAxes.add(yAxis);
377
378        const RSI_PERIOD = 14;
379        const rsiArray: number[] = [];
380        const gainArray: number[] = [];
381        const lossArray: number[] = [];
382
383        if (dateValues.length) {
384            rsiArray.push(NaN);
385            gainArray.push(NaN);
386            lossArray.push(NaN);
387        }
388
389        for (let i = 1; i < dateValues.length; i++) {
390            const previousClose = closeValues[i - 1];
391            const currentClose = closeValues[i];
392            const gain = currentClose > previousClose ? currentClose - previousClose : 0;
393            gainArray.push(gain);
394            const loss = previousClose > currentClose ? previousClose - currentClose : 0;
395            lossArray.push(loss);
396            const relativeStrength =
397                calcAverageForArray(gainArray, RSI_PERIOD) / calcAverageForArray(lossArray, RSI_PERIOD);
398            const rsi = 100 - 100 / (1 + relativeStrength);
399            rsiArray.push(rsi);
400        }
401        const rsiRenderableSeries = new FastLineRenderableSeries(wasmContext, {
402            dataSeries: new XyDataSeries(wasmContext, {
403                dataSeriesName: "RSI",
404                xValues: dateValues,
405                yValues: rsiArray,
406            }),
407            stroke: appTheme.MutedBlue,
408            strokeThickness: 2,
409        });
410        sciChartSurface.renderableSeries.add(rsiRenderableSeries);
411
412        sciChartSurface.chartModifiers.add(
413            new ZoomPanModifier({ enableZoom: true, xyDirection: EXyDirection.XDirection })
414        );
415        sciChartSurface.chartModifiers.add(new ZoomExtentsModifier({ xyDirection: EXyDirection.XDirection }));
416        sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }));
417        sciChartSurface.chartModifiers.add(
418            new RolloverModifier({
419                modifierGroup: "cursorGroup",
420                showTooltip: false,
421                tooltipLegendTemplate: getTooltipLegendTemplate,
422            })
423        );
424
425        verticalGroup.addSurfaceToGroup(sciChartSurface);
426        rsiChartSurface = sciChartSurface;
427
428        return { wasmContext, sciChartSurface };
429    };
430
431    // DRAW OVERVIEW
432    // Must be done after main chart creation
433    const drawOverview = (mainSurface: SciChartSurface) => async (rootElement: string | HTMLDivElement) => {
434        const overview = await SciChartOverview.create(mainSurface, rootElement, {
435            // prevent default size settings
436            disableAspect: true,
437            theme: appTheme.SciChartJsTheme,
438            transformRenderableSeries: getOverviewSeries,
439        });
440
441        return { sciChartSurface: overview.overviewSciChartSurface };
442    };
443
444    const configureAfterInit = () => {
445        const synchronizeAxes = () => {
446            // TODO refactor using AxisSynchroniser
447
448            // SYNCHRONIZE VISIBLE RANGES
449            chart1XAxis.visibleRangeChanged.subscribe((data1) => {
450                chart2XAxis.visibleRange = data1.visibleRange;
451                chart3XAxis.visibleRange = data1.visibleRange;
452            });
453            chart2XAxis.visibleRangeChanged.subscribe((data1) => {
454                chart1XAxis.visibleRange = data1.visibleRange;
455                chart3XAxis.visibleRange = data1.visibleRange;
456            });
457            chart3XAxis.visibleRangeChanged.subscribe((data1) => {
458                chart1XAxis.visibleRange = data1.visibleRange;
459                chart2XAxis.visibleRange = data1.visibleRange;
460            });
461        };
462
463        synchronizeAxes();
464
465        // Force showing the latest 200 bars
466        const twoHundredDaysOfSeconds = 60 * 60 * 24 * 200;
467        chart1XAxis.visibleRange = new NumberRange(
468            chart1XAxis.visibleRange.max - twoHundredDaysOfSeconds,
469            chart1XAxis.visibleRange.max
470        );
471    };
472
473    return { drawPriceChart, drawMacdChart, drawRsiChart, drawOverview, configureAfterInit };
474};
475
476/**
477 * An example PaletteProvider applied to the volume column series. It will return green / red
478 * fills and strokes when the main price data bar is up or down
479 */
480class VolumePaletteProvider implements IStrokePaletteProvider, IFillPaletteProvider {
481    public readonly strokePaletteMode: EStrokePaletteMode = EStrokePaletteMode.SOLID;
482    public readonly fillPaletteMode: EFillPaletteMode = EFillPaletteMode.SOLID;
483    private priceData: OhlcDataSeries;
484    private volumeUpArgb: number;
485    private volumnDownArgb: number;
486
487    constructor(priceData: OhlcDataSeries, volumeUpColor: string, volumeDownColor: string) {
488        this.priceData = priceData;
489        this.volumeUpArgb = parseColorToUIntArgb(volumeUpColor);
490        this.volumnDownArgb = parseColorToUIntArgb(volumeDownColor);
491    }
492
493    onAttached(parentSeries: IRenderableSeries): void {}
494
495    onDetached(): void {}
496
497    overrideFillArgb(xValue: number, yValue: number, index: number): number {
498        const open = this.priceData.getNativeOpenValues().get(index);
499        const close = this.priceData.getNativeCloseValues().get(index);
500
501        return close >= open ? this.volumeUpArgb : this.volumnDownArgb;
502    }
503
504    overrideStrokeArgb(xValue: number, yValue: number, index: number): number {
505        return this.overrideFillArgb(xValue, yValue, index);
506    }
507}
508
509// tslint:disable-next-line:max-classes-per-file
510class MacdHistogramPaletteProvider implements IStrokePaletteProvider, IFillPaletteProvider {
511    public readonly strokePaletteMode: EStrokePaletteMode = EStrokePaletteMode.SOLID;
512    public readonly fillPaletteMode: EFillPaletteMode = EFillPaletteMode.SOLID;
513    private aboveZeroArgb: number;
514    private belowZeroArgb: number;
515
516    constructor(aboveZeroColor: string, belowZeroColor: string) {
517        this.aboveZeroArgb = parseColorToUIntArgb(aboveZeroColor);
518        this.belowZeroArgb = parseColorToUIntArgb(belowZeroColor);
519    }
520
521    onAttached(parentSeries: IRenderableSeries): void {}
522
523    onDetached(): void {}
524
525    overrideFillArgb(xValue: number, yValue: number, index: number): number {
526        return yValue >= 0 ? this.aboveZeroArgb : this.belowZeroArgb;
527    }
528
529    overrideStrokeArgb(xValue: number, yValue: number, index: number): number {
530        return this.overrideFillArgb(xValue, yValue, index);
531    }
532}
533

Multi Pane Stock Charts using Sync Multi-Chart and JavaScript

Overview

This example demonstrates a multi-pane stock chart built exclusively with JavaScript and SciChart.js. It features a primary price chart along with indicator panels for MACD and RSI, plus an additional overview chart that synchronizes with the main charts.

Technical Implementation

The charts are initialized asynchronously using functions such as drawPriceChart, drawMacdChart, drawRsiChart, and drawOverview. These functions leverage the SciChartSurface.create method to establish high-performance WebGL charts. Custom palette providers are implemented for the volume and MACD histogram series by extending the IStrokePaletteProvider and IFillPaletteProvider interfaces, as detailed in The PaletteProvider API. Additionally, the charts are grouped using the SciChartVerticalGroup and synchronized by subscribing to the x-axis visibleRangeChanged events, which is explained in the Tutorial 09 - Linking Multiple Charts.

Features and Capabilities

The example supports real-time chart updates, advanced technical analysis through moving average filters (see XyMovingAverageFilter API Documentation), and interactive tooltips configured via the RolloverModifier. The integration of chart modifiers such as ZoomPanModifier, ZoomExtentsModifier, and MouseWheelZoomModifier ensures seamless navigation and interaction.

Integration and Best Practices

Built with JavaScript, this implementation follows asynchronous initialization best practices outlined in Getting Started with SciChart JS, and employs performance optimization techniques recommended in Performance Tips & Tricks. The synchronized overview chart, created using the transformRenderableSeries feature, further enhances usability by providing a compact visual summary, as described in How to Link JavaScript Charts and Synchronise zooming, panning ....

Overall, the example offers a comprehensive demonstration of chart synchronization, advanced customization, and efficient performance optimizations, making it a valuable reference for developers building high-performance financial charting applications using SciChart.js and JavaScript.

javascript Chart Examples & Demos

See Also: Financial Charts (9 Demos)

JavaScript Candlestick Chart | Online JavaScript Chart Examples

JavaScript Candlestick Chart

Discover how to create a JavaScript Candlestick Chart or Stock Chart using SciChart.js. For high Performance JavaScript Charts, get your free demo now.

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 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.