JavaScript User Annotated Stock Chart

This demo shows you how to create a JavaScript User Annotated Stock Chart 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.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

index.tsx

binanceRestClient.ts

ExampleDataProvider.ts

theme.ts

CreateLineAnnotationModifier.ts

CreateTradeMarkerModifier.ts

RulerModifier.ts

Copy to clipboard
Minimise
Fullscreen
1// SCICHART EXAMPLE
2import {
3    AnnotationClickEventArgs,
4    buildDataSeries,
5    CategoryAxis,
6    chartReviver,
7    configure2DSurface,
8    CursorModifier,
9    CursorTooltipSvgAnnotation,
10    CustomAnnotation,
11    DateTimeNumericAxis,
12    EAutoRange,
13    EBaseType,
14    ECoordinateMode,
15    EDataSeriesType,
16    EExecuteOn,
17    EFillPaletteMode,
18    EHorizontalAnchorPoint,
19    EMultiLineAlignment,
20    ENumericFormat,
21    ESeriesType,
22    EVerticalAnchorPoint,
23    FastCandlestickRenderableSeries,
24    FastColumnRenderableSeries,
25    FastLineRenderableSeries,
26    FastMountainRenderableSeries,
27    FastOhlcRenderableSeries,
28    GradientParams,
29    IFillPaletteProvider,
30    IPointMetadata,
31    IRenderableSeries,
32    MouseWheelZoomModifier,
33    NativeTextAnnotation,
34    NumberRange,
35    NumericAxis,
36    OhlcDataSeries,
37    OhlcSeriesInfo,
38    parseColorToUIntArgb,
39    Point,
40    registerFunction,
41    SciChartOverview,
42    SciChartSurface,
43    SeriesInfo,
44    SmartDateLabelProvider,
45    TOhlcSeriesData,
46    XyDataSeries,
47    XyMovingAverageFilter,
48    ZoomExtentsModifier,
49    ZoomPanModifier,
50} from "scichart";
51import { appTheme } from "../../../theme";
52import { CreateTradeMarkerModifier } from "./CreateTradeMarkerModifier";
53import { CreateLineAnnotationModifier } from "./CreateLineAnnotationModifier";
54import { VerticalYRulerModifier } from "./RulerModifier";
55import { simpleBinanceRestClient } from "../../../ExampleData/binanceRestClient";
56import { ExampleDataProvider } from "../../../ExampleData/ExampleDataProvider";
57
58const deleteOnClick = (args: AnnotationClickEventArgs) => {
59    if (args.sender.isSelected && args.mouseArgs.ctrlKey) {
60        args.sender.parentSurface.annotations.remove(args.sender, true);
61    }
62};
63
64registerFunction(EBaseType.OptionFunction, "deleteOnClick", deleteOnClick);
65
66export const drawExample = async (divElementId: string | HTMLDivElement) => {
67    // Create a SciChartSurface
68    const { sciChartSurface, wasmContext } = await SciChartSurface.create(divElementId, {
69        theme: appTheme.SciChartJsTheme,
70    });
71
72    const xAxis = new CategoryAxis(wasmContext, {
73        // autoRange.never as we're setting visibleRange explicitly below. If you dont do this, leave this flag default
74        autoRange: EAutoRange.Never,
75        labelProvider: new SmartDateLabelProvider(),
76    });
77    sciChartSurface.xAxes.add(xAxis);
78
79    // Create a NumericAxis on the YAxis with 2 Decimal Places
80    sciChartSurface.yAxes.add(
81        new NumericAxis(wasmContext, {
82            growBy: new NumberRange(0.1, 0.1),
83            labelFormat: ENumericFormat.Decimal,
84            labelPrecision: 2,
85            labelPrefix: "$",
86            autoRange: EAutoRange.Always,
87        })
88    );
89
90    const day = 24 * 60 * 60;
91    const startDate = new Date(Date.now() - 300 * day);
92    const { xValues, openValues, highValues, lowValues, closeValues } = ExampleDataProvider.getRandomOHLCVData(
93        300,
94        1.5,
95        startDate,
96        day
97    );
98
99    // Create and add the Candlestick series
100    // The Candlestick Series requires a special dataseries type called OhlcDataSeries with o,h,l,c and date values
101    const candleDataSeries = new OhlcDataSeries(wasmContext, {
102        xValues,
103        openValues,
104        highValues,
105        lowValues,
106        closeValues,
107        dataSeriesName: "BTC/USDT",
108    });
109    const candlestickSeries = new FastCandlestickRenderableSeries(wasmContext, {
110        id: "Candles",
111        dataSeries: candleDataSeries,
112        stroke: appTheme.ForegroundColor, // used by cursorModifier below
113        strokeThickness: 1,
114        brushUp: appTheme.VividGreen + "77",
115        brushDown: appTheme.MutedRed + "77",
116        strokeUp: appTheme.VividGreen,
117        strokeDown: appTheme.MutedRed,
118    });
119    sciChartSurface.renderableSeries.add(candlestickSeries);
120
121    // Add some moving averages using SciChart's filters/transforms API
122    // when candleDataSeries updates, XyMovingAverageFilter automatically recomputes
123    sciChartSurface.renderableSeries.add(
124        new FastLineRenderableSeries(wasmContext, {
125            dataSeries: new XyMovingAverageFilter(candleDataSeries, {
126                dataSeriesName: "Moving Average (20)",
127                length: 20,
128            }),
129            stroke: appTheme.VividSkyBlue,
130        })
131    );
132
133    sciChartSurface.renderableSeries.add(
134        new FastLineRenderableSeries(wasmContext, {
135            dataSeries: new XyMovingAverageFilter(candleDataSeries, {
136                dataSeriesName: "Moving Average (50)",
137                length: 50,
138            }),
139            stroke: appTheme.VividPink,
140        })
141    );
142
143    // Optional: Add some interactivity modifiers
144    sciChartSurface.chartModifiers.add(
145        new ZoomExtentsModifier(),
146        new MouseWheelZoomModifier(),
147        new ZoomPanModifier({ id: "pan" }),
148        new CreateTradeMarkerModifier({ id: "marker" }),
149        new CreateLineAnnotationModifier({ id: "line" })
150    );
151    sciChartSurface.chartModifiers.getById("marker").isEnabled = false;
152    sciChartSurface.chartModifiers.getById("line").isEnabled = false;
153
154    const helpAnnotation = new NativeTextAnnotation({
155        x1: 20,
156        y1: 20,
157        xCoordinateMode: ECoordinateMode.Pixel,
158        yCoordinateMode: ECoordinateMode.Pixel,
159        verticalAnchorPoint: EVerticalAnchorPoint.Top,
160        multiLineAlignment: EMultiLineAlignment.Left,
161        textColor: appTheme.ForegroundColor,
162    });
163    // Add this to modifierAnnotations so it is not saved/loaded
164    sciChartSurface.modifierAnnotations.add(helpAnnotation);
165
166    const getDefinition = () => {
167        return {
168            visibleRange: xAxis.visibleRange,
169            annotations: sciChartSurface.annotations.asArray().map((annotation) => annotation.toJSON()),
170            data: candleDataSeries.toJSON(),
171        };
172    };
173    const applyDefinition = (definition: any) => {
174        if (definition) {
175            configure2DSurface({ annotations: definition.annotations }, sciChartSurface, wasmContext);
176            xAxis.visibleRange = definition.visibleRange;
177            const newData = definition.data.options as TOhlcSeriesData;
178            candleDataSeries.clear();
179            candleDataSeries.appendRange(
180                newData.xValues,
181                newData.openValues,
182                newData.highValues,
183                newData.lowValues,
184                newData.closeValues
185            );
186        }
187    };
188
189    const setChartMode = (mode: string) => {
190        if (mode === "pan") {
191            sciChartSurface.chartModifiers.getById("marker").isEnabled = false;
192            sciChartSurface.chartModifiers.getById("line").isEnabled = false;
193            sciChartSurface.chartModifiers.getById("pan").isEnabled = true;
194            helpAnnotation.text = `Click and drag to pan the chart`;
195        } else if (mode === "line") {
196            sciChartSurface.chartModifiers.getById("marker").isEnabled = false;
197            sciChartSurface.chartModifiers.getById("line").isEnabled = true;
198            sciChartSurface.chartModifiers.getById("pan").isEnabled = false;
199            helpAnnotation.text = `Click and drag to draw a line.
200Ctrl + click a line to delete it`;
201        } else if (mode === "marker") {
202            sciChartSurface.chartModifiers.getById("marker").isEnabled = true;
203            sciChartSurface.chartModifiers.getById("line").isEnabled = false;
204            sciChartSurface.chartModifiers.getById("pan").isEnabled = false;
205            helpAnnotation.text = `Left click to place a buy marker.
206Right click to place a sell marker
207Ctrl + Click to delete a marker`;
208        }
209    };
210
211    const resetChart = () => {
212        sciChartSurface.annotations.clear(true);
213        // Zoom to the latest 100 candles
214        xAxis.visibleRange = new NumberRange(xValues.length - 100, xValues.length - 1);
215    };
216
217    resetChart();
218    setChartMode("line");
219
220    return {
221        sciChartSurface,
222        controls: { getDefinition, applyDefinition, resetChart, setChartMode },
223    };
224};
225

User Annotated Stock Chart in JavaScript

Overview

This example demonstrates how to build an interactive candlestick stock chart using SciChart.js in a JavaScript application. It offers advanced customization features, including the ability to add custom line annotations and trade markers for enhanced financial charting. The implementation also leverages state serialization to save and reload chart configurations, ensuring a persistent and responsive user experience.

Technical Implementation

The chart is initialized asynchronously using the SciChartSurface.create() method, which sets up the WebGL rendering context for high-performance graphics. Custom chart modifiers such as the CreateLineAnnotationModifier and CreateTradeMarkerModifier extend the SciChart.js ChartModifierBase2D class to handle mouse events and enable interactive annotation creation. Coordinate conversions are performed with the translateFromCanvasToSeriesViewRect utility, which transforms canvas pixel positions into data coordinates. This approach is detailed in the Custom Chart Modifier API and the Axis APIs - Convert Pixel to Data Coordinates documentation.

Features and Capabilities

The example integrates several advanced features:

  • Real-Time Data Processing: FastCandlestickRenderableSeries combined with XyMovingAverageFilters ensures efficient data visualization.
  • Interactive Controls: Users can switch between pan, line drawing, and marker placement modes, facilitating dynamic interactions with the chart.
  • Custom Annotations: With the CreateLineAnnotationModifier and CreateTradeMarkerModifier, line and trade marker annotations are created on-click and modified on-the-fly, allowing for detailed chart analysis. More information is available in Tutorial 06 - Adding Annotations.
  • State Persistence: The entire chart state, including annotations and data, is serialized to JSON and stored using the localStorage API. This mechanism is explained in the Serialization and Deserialization of Charts guide.

Integration and Best Practices

This JavaScript implementation follows best practices for asynchronous module initialization and performance optimization. By leveraging WebGL for rendering and maintaining chart state through JSON configurations, developers can achieve both high performance and robust interactivity. For further details on asynchronous setup, see Getting Started with SciChart JS. The example also demonstrates practical techniques for managing persistent state via the localStorage API, ensuring that user annotations and configurations are preserved across sessions.

Overall, this example serves as a comprehensive guide to building high-performance, interactive financial charts in JavaScript with SciChart.js, combining advanced customization, real-time data processing, and robust state persistence.

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

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