{
  "$schema": "https://ai.syncfusion.com/schema/registry-item.json",
  "name": "chart-live-stock-data",
  "framework": "angular",
  "type": "registry:component",
  "component": "Chart",
  "variant": "live-stock-data",
  "dependencies": [
    "@syncfusion/ej2-angular-charts"
  ],
  "description": "Real-time Candlestick chart streaming live AAPL OHLC ticks with crosshair and last-value label.",
  "meta": {
    "essentialStudioRelease": "2026 Volume 2 (v34.1.29)",
    "license": "commercial-or-community",
    "licenseNote": "The Syncfusion package is licensed. The composition in this file is source you own and edit. See https://ai.syncfusion.com/licensing.md",
    "requiresLicenseKey": true,
    "requiresServerEndpoint": false,
    "platformIndex": "https://ai.syncfusion.com/angular/llms.txt",
    "skillPack": "syncfusion/angular-ui-components-skills",
    "docs": "https://ai.syncfusion.com/gallery/angular/chart-live-stock-data.md"
  },
  "files": [
    {
      "target": "src/components/chart-live-stock-data/live-stock-data.component.ts",
      "content": "import { Component, OnDestroy, ViewEncapsulation } from '@angular/core';\nimport { ILoadedEventArgs, IAxisRangeCalculatedEventArgs, LastValueLabel, ChartTheme, ChartAllModule, Series } from '@syncfusion/ej2-angular-charts';\nimport { Browser } from '@syncfusion/ej2-base';\nimport { loadChartTheme } from '../theme-color';\n/**\n * Sample for Spline Series\n */\n@Component({\n    selector: 'control-content',\n    templateUrl: 'live-stock-data.html',\n    encapsulation: ViewEncapsulation.None,\n    standalone: true,\n    imports: [ ChartAllModule]\n})\nexport class LiveStockDataComponent implements OnDestroy {\n    public chartArea: Object = {\n        border: {\n            width: 0\n        }\n    };\n    public width: string = Browser.isDevice ? '100%' : '90%';\n    //Initializing Primary X Axis\n    public primaryXAxis: Object = {\n        valueType: 'DateTime', \n        interval: Browser.isDevice ? 8 : 4, \n        crosshairTooltip: { enable: true }, \n        edgeLabelPlacement: Browser.isDevice ? 'None' : 'Shift',\n        majorGridLines: { width: 0 },\n        labelIntersectAction: 'Hide'\n    };\n    //Initializing Primary Y Axis\n    public primaryYAxis: Object = {\n        interval: 20, \n        opposedPosition: true, \n        minimum: 120, \n        crosshairTooltip: { enable: true }, \n        lineStyle: { width: 0 },\n        majorGridLines: { width: 1 }, \n        majorTickLines: { width: 0 }\n    };\n    public lastValueLabel: Object = { enable: true, background: 'red', dashArray: '3,2', lineWidth: 0.5, font: {size: '10px'} };\n    public getData = (): { series: Candlestick[] } => {\n        let value: number = 180;\n        let series: Candlestick[] = [];\n        let point: Candlestick;\n        for (let i: number = 0; i < 30; i++) {\n        value = 180 + (Math.random() * 25) * Math.sin(i * Math.PI / 8); // Adjust the function as needed\n        value = Math.max(140, Math.min(260, value));\n        if (value > 260) {\n            value = 260;\n        }\n        if (value < 140) {\n            value = 140;\n        }\n        value += Math.random() * 0.1;\n            let open: number = value + Math.round(Math.random() * 18);\n            let low: number = Math.min(value, open) - Math.round(Math.random() * 6);\n            let high: number = Math.min(220, Math.max(value, open) + Math.round(Math.random() * 15));\n            point = {\n                x: new Date(2000, 5, 2, 2, 0, i),\n                close: value,\n                open: open,\n                low: low,\n                high: high\n            };\n            series.push(point);\n        }\n        return { series: series };\n    };\n    public data: Candlestick[] = this.getData().series;\n    public updateVal: number = this.data.length;\n    public incVal: number = 0;\n    public pointAdded: boolean = false;\n    private intervalId: any;\n    public load(args: ILoadedEventArgs): void {\n        loadChartTheme(args);\n        const chart: LiveStockDataComponent = this;\n        this.clearInterval(); // Clear any existing interval\n        this.intervalId = setInterval(function () {\n            var container = document.getElementById('stock');\n            if (container && container.id === args.chart.element.id) {\n                let newData1: Candlestick[] = [];\n                let value: number = 180;\n                chart.pointAdded = true;\n                const dataSource : Candlestick[] = args.chart.series[0].dataSource as Candlestick[];\n                for (let i: number = 0; i < dataSource.length; i++) {\n                    newData1.push(Object.assign({}, dataSource[i]));\n                }\n                if (newData1.length > 0) {\n                    const lastIndex: number = newData1.length - 1;\n                    const previousClose: number = newData1[lastIndex].close;\n                    newData1[lastIndex].close += (Math.random() < 0.5 ? 1 : -1) * Math.random() * 25;\n                    newData1[lastIndex].close = Math.min(Math.min(Math.max(newData1[lastIndex].close, newData1[lastIndex].low + 5), newData1[lastIndex].high - 5), newData1[lastIndex].open - 2);\n                    if (previousClose === newData1[lastIndex].close) {\n                        newData1[lastIndex].close -= 5;\n                    }\n                }\n                if (chart.incVal < 10) {\n                    if (args.chart.series.length > 0) {\n                        args.chart.series[0]!.setData!(newData1);\n                        chart.incVal++;\n                    }\n                }\n                else {\n                    let change: number = (Math.random() < 0.49 ? 1 : -1) * Math.random() * 10;\n                    value += change;\n                    if (value > 260) {\n                        value = 260;\n                    }\n                    if (value < 140) {\n                        value = 140;\n                    }\n                    value += Math.random() * 0.1;\n                    let open: number = value + Math.round(Math.random() * 12);\n                    let low: number = Math.min(value, open) - Math.round(Math.random() * 8);\n                    let high: number = Math.max(value, open) + Math.round(Math.random() * 15);\n                    if (args.chart.series.length > 0) {\n                        const dataSource = args.chart.series[0]!.dataSource as Candlestick[];\n                        var lastDataPointIndex = dataSource.length - 1;\n                        if (lastDataPointIndex >= 0) {\n                            var timestamp = dataSource[lastDataPointIndex].x;\n                            var lastTimestamp = new Date(timestamp).getTime();\n                            args.chart.series[0]!.addPoint!({ x: new Date(lastTimestamp + 1000), high: high, low: low, open: open, close: value });\n                        }\n                    }\n                    chart.incVal = 0;\n                    chart.updateVal++;\n                }\n            } else {\n                chart.clearInterval();\n            }\n        }, 1000);\n    };\n\n    private clearInterval(): void {\n        if (this.intervalId) {\n            clearInterval(this.intervalId);\n            this.intervalId = null;\n        }\n    }\n \n    public axisRangeCalculated (args: IAxisRangeCalculatedEventArgs): void {\n        if (args.axis.name === 'primaryXAxis') {\n            let lastPoint: Object = args.axis.series[0].points[args.axis.series[0].points.length - 1].x;\n            args.maximum = new Date(Number(lastPoint)).getTime() + 2500;\n            let firstPoint: Object = args.axis.series[0].points[0].x;\n            args.minimum = new Date(Number(firstPoint)).getTime() + 500;\n        }\n    }\n    public pointRender (args: any): void {\n        args.series.lastValueLabel.background = args.fill;\n    };\n    public title: string = 'AAPL Historical';\n    public crosshair: Object = { enable: true, dashArray: '5,5' };\n    constructor() {\n        //code\n    };\n    ngOnDestroy(): void {\n        this.clearInterval();\n    }\n}\ninterface Candlestick {\n    open: number;\n    close: number;\n    high: number;\n    low: number;\n    x: Date;\n}"
    },
    {
      "target": "src/components/chart-live-stock-data/live-stock-data.html",
      "content": "\n<div class=\"control-section\">\n    <div align='center'>\n        <ejs-chart id='stock' align='center' [chartArea]='chartArea' [width]='width' style='display:block;' [primaryXAxis]='primaryXAxis'\n            [primaryYAxis]='primaryYAxis' (load)='load($event)' (pointRender)='pointRender($event)' (axisRangeCalculated)='axisRangeCalculated($event)' \n            [title]='title' [crosshair]='crosshair'>\n            <e-series-collection>\n                <e-series [dataSource]='data' type='Candle' xName='x' low='low' high='high' open='open' close='close' columnWidth=0.4 bearFillColor='#2ecd71' bullFillColor='#e74c3d' [lastValueLabel]='lastValueLabel'> </e-series>\n            </e-series-collection>\n        </ejs-chart>\n    </div>\n</div>\n\n\n<style>\n    #control-container {\n        padding: 0px !important;\n    }\n</style>"
    }
  ]
}