DevExtreme v24.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Angular Charts - Candlestick

The Candlestick financial chart is designed to communicate trading patterns over a short period of time. A single data point on a Candlestick series displays variations in stock prices over the course of a day.

You can use the Candlestick type for an individual series or specify the type in the commonSeriesSettings object for all series in the Chart. Use the commonSeriesSettings.candlestick object to configure properties of the Chart Candlestick series.

Backend API
<dx-chart id="chart" title="Stock Price" [dataSource]="stockPrices"> <dxi-series name="E-Mart" openValueField="o" highValueField="h" lowValueField="l" closeValueField="c" > <dxo-reduction color="red"></dxo-reduction> </dxi-series> <dxo-common-series-settings argumentField="date" type="candlestick"> </dxo-common-series-settings> <dxo-legend itemTextPosition="left"></dxo-legend> <dxi-value-axis [tickInterval]="1"> <dxo-title text="US dollars"></dxo-title> <dxo-label> <dxo-format type="currency" [precision]="0"> </dxo-format> </dxo-label> </dxi-value-axis> <dxo-argument-axis [workdaysOnly]="true"> <dxo-label format="shortDate"></dxo-label> </dxo-argument-axis> <dxo-export [enabled]="true"></dxo-export> <dxo-tooltip [enabled]="true" location="edge" [customizeTooltip]="customizeTooltip" > </dxo-tooltip> </dx-chart>
import { NgModule, Component, enableProdMode } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { DxChartModule } from 'devextreme-angular'; import { StockPrice, Service } from './app.service'; if (!/localhost/.test(document.location.host)) { enableProdMode(); } @Component({ selector: 'demo-app', templateUrl: `app/app.component.html`, styleUrls: [`app/app.component.css`], providers: [Service], }) export class AppComponent { stockPrices: StockPrice[]; constructor(service: Service) { this.stockPrices = service.getStockPrices(); } customizeTooltip(arg) { return { text: `Open: $${arg.openValue}<br/>` + `Close: $${arg.closeValue}<br/>` + `High: $${arg.highValue}<br/>` + `Low: $${arg.lowValue}<br/>`, }; } } @NgModule({ imports: [ BrowserModule, DxChartModule, ], declarations: [AppComponent], bootstrap: [AppComponent], }) export class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule);
::ng-deep #chart { height: 440px; }
import { Injectable } from '@angular/core'; export class StockPrice { date: Date; l: number; h: number; o: number; c: number; } const stockPrices: StockPrice[] = [{ date: new Date(1994, 2, 1), l: 24.00, h: 25.00, o: 25.00, c: 24.875, }, { date: new Date(1994, 2, 2), l: 23.625, h: 25.125, o: 24.00, c: 24.875, }, { date: new Date(1994, 2, 3), l: 26.25, h: 28.25, o: 26.75, c: 27.00, }, { date: new Date(1994, 2, 4), l: 26.50, h: 27.875, o: 26.875, c: 27.25, }, { date: new Date(1994, 2, 7), l: 26.375, h: 27.50, o: 27.375, c: 26.75, }, { date: new Date(1994, 2, 8), l: 25.75, h: 26.875, o: 26.75, c: 26.00, }, { date: new Date(1994, 2, 9), l: 25.75, h: 26.75, o: 26.125, c: 26.25, }, { date: new Date(1994, 2, 10), l: 25.75, h: 26.375, o: 26.375, c: 25.875, }, { date: new Date(1994, 2, 11), l: 24.875, h: 26.125, o: 26.00, c: 25.375, }, { date: new Date(1994, 2, 14), l: 25.125, h: 26.00, o: 25.625, c: 25.75, }, { date: new Date(1994, 2, 15), l: 25.875, h: 26.625, o: 26.125, c: 26.375, }, { date: new Date(1994, 2, 16), l: 26.25, h: 27.375, o: 26.25, c: 27.25, }, { date: new Date(1994, 2, 17), l: 26.875, h: 27.25, o: 27.125, c: 26.875, }, { date: new Date(1994, 2, 18), l: 26.375, h: 27.125, o: 27.00, c: 27.125, }, { date: new Date(1994, 2, 21), l: 26.75, h: 27.875, o: 26.875, c: 27.75, }, { date: new Date(1994, 2, 22), l: 26.75, h: 28.375, o: 27.50, c: 27.00, }, { date: new Date(1994, 2, 23), l: 26.875, h: 28.125, o: 27.00, c: 28.00, }, { date: new Date(1994, 2, 24), l: 26.25, h: 27.875, o: 27.75, c: 27.625, }, { date: new Date(1994, 2, 25), l: 27.50, h: 28.75, o: 27.75, c: 28.00, }, { date: new Date(1994, 2, 28), l: 25.75, h: 28.25, o: 28.00, c: 27.25, }, { date: new Date(1994, 2, 29), l: 26.375, h: 27.50, o: 27.50, c: 26.875, }, { date: new Date(1994, 2, 30), l: 25.75, h: 27.50, o: 26.375, c: 26.25, }, { date: new Date(1994, 2, 31), l: 24.75, h: 27.00, o: 26.50, c: 25.25, }]; @Injectable() export class Service { getStockPrices(): StockPrice[] { return stockPrices; } }
// In real applications, you should not transpile code in the browser. // You can see how to create your own application with Angular and DevExtreme here: // https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started/Create_a_DevExtreme_Application/ const componentNames = [ 'accordion', 'action-sheet', 'autocomplete', 'bar-gauge', 'box', 'bullet', 'button-group', 'button', 'calendar', 'chart', 'chat', 'check-box', 'circular-gauge', 'color-box', 'context-menu', 'data-grid', 'date-box', 'date-range-box', 'defer-rendering', 'diagram', 'draggable', 'drawer', 'drop-down-box', 'drop-down-button', 'file-manager', 'file-uploader', 'filter-builder', 'form', 'funnel', 'gallery', 'gantt', 'html-editor', 'linear-gauge', 'list', 'load-indicator', 'load-panel', 'lookup', 'map', 'menu', 'multi-view', 'nested', 'number-box', 'pagination', 'pie-chart', 'pivot-grid-field-chooser', 'pivot-grid', 'polar-chart', 'popover', 'popup', 'progress-bar', 'radio-group', 'range-selector', 'range-slider', 'recurrence-editor', 'resizable', 'responsive-box', 'sankey', 'scheduler', 'scroll-view', 'select-box', 'slider', 'sortable', 'sparkline', 'speed-dial-action', 'splitter', 'switch', 'tab-panel', 'tabs', 'tag-box', 'text-area', 'text-box', 'tile-view', 'toast', 'toolbar', 'tooltip', 'tree-list', 'tree-map', 'tree-view', 'validation-group', 'validation-summary', 'validator', 'vector-map', ]; window.exports = window.exports || {}; window.config = { transpiler: 'ts', typescriptOptions: { module: 'system', emitDecoratorMetadata: true, experimentalDecorators: true, }, meta: { 'typescript': { 'exports': 'ts', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, '@angular/platform-browser-dynamic': { 'esModule': true, }, '@angular/platform-browser': { 'esModule': true, }, '@angular/core': { 'esModule': true, }, '@angular/common': { 'esModule': true, }, '@angular/common/http': { 'esModule': true, }, '@angular/animations': { 'esModule': true, }, '@angular/forms': { 'esModule': true, }, 'openai': { 'esModule': true, }, }, paths: { 'npm:': 'https://unpkg.com/', 'bundles:': '../../../../bundles/', 'externals:': '../../../../bundles/externals/', }, map: { 'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js', 'typescript': 'npm:typescript@4.2.4/lib/typescript.js', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', /* @angular */ '@angular/compiler': 'bundles:@angular/compiler.umd.js', '@angular/platform-browser-dynamic': 'bundles:@angular/platform-browser-dynamic.umd.js', '@angular/core': 'bundles:@angular/core.umd.js', '@angular/core/primitives/signals': 'bundles:@angular/core.primitives.signals.umd.js', '@angular/common': 'bundles:@angular/common.umd.js', '@angular/common/http': 'bundles:@angular/common-http.umd.js', '@angular/platform-browser': 'bundles:@angular/platform-browser.umd.js', '@angular/platform-browser/animations': 'bundles:@angular/platform-browser.umd.js', '@angular/forms': 'bundles:@angular/forms.umd.js', /* devextreme */ 'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12', 'devextreme/bundles/dx.all': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/bundles/dx.all.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.5', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.54', /* devextreme-angular umd maps */ 'devextreme-angular': 'bundles:devextreme-angular/devextreme-angular.umd.js', 'devextreme-angular/core': 'bundles:devextreme-angular/devextreme-angular-core.umd.js', 'devextreme-angular/http': 'bundles:devextreme-angular/devextreme-angular-http.umd.js', ...componentNames.reduce((acc, name) => { acc[`devextreme-angular/ui/${name}`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}.umd.js`; acc[`devextreme-angular/ui/${name}/nested`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}-nested.umd.js`; return acc; }, {}), 'tslib': 'npm:tslib/tslib.js', 'rxjs': 'npm:rxjs@7.5.3/dist/bundles/rxjs.umd.js', 'rxjs/operators': 'npm:rxjs@7.5.3/dist/cjs/operators/index.js', 'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js', 'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign', 'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js', 'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js', 'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js', 'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js', 'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js', 'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js', 'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js', 'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js', // Prettier 'prettier/standalone': 'npm:prettier@2.8.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js', }, packages: { 'app': { main: './app.component.ts', defaultExtension: 'ts', }, 'devextreme': { defaultExtension: 'js', }, 'devextreme/events/utils': { main: 'index', }, 'devextreme/events': { main: 'index', }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js', }, 'rxjs': { defaultExtension: 'js', }, 'rxjs/operators': { defaultExtension: 'js', }, }, packageConfigPaths: [ 'npm:@devextreme/*/package.json', 'npm:@devextreme/runtime@3.0.12/inferno/package.json', 'npm:rxjs@7.5.3/package.json', 'npm:rxjs@7.5.3/operators/package.json', 'npm:devexpress-diagram@2.2.5/package.json', 'npm:devexpress-gantt@4.1.54/package.json', ], }; System.config(window.config); // System.import('@angular/compiler').catch(console.error.bind(console));
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/24.2.3/css/dx.light.css" /> <script src="https://unpkg.com/core-js@2.6.12/client/shim.min.js"></script> <script src="https://unpkg.com/zone.js@0.14.10/bundles/zone.umd.js"></script> <script src="https://unpkg.com/reflect-metadata@0.1.13/Reflect.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script src="config.js"></script> <script> System.import("app").catch(console.error.bind(console)); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <demo-app>Loading...</demo-app> </div> </body> </html>

In Candlestick series, each point consists of a rectangle (body) and a vertical line (shadow, wick, or tail). The top and bottom values of a vertical line correspond to the highest and lowest prices of the stock, respectively. Use the highValueField and lowValueField properties to specify data source fields for these prices.

The bottom and topmost values of the point's body correspond to the opening and closing price of a stock. To specify these prices, use the openValueField and closeValueField properties. If the stock closes higher than its opening price, no color fills the body; if the stock closes lower than its opening price, the Chart applies a color fill to the body.

To reflect changes on the market, the Chart component compares the price of every point with the price of the previous point. The Chart paints the points whose price has decreased in a specific reduction color. To change color of other points, use the series.color property; you can also specify the series.innerColor property to fill these points' bodies with color. To switch between high, low, open, or close prices of points as sources for data comparison, use the series.reduction.level property.

Apply the following settings to make your chart more user-friendly: