Tenor Curves Demo

In financial applications sometimes you want to visualise options-volatility smiles or interest-rate swap tenor curves. This can be done in SciChart.js using a 3D Surface Mesh (heightmap) chart type.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

angular.ts

theme.ts

TenorCurveData.ts

Copy to clipboard
Minimise
Fullscreen
1import { appTheme } from "../../../theme";
2import { getTenorCurveData } from "./TenorCurveData";
3import {
4    EllipsePointMarker,
5    FastMountainRenderableSeries,
6    IDeletable,
7    NumericAxis,
8    NumberRange,
9    Point,
10    SciChartSurface,
11    XyDataSeries,
12    CameraController,
13    EDrawMeshAs,
14    EMeshPaletteMode,
15    GradientColorPalette,
16    HeatmapLegend,
17    MouseWheelZoomModifier3D,
18    NumericAxis3D,
19    OrbitModifier3D,
20    ResetCamera3DModifier,
21    SciChart3DSurface,
22    SurfaceMeshRenderableSeries3D,
23    UniformGridDataSeries3D,
24    Vector3,
25} from "scichart";
26
27const X_DATA_SIZE = 25;
28const Z_DATA_SIZE = 25;
29
30export const draw3DChart = async (rootElement: string | HTMLDivElement) => {
31    // Create the 3d chart
32    const { sciChart3DSurface, wasmContext } = await SciChart3DSurface.create(rootElement, {
33        theme: appTheme.SciChartJsTheme,
34    });
35
36    // Create camerea, position, field of view
37    sciChart3DSurface.camera = new CameraController(wasmContext, {
38        position: new Vector3(-225, 300, -225),
39        target: new Vector3(0, 50, 0),
40    });
41    sciChart3DSurface.camera.aspectRatio = 1.333;
42    sciChart3DSurface.camera.fieldOfView = 45;
43
44    // World dimensions specifies size of the axis cube box
45    sciChart3DSurface.worldDimensions = new Vector3(200, 200, 200);
46
47    // Add X.Y,Z axis
48    sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, { axisTitle: "X Axis" });
49    sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, { axisTitle: "Y Axis" });
50    sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, { axisTitle: "Z Axis" });
51
52    // Add optional interaction modifiers (mousewheel and orbit via mouse drag)
53    sciChart3DSurface.chartModifiers.add(new MouseWheelZoomModifier3D());
54    sciChart3DSurface.chartModifiers.add(new OrbitModifier3D());
55    sciChart3DSurface.chartModifiers.add(new ResetCamera3DModifier());
56
57    // returns data for the example. UniformGridDataSeries3D expects number[][] 2D Array
58    // filled with values. The values are heights (y-values) on the 3d chart and
59    // are mapped to colors via a colorMap
60    const tenorCurvesData = getTenorCurveData(X_DATA_SIZE, Z_DATA_SIZE);
61
62    // Create the DataSeries for the 3d chart
63    const dataSeries = new UniformGridDataSeries3D(wasmContext, {
64        yValues: tenorCurvesData,
65        xStep: 1,
66        zStep: 1,
67        dataSeriesName: "Uniform Surface Mesh",
68    });
69
70    // Create a color map. Color at offset=0 is mapped to y-value at SurfaceMeshRenderableSeries3D.minimum
71    // color at offset = 1 is mapped to y-value at SurfaceMeshRenderableSeries3D.maximum
72    const colorMap = new GradientColorPalette(wasmContext, {
73        gradientStops: [
74            { offset: 1, color: appTheme.VividPink },
75            { offset: 0.9, color: appTheme.VividOrange },
76            { offset: 0.7, color: appTheme.MutedRed },
77            { offset: 0.5, color: appTheme.VividGreen },
78            { offset: 0.3, color: appTheme.VividSkyBlue },
79            { offset: 0.2, color: appTheme.Indigo },
80            { offset: 0, color: appTheme.DarkIndigo },
81        ],
82    });
83
84    const series = new SurfaceMeshRenderableSeries3D(wasmContext, {
85        dataSeries,
86        minimum: 1,
87        maximum: 100,
88        opacity: 1.0,
89        cellHardnessFactor: 1,
90        shininess: 0,
91        lightingFactor: 0.8,
92        highlight: 0.05,
93        stroke: appTheme.VividSkyBlue + "33",
94        strokeThickness: 1.5,
95        drawSkirt: false,
96        drawMeshAs: EDrawMeshAs.SOLID_WIREFRAME,
97        meshPaletteMode: EMeshPaletteMode.HEIGHT_MAP_INTERPOLATED,
98        meshColorPalette: colorMap,
99    });
100    sciChart3DSurface.renderableSeries.add(series);
101
102    return { sciChartSurface: sciChart3DSurface };
103};
104
105export const drawLineChart1 = async (rootElement: string | HTMLDivElement) => {
106    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
107        theme: appTheme.SciChartJsTheme,
108    });
109    const xAxis = new NumericAxis(wasmContext);
110    sciChartSurface.xAxes.add(xAxis);
111
112    const yAxis = new NumericAxis(wasmContext, { growBy: new NumberRange(0.05, 0.05) });
113    sciChartSurface.yAxes.add(yAxis);
114
115    // xAxis.isVisible = false;
116    // yAxis.isVisible = false;
117
118    const mountainSeries = new FastMountainRenderableSeries(wasmContext, {
119        stroke: appTheme.VividSkyBlue,
120        strokeThickness: 3,
121        pointMarker: new EllipsePointMarker(wasmContext, {
122            width: 9,
123            height: 9,
124            stroke: appTheme.VividSkyBlue,
125            strokeThickness: 2,
126            fill: appTheme.ForegroundColor,
127        }),
128        fillLinearGradient: {
129            startPoint: new Point(0, 0),
130            endPoint: new Point(0, 1),
131            gradientStops: [
132                { offset: 0, color: appTheme.VividSkyBlue },
133                { offset: 1, color: "Transparent" },
134            ],
135        },
136    });
137    sciChartSurface.renderableSeries.add(mountainSeries);
138
139    const dataSeries = new XyDataSeries(wasmContext);
140    const tenorCurvesData = getTenorCurveData(X_DATA_SIZE, Z_DATA_SIZE);
141    let average: number;
142    for (let z = 0; z < Z_DATA_SIZE; z++) {
143        average = 0;
144        for (let x = 0; x < X_DATA_SIZE; x++) {
145            average += tenorCurvesData[x][z];
146        }
147        dataSeries.append(z, average / X_DATA_SIZE);
148    }
149    mountainSeries.dataSeries = dataSeries;
150
151    return { sciChartSurface };
152};
153
154export const drawLineChart2 = async (rootElement: string | HTMLDivElement) => {
155    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement, {
156        theme: appTheme.SciChartJsTheme,
157    });
158
159    const xAxis = new NumericAxis(wasmContext);
160    sciChartSurface.xAxes.add(xAxis);
161
162    const yAxis = new NumericAxis(wasmContext, { growBy: new NumberRange(0.05, 0.05) });
163    sciChartSurface.yAxes.add(yAxis);
164    // xAxis.isVisible = false;
165    // yAxis.isVisible = false;
166
167    const mountainSeries = new FastMountainRenderableSeries(wasmContext, {
168        stroke: appTheme.PaleSkyBlue,
169        strokeThickness: 5,
170        fillLinearGradient: {
171            startPoint: new Point(0, 0),
172            endPoint: new Point(0, 1),
173            gradientStops: [
174                { offset: 0, color: appTheme.VividTeal },
175                { offset: 1, color: "Transparent" },
176            ],
177        },
178        pointMarker: new EllipsePointMarker(wasmContext, {
179            width: 9,
180            height: 9,
181            stroke: appTheme.PaleSkyBlue,
182            strokeThickness: 2,
183            fill: appTheme.ForegroundColor,
184        }),
185    });
186    sciChartSurface.renderableSeries.add(mountainSeries);
187
188    const dataSeries = new XyDataSeries(wasmContext);
189    const tenorCurvesData = getTenorCurveData(X_DATA_SIZE, Z_DATA_SIZE);
190    const zMiddleIndex = Math.floor(Z_DATA_SIZE / 2);
191    for (let x = 0; x < Z_DATA_SIZE; x++) {
192        dataSeries.append(x, tenorCurvesData[x][zMiddleIndex]);
193    }
194    mountainSeries.dataSeries = dataSeries;
195
196    return { sciChartSurface };
197};
198
199export const drawHeatmapLegend = async (rootElement: string | HTMLDivElement) => {
200    const { heatmapLegend, wasmContext } = await HeatmapLegend.create(rootElement, {
201        theme: {
202            ...appTheme.SciChartJsTheme,
203            sciChartBackground: appTheme.DarkIndigo + "BB",
204            loadingAnimationBackground: appTheme.DarkIndigo + "BB",
205        },
206        yAxisOptions: {
207            isInnerAxis: true,
208            labelStyle: {
209                fontSize: 12,
210                color: appTheme.ForegroundColor,
211            },
212            axisBorder: {
213                borderRight: 1,
214                color: appTheme.ForegroundColor + "77",
215            },
216            majorTickLineStyle: {
217                color: appTheme.ForegroundColor,
218                tickSize: 6,
219                strokeThickness: 1,
220            },
221            minorTickLineStyle: {
222                color: appTheme.ForegroundColor,
223                tickSize: 3,
224                strokeThickness: 1,
225            },
226        },
227        colorMap: {
228            minimum: 0,
229            maximum: 200,
230            gradientStops: [
231                { offset: 1, color: appTheme.VividPink },
232                { offset: 0.9, color: appTheme.VividOrange },
233                { offset: 0.7, color: appTheme.MutedRed },
234                { offset: 0.5, color: appTheme.VividGreen },
235                { offset: 0.3, color: appTheme.VividSkyBlue },
236                { offset: 0.2, color: appTheme.Indigo },
237                { offset: 0, color: appTheme.DarkIndigo },
238            ],
239        },
240    });
241
242    return { sciChartSurface: heatmapLegend.innerSciChartSurface.sciChartSurface };
243};
244

Tenor Curves Demo 3D with Angular

Overview

This example demonstrates a composite chart layout built with Angular where a 3D surface mesh is combined with two 2D line charts and an integrated heatmap legend. The application is designed to visualize financial data, such as tenor curves, by leveraging the power of SciChart.js. The charts are embedded inside Angular standalone components using the scichart-angular package.

Technical Implementation

The implementation uses asynchronous initialization for each chart through dedicated functions like draw3DChart, drawLineChart1, drawLineChart2 and drawHeatmapLegend. These functions are passed to the Angular component through input bindings, ensuring that each chart initializes independently when its WebAssembly context becomes available. For detailed guidance on asynchronous chart initialization, refer to Getting Started with SciChart JS. The code configures camera settings, axis definitions, rendering series, and color mapping to render the charts efficiently.

Features and Capabilities

The example integrates multiple advanced features:

  • A 3D Surface Mesh chart that uses a height map generated from tenor curve data with custom gradient color palettes. This is aligned with the guidelines provided in the SciChart.js 3D Surface Mesh Documentation.
  • Two 2D Mountain Charts which aggregate and present slice data from the underlying dataset.
  • An integrated Heatmap Legend is employed to visually correlate the color gradient with data values, adding clarity to the 3D visualization.

Integration and Best Practices

The charts are rendered within Angular's standalone components using input bindings, demonstrating best practices in Angular component integration. Developers can refer to the Angular Responsive Design: Complete Guide for strategies that ensure the charts and layouts remain adaptive across devices. Additionally, the composite layout strategy, which integrates several chart components in a single view, follows robust practices for managing multiple WebGL contexts in Angular applications. For further insights on composite layout strategies, the 3D Tutorial 01 - Setting up a 3D Chart Project with SciChart.js provides valuable context.

The approach in this example emphasizes performance optimizations by isolating the chart initialization logic and reducing overlapping WebGL contexts, ensuring smooth and responsive interactions. This makes it an ideal reference for Angular developers looking to build real-time, composite data visualizations with SciChart.js.

angular Chart Examples & Demos

See Also: Financial Charts (9 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.

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

Angular Multi-Pane Stock Chart | View JavaScript Charts

Angular Multi-Pane Stock Charts using Sync Multi-Chart

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

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.

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