React User Annotated Stock Chart

This demo shows you how to create a React 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

React User Annotated Stock Chart

Overview

This example demonstrates how to create a user annotated stock chart in a React application using SciChart.js. The chart allows users to draw custom line annotations and trade markers on a candlestick chart, with the capability to save and reload the entire chart configuration including data and annotations.

Technical Implementation

The implementation leverages React by integrating the <SciChartReact/> component for asynchronous chart initialization. The chart is configured in an async function that returns both the SciChartSurface and control functions for saving, resetting, and applying chart definitions in JSON. Users interact with the chart through custom modifiers such as CreateLineAnnotationModifier and CreateTradeMarkerModifier, which handle mouse events for drawing and editing annotations. Material UI components like ToggleButtonGroup, TextField, Button, and Select are used to manage chart modes (pan, line, marker) and to persist chart state in localStorage. Developers can learn more about setting up and managing asynchronous chart components in React from the Creating a SciChart React Component from the Ground Up guide.

Features and Capabilities

The example supports interactivity with features including:

  • Custom Annotations: Users can draw editable line annotations and trade markers via custom modifiers.
  • Data Streaming and Moving Averages: The chart renders candlestick series with moving averages calculated through SciChart's filters.
  • State Serialization: The entire chart state, including annotations and data, can be saved to and loaded from JSON definitions, ensuring persistence between sessions.

Integration and Best Practices

The example follows best practices for React integration by using hooks such as useRef and useEffect to manage asynchronous initialization and to store mutable chart control objects effectively. Material UI is seamlessly integrated for UI controls, with components such as ToggleButtonGroup managing chart mode toggling following guidelines from the MUI Toggle Button Group documentation. Moreover, localStorage is utilized for chart state persistence, aligning with practices discussed in working with React useEffect & local storage. The integration of custom chart modifiers within the React lifecycle demonstrates efficient state updates and performance optimization techniques for interactive data visualization.

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 Multi-Pane Stock Chart | View JavaScript Charts

React Multi-Pane Stock Charts using Sync Multi-Chart

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

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

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