React 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 and React

Overview

This example demonstrates a multi-pane stock charts implementation using SciChart.js with React. The app features a primary price chart, along with MACD and RSI indicator panels, and an overview chart that synchronizes zooming, panning, and crosshair interactions across all panes.

Technical Implementation

The React integration utilizes the <SciChartReact/> component from the scichart-react package to initialize charts dynamically. React state management (with useState) is employed to set the main chart before the overview is initialized, and the synchronization across multiple panels is achieved by subscribing to visible range changes on the x-axes. The core of the example is contained within Index.tsx where multiple instances of the SciChart chart component are instantiated. These instances are initialized with functions from the initialization API, such as drawPriceChart, drawMacdChart, drawRsiChart, and drawOverview. Each initialization function configures its respective chart using the SciChartSurface API, allowing for dynamic chart creation and synchronization. Axis synchronization is implemented by subscribing to the visibleRangeChanged events on the x-axes across the different chart panels.

Features and Capabilities

Key features include advanced real-time updates, custom palette providers for rendering volume and MACD series, and enhanced customizations such as annotated watermarks. The implementation leverages moving average filters and bespoke tooltips configured via custom palette providers, providing detailed visual insights. For more details on creating custom palette providers, check out the PaletteProvider API.

Integration and Best Practices

The example is built using a flexible CSS flexbox layout to host multiple chart panels, ensuring responsiveness and consistency in UI rendering. Chart synchronization is efficiently handled using techniques described in the Synchronizing Multiple Charts documentation. Additionally, the approach shows how to pass initialization functions as props in the <SciChartReact/> component, following best practices for React integration.

react Chart Examples & Demos

See Also: Financial Charts (9 Demos)

React Candlestick Chart | Online JavaScript Chart Examples

React Candlestick Chart

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

React OHLC Chart | React Charts | SciChart.js Demo

React OHLC Chart

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

React Realtime Ticking Stock Chart | SciChart.js Demo

React Realtime Ticking Stock Charts

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

NEW!
React Orderbook Heatmap | React Charts | SciChart.js Demo

Order Book Heatmap

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

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

React Multi-Pane Stock Charts using Subcharts

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

Tenor Curves Demo | React 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.

React Market Depth Chart | React Charts | SciChart.js Demo

React Market Depth Chart

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

React Chart Hoverable Buy Sell Marker Annotations | SciChart

React Chart Hoverable Buy Sell Marker Annotations

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

React User Annotated Stock Chart | React Charts | SciChart.js

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