Angular 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

angular.ts

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                snapToDataPoint: true,
253                tooltipLegendTemplate: getTooltipLegendTemplate,
254            })
255        );
256
257        verticalGroup.addSurfaceToGroup(sciChartSurface);
258        priceChartSurface = sciChartSurface;
259        sciChartSurface.zoomExtentsX();
260
261        return { wasmContext, sciChartSurface };
262    };
263
264    // CHART 2 - MACD
265    const drawMacdChart = async (rootElement: string | HTMLDivElement) => {
266        const [{ wasmContext, sciChartSurface }, { dateValues, closeValues }] = await Promise.all([
267            SciChartSurface.create(rootElement, {
268                // prevent default size settings
269                disableAspect: true,
270                theme: appTheme.SciChartJsTheme,
271            }),
272            dataPromise,
273        ]);
274
275        chart2XAxis = new DiscontinuousDateAxis(wasmContext, {
276            drawLabels: false,
277            drawMajorTickLines: false,
278            drawMinorTickLines: false,
279        });
280        sciChartSurface.xAxes.add(chart2XAxis);
281
282        const yAxis = new NumericAxis(wasmContext, {
283            autoRange: EAutoRange.Always,
284            growBy: new NumberRange(0.1, 0.1),
285            axisAlignment,
286            labelPrecision: 2,
287            cursorLabelPrecision: 2,
288            labelStyle: { alignment: ELabelAlignment.Right },
289        });
290        yAxis.labelProvider.numericFormat = ENumericFormat.Decimal;
291        sciChartSurface.yAxes.add(yAxis);
292
293        const macdArray: number[] = [];
294        const signalArray: number[] = [];
295        const divergenceArray: number[] = [];
296        for (let i = 0; i < dateValues.length; i++) {
297            const maSlow = calcAverageForArray(closeValues, 12, i);
298            const maFast = calcAverageForArray(closeValues, 25, i);
299            const macd = maSlow - maFast;
300            macdArray.push(macd);
301            const signal = calcAverageForArray(macdArray, 9, i);
302            signalArray.push(signal);
303            const divergence = macd - signal;
304            divergenceArray.push(divergence);
305        }
306
307        const bandSeries = new FastBandRenderableSeries(wasmContext, {
308            dataSeries: new XyyDataSeries(wasmContext, {
309                dataSeriesName: "MACD",
310                xValues: dateValues,
311                yValues: signalArray,
312                y1Values: macdArray,
313            }),
314            stroke: downCol,
315            strokeY1: upCol,
316            fill: upCol + "77",
317            fillY1: downCol + "77",
318        });
319        sciChartSurface.renderableSeries.add(bandSeries);
320
321        const columnSeries = new FastColumnRenderableSeries(wasmContext, {
322            dataSeries: new XyDataSeries(wasmContext, {
323                dataSeriesName: "Divergence",
324                xValues: dateValues,
325                yValues: divergenceArray,
326            }),
327            paletteProvider: new MacdHistogramPaletteProvider(upCol + "AA", downCol + "AA"),
328            dataPointWidth: 0.5,
329        });
330        sciChartSurface.renderableSeries.add(columnSeries);
331
332        sciChartSurface.chartModifiers.add(
333            new ZoomPanModifier({ enableZoom: true, xyDirection: EXyDirection.XDirection })
334        );
335        sciChartSurface.chartModifiers.add(new ZoomExtentsModifier({ xyDirection: EXyDirection.XDirection }));
336        sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }));
337        sciChartSurface.chartModifiers.add(
338            new RolloverModifier({
339                modifierGroup: "cursorGroup",
340                showTooltip: false,
341                snapToDataPoint: true,
342                tooltipLegendTemplate: getTooltipLegendTemplate,
343            })
344        );
345
346        verticalGroup.addSurfaceToGroup(sciChartSurface);
347        macdChartSurface = sciChartSurface;
348
349        return { wasmContext, sciChartSurface };
350    };
351
352    // CHART 3 - RSI
353    const drawRsiChart = async (rootElement: string | HTMLDivElement) => {
354        const [{ wasmContext, sciChartSurface }, { dateValues, closeValues }] = await Promise.all([
355            SciChartSurface.create(rootElement, {
356                // prevent default size settings
357                disableAspect: true,
358                theme: appTheme.SciChartJsTheme,
359            }),
360            dataPromise,
361        ]);
362
363        chart3XAxis = new DiscontinuousDateAxis(wasmContext, {
364            autoRange: EAutoRange.Once,
365            labelProvider: new SmartDateLabelProvider(),
366        });
367        sciChartSurface.xAxes.add(chart3XAxis);
368
369        const yAxis = new NumericAxis(wasmContext, {
370            autoRange: EAutoRange.Always,
371            growBy: new NumberRange(0.1, 0.1),
372            labelPrecision: 0,
373            cursorLabelPrecision: 0,
374            axisAlignment,
375            labelStyle: { alignment: ELabelAlignment.Right },
376        });
377        yAxis.labelProvider.numericFormat = ENumericFormat.Decimal;
378        sciChartSurface.yAxes.add(yAxis);
379
380        const RSI_PERIOD = 14;
381        const rsiArray: number[] = [];
382        const gainArray: number[] = [];
383        const lossArray: number[] = [];
384
385        if (dateValues.length) {
386            rsiArray.push(NaN);
387            gainArray.push(NaN);
388            lossArray.push(NaN);
389        }
390
391        for (let i = 1; i < dateValues.length; i++) {
392            const previousClose = closeValues[i - 1];
393            const currentClose = closeValues[i];
394            const gain = currentClose > previousClose ? currentClose - previousClose : 0;
395            gainArray.push(gain);
396            const loss = previousClose > currentClose ? previousClose - currentClose : 0;
397            lossArray.push(loss);
398            const relativeStrength =
399                calcAverageForArray(gainArray, RSI_PERIOD) / calcAverageForArray(lossArray, RSI_PERIOD);
400            const rsi = 100 - 100 / (1 + relativeStrength);
401            rsiArray.push(rsi);
402        }
403        const rsiRenderableSeries = new FastLineRenderableSeries(wasmContext, {
404            dataSeries: new XyDataSeries(wasmContext, {
405                dataSeriesName: "RSI",
406                xValues: dateValues,
407                yValues: rsiArray,
408            }),
409            stroke: appTheme.MutedBlue,
410            strokeThickness: 2,
411        });
412        sciChartSurface.renderableSeries.add(rsiRenderableSeries);
413
414        sciChartSurface.chartModifiers.add(
415            new ZoomPanModifier({ enableZoom: true, xyDirection: EXyDirection.XDirection })
416        );
417        sciChartSurface.chartModifiers.add(new ZoomExtentsModifier({ xyDirection: EXyDirection.XDirection }));
418        sciChartSurface.chartModifiers.add(new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }));
419        sciChartSurface.chartModifiers.add(
420            new RolloverModifier({
421                modifierGroup: "cursorGroup",
422                showTooltip: false,
423                snapToDataPoint: true,
424                tooltipLegendTemplate: getTooltipLegendTemplate,
425            })
426        );
427
428        verticalGroup.addSurfaceToGroup(sciChartSurface);
429        rsiChartSurface = sciChartSurface;
430
431        return { wasmContext, sciChartSurface };
432    };
433
434    // DRAW OVERVIEW
435    // Must be done after main chart creation
436    const drawOverview = (mainSurface: SciChartSurface) => async (rootElement: string | HTMLDivElement) => {
437        const overview = await SciChartOverview.create(mainSurface, rootElement, {
438            // prevent default size settings
439            disableAspect: true,
440            theme: appTheme.SciChartJsTheme,
441            transformRenderableSeries: getOverviewSeries,
442        });
443
444        return { sciChartSurface: overview.overviewSciChartSurface };
445    };
446
447    const configureAfterInit = () => {
448        const synchronizeAxes = () => {
449            // TODO refactor using AxisSynchroniser
450
451            // SYNCHRONIZE VISIBLE RANGES
452            chart1XAxis.visibleRangeChanged.subscribe((data1) => {
453                chart2XAxis.visibleRange = data1.visibleRange;
454                chart3XAxis.visibleRange = data1.visibleRange;
455            });
456            chart2XAxis.visibleRangeChanged.subscribe((data1) => {
457                chart1XAxis.visibleRange = data1.visibleRange;
458                chart3XAxis.visibleRange = data1.visibleRange;
459            });
460            chart3XAxis.visibleRangeChanged.subscribe((data1) => {
461                chart1XAxis.visibleRange = data1.visibleRange;
462                chart2XAxis.visibleRange = data1.visibleRange;
463            });
464        };
465
466        synchronizeAxes();
467
468        // Force showing the latest 200 bars
469        const twoHundredDaysOfSeconds = 60 * 60 * 24 * 200;
470        chart1XAxis.visibleRange = new NumberRange(
471            chart1XAxis.visibleRange.max - twoHundredDaysOfSeconds,
472            chart1XAxis.visibleRange.max
473        );
474    };
475
476    return { drawPriceChart, drawMacdChart, drawRsiChart, drawOverview, configureAfterInit };
477};
478
479/**
480 * An example PaletteProvider applied to the volume column series. It will return green / red
481 * fills and strokes when the main price data bar is up or down
482 */
483class VolumePaletteProvider implements IStrokePaletteProvider, IFillPaletteProvider {
484    public readonly strokePaletteMode: EStrokePaletteMode = EStrokePaletteMode.SOLID;
485    public readonly fillPaletteMode: EFillPaletteMode = EFillPaletteMode.SOLID;
486    private priceData: OhlcDataSeries;
487    private volumeUpArgb: number;
488    private volumnDownArgb: number;
489
490    constructor(priceData: OhlcDataSeries, volumeUpColor: string, volumeDownColor: string) {
491        this.priceData = priceData;
492        this.volumeUpArgb = parseColorToUIntArgb(volumeUpColor);
493        this.volumnDownArgb = parseColorToUIntArgb(volumeDownColor);
494    }
495
496    onAttached(parentSeries: IRenderableSeries): void {}
497
498    onDetached(): void {}
499
500    overrideFillArgb(xValue: number, yValue: number, index: number): number {
501        const open = this.priceData.getNativeOpenValues().get(index);
502        const close = this.priceData.getNativeCloseValues().get(index);
503
504        return close >= open ? this.volumeUpArgb : this.volumnDownArgb;
505    }
506
507    overrideStrokeArgb(xValue: number, yValue: number, index: number): number {
508        return this.overrideFillArgb(xValue, yValue, index);
509    }
510}
511
512// tslint:disable-next-line:max-classes-per-file
513class MacdHistogramPaletteProvider implements IStrokePaletteProvider, IFillPaletteProvider {
514    public readonly strokePaletteMode: EStrokePaletteMode = EStrokePaletteMode.SOLID;
515    public readonly fillPaletteMode: EFillPaletteMode = EFillPaletteMode.SOLID;
516    private aboveZeroArgb: number;
517    private belowZeroArgb: number;
518
519    constructor(aboveZeroColor: string, belowZeroColor: string) {
520        this.aboveZeroArgb = parseColorToUIntArgb(aboveZeroColor);
521        this.belowZeroArgb = parseColorToUIntArgb(belowZeroColor);
522    }
523
524    onAttached(parentSeries: IRenderableSeries): void {}
525
526    onDetached(): void {}
527
528    overrideFillArgb(xValue: number, yValue: number, index: number): number {
529        return yValue >= 0 ? this.aboveZeroArgb : this.belowZeroArgb;
530    }
531
532    overrideStrokeArgb(xValue: number, yValue: number, index: number): number {
533        return this.overrideFillArgb(xValue, yValue, index);
534    }
535}
536

Angular Multi-Pane Stock Charts using Sync Multi-Chart

Overview

This Angular example demonstrates the creation of a synchronized multi-pane stock chart application using SciChart.js. The application renders several chart panels including a primary price chart, MACD and RSI indicator panels, and an overview chart that appears once the main charts are initialized. It leverages Angular standalone components for modular and dynamic chart rendering.

Technical Implementation

The core of the example is contained within the Angular component 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. For more details on subscribing to these events, refer to the Axis Ranging - How to Listen to VisibleRange Changes documentation. Additionally, asynchronous initialization of charts is handled in a way that once the primary charts are ready, the overview chart is dynamically rendered using Angular mechanisms. This approach is aligned with Angular’s best practices for managing asynchronous operations, as discussed in Component Lifecycle - Angular.

Features and Capabilities

The example not only showcases real-time charting capabilities with synchronized zooming, panning, and cursor interactions but also includes advanced customizations like custom palette providers for volume and MACD histogram series. The flexible use of CSS flexbox layout ensures that the UI is responsive and that charts adjust to various screen sizes. The implementation highlights the importance of performance considerations when dealing with dynamic, high-performance charting applications in Angular. For more on performance optimization in multi-chart scenarios, see How to Link JavaScript Charts and Synchronise zooming, panning ....

Integration and Best Practices

This example is built entirely on Angular, using standalone components to integrate SciChart.js seamlessly into an Angular application. The use of scichart-angular makes it easy to pass initialization functions as component properties, thereby streamlining the component interaction process as described in Component interaction - Angular. The synchronization of visual ranges across multiple charts ensures a coherent user experience, and the dynamic rendering approach improves both performance and flexibility. For additional insights into dynamic component rendering and lazy loading in Angular, consider reviewing resources such as Implementing Angular Lazy Loading with Dynamic Chart ....

Overall, this Angular multi-pane stock chart example demonstrates effective usage of SciChart.js in an Angular environment, emphasizing modular design, performance optimization, and advanced visual sync capabilities for stock charting applications.

angular Chart Examples & Demos

See Also: Financial Charts (13 Demos)

Angular Candlestick Chart | Online JavaScript Chart Examples

Angular Candlestick Chart

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

Angular OHLC Chart | Angular Charts | SciChart.js Demo

Angular OHLC Chart

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

Angular Realtime Ticking Stock Chart | SciChart.js Demo

Angular Realtime Ticking Stock Charts

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

Angular Orderbook Heatmap | Angular Charts | SciChart.js Demo

Angular Orderbook Heatmap

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

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

Angular Multi-Pane Stock Charts using Subcharts

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

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

Financial Data Filters | Angular Charts | SciChart.js Demo

Financial Data Filters

Shows one seeded OHLC data set toggled between no filter, Heikin-Ashi, Renko, and Point & Figure views.

Angular Market Depth Chart | Angular Charts | SciChart.js

Angular Market Depth Chart

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

Angular Chart Hoverable Buy Sell Marker Annotations

Angular Chart Hoverable Buy Sell Marker Annotations

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

Angular User Annotated Stock Chart | SciChart.js Demo

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

Angular Trading Drawing Tools for Devs | Try SciChart Demo

Angular Trading Drawing Tools Demo

Build high-performance financial apps with Angular trading drawing tools. Try SciChart’s demo to see the advanced drawing tools for trading apps in action.

Angular Custom Paired Dashed Polyline Annotation | SciChart

Angular Custom Paired Dashed Polyline Annotation

Create a custom Angular stock chart annotation by extending SciChart.js PolyLineAnnotation with paired dashed connectors.

Angular Freehand Drawing Tools for Apps | Try SciChart Demo

Angular Freehand Drawing Tools Demo

Deploy the ultimate Angular freehand drawing tool in your app. Render complex freehand drawing tools with a smooth UI experience. Try the SciChart demo today.

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