UNPKG

highcharts

Version:
1,437 lines (1,409 loc) 370 kB
// SPDX-License-Identifier: LicenseRef-Highcharts /** * @license Highstock JS v13.0.1 (2026-08-17) * @module highcharts/indicators/indicators-all * @requires highcharts * @requires highcharts/modules/stock * * All technical indicators for Highcharts Stock * * (c) 2010-2026 Highsoft AS * Author: Paweł Fus * * A commercial license may be required depending on use, * see www.highcharts.com/license */ import * as __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__ from "../highcharts.src.js"; import * as __WEBPACK_EXTERNAL_MODULE__modules_datagrouping_src_js_b7a4250c__ from "../modules/datagrouping.src.js"; /******/ // The require scope /******/ const __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ const getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter/value functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ if(Array.isArray(definition)) { /******/ var i = 0; /******/ while(i < definition.length) { /******/ var key = definition[i++]; /******/ var binding = definition[i++]; /******/ if(!__webpack_require__.o(exports, key)) { /******/ if(binding === 0) { /******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] }); /******/ } else { /******/ Object.defineProperty(exports, key, { enumerable: true, get: binding }); /******/ } /******/ } else if(binding === 0) { i++; } /******/ } /******/ } else { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /************************************************************************/ ;// external ["../highcharts.src.js","default"] const external_highcharts_src_js_default_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"]; var external_highcharts_src_js_default_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_namespaceObject); ;// external ["../highcharts.src.js","default","Chart"] const external_highcharts_src_js_default_Chart_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].Chart; var external_highcharts_src_js_default_Chart_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_Chart_namespaceObject); ;// ./code/es-modules/Data/ColumnUtils.js /* * * * (c) 2020-2026 Highsoft AS * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * Authors: * - Dawid Draguła * * */ /* * * * Functions * * */ /** * Sets the length of the column array. * * @param {DataTableColumn} column * Column to be modified. * * @param {number} length * New length of the column. * * @param {boolean} asSubarray * If column is a typed array, return a subarray instead of a new array. It * is faster `O(1)`, but the entire buffer will be kept in memory until all * views of it are destroyed. Default is `false`. * * @return {DataTableColumn} * Modified column. * * @private */ function setLength(column, length, asSubarray) { if (Array.isArray(column)) { column.length = length; return column; } return column[asSubarray ? 'subarray' : 'slice'](0, length); } /** * Splices a column array. * * @param {DataTableColumn} column * Column to be modified. * * @param {number} start * Index at which to start changing the array. * * @param {number} deleteCount * An integer indicating the number of old array elements to remove. * * @param {boolean} removedAsSubarray * If column is a typed array, return a subarray instead of a new array. It * is faster `O(1)`, but the entire buffer will be kept in memory until all * views to it are destroyed. Default is `true`. * * @param {Array<number>|TypedArray} items * The elements to add to the array, beginning at the start index. If you * don't specify any elements, `splice()` will only remove elements from the * array. * * @return {SpliceResult} * Object containing removed elements and the modified column. * * @private */ function splice(column, start, deleteCount, removedAsSubarray, items = []) { if (Array.isArray(column)) { if (!Array.isArray(items)) { items = Array.from(items); } return { removed: column.splice(start, deleteCount, ...items), array: column }; } const Constructor = Object.getPrototypeOf(column) .constructor; const removed = column[removedAsSubarray ? 'subarray' : 'slice'](start, start + deleteCount); const newLength = column.length - deleteCount + items.length; const result = new Constructor(newLength); result.set(column.subarray(0, start), 0); result.set(items, start); result.set(column.subarray(start + deleteCount), start + items.length); return { removed: removed, array: result }; } /** * Converts a cell value to a number. * * @param {DataTableCellType} value * Cell value to convert to a number. * * @param {boolean} useNaN * If `true`, returns `NaN` for non-numeric values; if `false`, * returns `null` instead. * * @return {number | null} * Number or `null` if the value is not a number. * * @private */ function convertToNumber(value, useNaN) { switch (typeof value) { case 'boolean': return (value ? 1 : 0); case 'number': return (isNaN(value) && !useNaN ? null : value); default: value = parseFloat(`${value ?? ''}`); return (isNaN(value) && !useNaN ? null : value); } } /* * * * Default Export * * */ const ColumnUtils = { convertToNumber, setLength, splice }; /* harmony default export */ const Data_ColumnUtils = (ColumnUtils); ;// ./code/es-modules/Data/DataTableCore.js /* * * * (c) 2009-2026 Highsoft AS * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * Authors: * - Sophie Bremer * - Gøran Slettemark * - Torstein Hønsi * * */ const { setLength: DataTableCore_setLength, splice: DataTableCore_splice } = Data_ColumnUtils; /* * * * Class * * */ /** * Class to manage columns and rows in a table structure. It provides methods * to add, remove, and manipulate columns and rows, as well as to retrieve data * from specific cells. * * Highcharts allows passing a `DataTable` or a configuration object for a data * table in the `dataTable` property, either chart-level * [dataTable](https://api.highcharts.com/highcharts/dataTable) or as * [series.dataTable](https://api.highcharts.com/highcharts/series.dataTable). * The `DataTable` is then used as a source for the series data points, mapped * by the `series.dataMapping` option. * * After chart instantiation, the data table can be accessed from the series as * `series.dataTable`. CRUD operations on the data table will be reflected in * the chart. * * @example * const dataTable = new Highcharts.DataTable({ * columns: { * year: [2020, 2021, 2022, 2023], * cost: [11, 13, 12, 14], * revenue: [12, 15, 14, 18] * } * }); * * @class * @name Highcharts.DataTable * * @param {Highcharts.DataTableOptionsObject} [options] * Options to initialize the new DataTable instance. */ class DataTableCore { constructor(options = {}) { this.isDataTable = true; this.autoId = !options.id; this.columns = {}; this.id = (options.id || (0,external_highcharts_src_js_default_namespaceObject.uniqueKey)()); this.rowCount = 0; this.versionTag = (0,external_highcharts_src_js_default_namespaceObject.uniqueKey)(); let rowCount = 0; (0,external_highcharts_src_js_default_namespaceObject.objectEach)(options.columns || {}, (column, columnId) => { this.columns[columnId] = column.slice(); rowCount = Math.max(rowCount, column.length); }); this.applyRowCount(rowCount); } /* * * * Functions * * */ /** * Applies a row count to the table by setting the `rowCount` property and * adjusting the length of all columns. * * @private * @param {number} rowCount The new row count. */ applyRowCount(rowCount) { this.rowCount = rowCount; (0,external_highcharts_src_js_default_namespaceObject.objectEach)(this.columns, (column, columnId) => { if (column.length !== rowCount) { this.columns[columnId] = DataTableCore_setLength(column, rowCount); } }); } /** * Delete rows. Simplified version of the full * `DataTable.deleteRows` method. * * @sample highcharts/datatable/live-chart/ * Add and delete rows in a live chart * @sample highcharts/datatable/shared-with-grid/ * Chart with data table CRUD operations * * @function Highcharts.DataTable#deleteRows * * @param {number} rowIndex * The start row index * * @param {number} [rowCount=1] * The number of rows to delete * * @return {void} * * @emits #afterDeleteRows */ deleteRows(rowIndex, rowCount = 1) { if (rowCount > 0 && rowIndex < this.rowCount) { let length = 0; (0,external_highcharts_src_js_default_namespaceObject.objectEach)(this.columns, (column, columnId) => { this.columns[columnId] = DataTableCore_splice(column, rowIndex, rowCount).array; length = column.length; }); this.rowCount = length; } (0,external_highcharts_src_js_default_namespaceObject.fireEvent)(this, 'afterDeleteRows', { rowIndex, rowCount }); this.versionTag = (0,external_highcharts_src_js_default_namespaceObject.uniqueKey)(); } /** * Fetches the given column by the canonical column ID. Simplified version * of the full `DataTable.getRow` method, always returning by reference. * * @function Highcharts.DataTable#getColumn * * @param {string} columnId * ID of the column to get. * * @return {Highcharts.DataTableColumn|undefined} * A copy of the column, or `undefined` if not found. */ getColumn(columnId, // eslint-disable-next-line @typescript-eslint/no-unused-vars asReference) { return this.columns[columnId]; } /** * Retrieves all or the given columns. Simplified version of the full * `DataTable.getColumns` method, always returning by reference. * * @function Highcharts.DataTable#getColumns * * @param {Array<string>} [columnIds] * Column ids to retrieve. * * @return {Highcharts.DataTableColumnCollection} * Collection of columns. If a requested column was not found, it is * `undefined`. */ getColumns(columnIds, // eslint-disable-next-line @typescript-eslint/no-unused-vars asReference) { return (columnIds || Object.keys(this.columns)).reduce((columns, columnId) => { columns[columnId] = this.columns[columnId]; return columns; }, {}); } /** * Retrieves the row at a given index. * * @function Highcharts.DataTable#getRowObject * * @param {number} rowIndex * Row index to retrieve. First row has index 0. * * @param {Array<string>} [columnNames] * Column names to retrieve. * * @return {Record<string, number|string|undefined>|undefined} * Returns the row values, or `undefined` if not found. */ getRowObject(rowIndex, columnNames) { const row = {}, columns = this.columns; columnNames ?? (columnNames = Object.keys(this.columns)); for (const columnName of columnNames) { row[columnName] = columns[columnName]?.[rowIndex]; } return row; } /** * Sets cell values for a column. Will insert a new column, if not found. * * @function Highcharts.DataTable#setColumn * * @param {string} columnId * Column name to set. * * @param {Highcharts.DataTableColumn} [column] * Values to set in the column. * * @param {number} [rowIndex] * Index of the first row to change. (Default: 0) * * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail] * Custom information for pending events. * * @emits #setColumns * @emits #afterSetColumns */ setColumn(columnId, column = [], rowIndex = 0, eventDetail) { this.setColumns({ [columnId]: column }, rowIndex, eventDetail); } /** * Sets cell values for multiple columns. Will insert new columns, if not * found. Simplified version of the full `DataTable.setColumns`, limited * to full replacement of the columns (undefined `rowIndex`). * * @sample highcharts/datatable/shared-with-grid/ * Chart with data table CRUD operations * * @function Highcharts.DataTable#setColumns * * @param {Highcharts.DataTableColumnCollection} columns * Columns as a collection, where the keys are the column names. * * @param {number} [rowIndex] * Index of the first row to change. Ignored in the simplified `DataTable`, * as it always replaces the full column. * * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail] * Custom information for pending events. * * @emits #setColumns * @emits #afterSetColumns */ setColumns(columns, rowIndex, eventDetail) { let rowCount = this.rowCount; (0,external_highcharts_src_js_default_namespaceObject.objectEach)(columns, (column, columnId) => { this.columns[columnId] = column.slice(); rowCount = column.length; }); this.applyRowCount(rowCount); if (!eventDetail?.silent) { (0,external_highcharts_src_js_default_namespaceObject.fireEvent)(this, 'afterSetColumns'); this.versionTag = (0,external_highcharts_src_js_default_namespaceObject.uniqueKey)(); } } /** * Sets cell values of a row. Will insert a new row if no index was * provided, or if the index is higher than the total number of table rows. * A simplified version of the full `DateTable.setRow`, limited to objects. * * @sample highcharts/datatable/live-chart/ * Add and delete rows in a live chart * @sample stock/datatable/live-candlestick/ * Live candlestick * @sample highcharts/datatable/shared-with-grid/ * Chart with data table CRUD operations * * @function Highcharts.DataTable#setRow * * @param {Record<string, number|string|undefined>} row * Cell values to set. * * @param {number} [rowIndex] * Index of the row to set. Leave `undefined` to add as a new row. * * @param {boolean} [insert] * Whether to insert the row at the given index, or to overwrite the row. * * @param {Record<string, (boolean|number|string|null|undefined)>} [eventDetail] * Custom information for pending events. * * @emits #afterSetRows */ setRow(row, rowIndex = this.rowCount, insert, eventDetail) { var _a; const { columns } = this, indexRowCount = insert ? this.rowCount + 1 : rowIndex + 1, rowKeys = Object.keys(row); if (eventDetail?.addColumns !== false) { for (let i = 0, iEnd = rowKeys.length; i < iEnd; i++) { columns[_a = rowKeys[i]] || (columns[_a] = new Array(this.rowCount)); } } (0,external_highcharts_src_js_default_namespaceObject.objectEach)(columns, (column, columnId) => { if (column) { if (insert) { column = DataTableCore_splice(column, rowIndex, 0, true, [row[columnId]]).array; } else { column[rowIndex] = // Preserve explicit null and undefined but fall back // to existing value if the new row does not have the // key columnId in row ? row[columnId] : column[rowIndex]; } columns[columnId] = column; } }); this.applyRowCount(Math.max(indexRowCount, this.rowCount)); if (!eventDetail?.silent) { (0,external_highcharts_src_js_default_namespaceObject.fireEvent)(this, 'afterSetRows', { rowIndex }); this.versionTag = (0,external_highcharts_src_js_default_namespaceObject.uniqueKey)(); } } /** * Returns the modified (clone) or the original data table if the modified * one does not exist. * * @return {Highcharts.DataTable} * The modified (clone) or the original data table. */ getModified() { return this.modified || this; } } /* * * * Default Export * * */ /* harmony default export */ const Data_DataTableCore = (DataTableCore); /* * * * API Declarations * * */ /** * A collection of data table columns defined by a object where the key is the * column ID and the value is an array of the column values. Typed arrays are * supported. * * @type {Highcharts.DataTableColumnCollection|undefined} * @apioption dataTable.columns */ /** * Custom ID to identify the new DataTable instance. * * @type {string|undefined} * @apioption dataTable.id */ /** * A typed array. * @typedef {Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} Highcharts.TypedArray */ /** * A column of values in a data table. * @typedef {Array<boolean|null|number|string|undefined>|Highcharts.TypedArray} Highcharts.DataTableColumn */ /** * A collection of data table columns defined by a object where the key is the * column ID and the value is an array of the column values. Typed arrays are * supported. * @typedef {Record<string, Highcharts.DataTableColumn>} Highcharts.DataTableColumnCollection */ /** * Options for the `DataTable` or `DataTableCore` classes. * @interface Highcharts.DataTableOptionsObject */ /** * The column options for the data table. The columns are defined by an object * where the key is the column ID and the value is an array of the column * values. * * @name Highcharts.DataTableOptionsObject.columns * @type {Highcharts.DataTableColumnCollection|undefined} */ /** * Custom ID to identify the new DataTable instance. * * @name Highcharts.DataTableOptionsObject.id * @type {string|undefined} */ (''); // Keeps doclets above in JS file ;// external ["../highcharts.src.js","default","SeriesRegistry"] const external_highcharts_src_js_default_SeriesRegistry_namespaceObject = __WEBPACK_EXTERNAL_MODULE__highcharts_src_js_8202131d__["default"].SeriesRegistry; var external_highcharts_src_js_default_SeriesRegistry_default = /*#__PURE__*/__webpack_require__.n(external_highcharts_src_js_default_SeriesRegistry_namespaceObject); ;// ./code/es-modules/Stock/Indicators/SMA/SMAIndicator.js /* * * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ const { line: LineSeries } = (external_highcharts_src_js_default_SeriesRegistry_default()).seriesTypes; /** * * Return the parent series values in the legacy two-dimensional yData * format * @internal */ const tableToMultiYData = (series, processed) => { const yData = [], pointArrayMap = series.pointArrayMap, table = processed && series.dataTable.getModified() || series.dataTable; if (!pointArrayMap) { return series.getColumn('y', processed); } const columns = pointArrayMap.map((key) => series.getColumn(key, processed)); for (let i = 0; i < table.rowCount; i++) { const values = pointArrayMap.map((key, colIndex) => columns[colIndex]?.[i] || 0); yData.push(values); } return yData; }; /* * * * Class * * */ /** * The SMA series type. * * @internal */ class SMAIndicator extends LineSeries { /* * * * Functions * * */ /** @internal */ destroy() { this.dataEventsToUnbind.forEach(function (unbinder) { unbinder(); }); super.destroy.apply(this, arguments); } /** @internal */ getName() { const params = []; let name = this.name; if (!name) { (this.nameComponents || []).forEach(function (component, index) { params.push(this.options.params[component] + (0,external_highcharts_src_js_default_namespaceObject.pick)(this.nameSuffixes[index], '')); }, this); name = (this.nameBase || this.type.toUpperCase()) + (this.nameComponents ? ' (' + params.join(', ') + ')' : ''); } return name; } /** @internal */ getValues(series, params) { const period = params.period, xVal = series.xData || [], yVal = series.yData, yValLen = yVal.length, SMA = [], xData = [], yData = []; let i, index = -1, range = 0, SMAPoint, sum = 0; if (xVal.length < period) { return; } // Switch index for OHLC / Candlestick / Arearange if ((0,external_highcharts_src_js_default_namespaceObject.isArray)(yVal[0])) { index = params.index ? params.index : 0; } // Accumulate first N-points while (range < period - 1) { sum += index < 0 ? yVal[range] : yVal[range][index]; range++; } // Calculate value one-by-one for each period in visible data for (i = range; i < yValLen; i++) { sum += index < 0 ? yVal[i] : yVal[i][index]; SMAPoint = [xVal[i], sum / period]; SMA.push(SMAPoint); xData.push(SMAPoint[0]); yData.push(SMAPoint[1]); sum -= (index < 0 ? yVal[i - range] : yVal[i - range][index]); } return { values: SMA, xData: xData, yData: yData }; } /** @internal */ init(chart, options) { const indicator = this; super.init.call(indicator, chart, options); // Only after series are linked indicator can be processed. const linkedSeriesUnbiner = (0,external_highcharts_src_js_default_namespaceObject.addEvent)((external_highcharts_src_js_default_Chart_default()), 'afterLinkSeries', function ({ isUpdating }) { // #18643 indicator shouldn't recalculate // values while series updating. if (isUpdating) { return; } const hasEvents = !!indicator.dataEventsToUnbind.length; if (indicator.linkedParent) { if (!hasEvents) { // No matter which indicator, always recalculate after // updating the data. indicator.dataEventsToUnbind.push((0,external_highcharts_src_js_default_namespaceObject.addEvent)(indicator.linkedParent, 'updatedData', function () { indicator.recalculateValues(); })); // Some indicators (like VBP) requires an additional // event (afterSetExtremes) to properly show the data. if (indicator.calculateOn.xAxis) { indicator.dataEventsToUnbind.push((0,external_highcharts_src_js_default_namespaceObject.addEvent)(indicator.linkedParent.xAxis, indicator.calculateOn.xAxis, function () { indicator.recalculateValues(); })); } } // Most indicators are being calculated on chart's init. if (indicator.calculateOn.chart === 'init') { // When closestPointRange is set, it is an indication // that `Series.processData` has run. If it hasn't we // need to `recalculateValues`. if (!indicator.closestPointRange) { indicator.recalculateValues(); } } else if (!hasEvents) { // Some indicators (like VBP) has to recalculate their // values after other chart's events (render). const unbinder = (0,external_highcharts_src_js_default_namespaceObject.addEvent)(indicator.chart, indicator.calculateOn.chart, function () { indicator.recalculateValues(); // Call this just once. unbinder(); }); } } else { return (0,external_highcharts_src_js_default_namespaceObject.error)('Series ' + indicator.options.linkedTo + ' not found! Check `linkedTo`.', false, chart); } }, { order: 0 }); // Make sure we find series which is a base for an indicator // chart.linkSeries(); indicator.dataEventsToUnbind = []; indicator.eventsToUnbind.push(linkedSeriesUnbiner); } /** @internal */ recalculateValues() { const indicator = this, table = this.dataTable, oldDataLength = indicator.dataTable.rowCount, emptySet = { values: [], xData: [], yData: [] }; let overwriteData = true, min, max; // For the newer data table, temporarily set the parent series `yData` // to the legacy format that is documented for custom indicators, and // get the xData from the data table const yData = indicator.linkedParent.yData, processedYData = indicator.linkedParent.processedYData; indicator.linkedParent.xData = indicator.linkedParent .getColumn('x'); indicator.linkedParent.yData = tableToMultiYData(indicator.linkedParent); indicator.linkedParent.processedYData = tableToMultiYData(indicator.linkedParent, true); // Updating an indicator with redraw=false may destroy data. // If there will be a following update for the parent series, // we will try to access Series object without any properties // (except for prototyped ones). This is what happens // for example when using Axis.setDataGrouping(). See #16670 const processedData = indicator.linkedParent.options && // #18176, #18177 indicators should work with empty dataset indicator.linkedParent.dataTable.rowCount ? (indicator.getValues(indicator.linkedParent, indicator.options.params) || emptySet) : emptySet; processedData.xData.length = processedData.values.length; // Reset delete indicator.linkedParent.xData; indicator.linkedParent.yData = yData; indicator.linkedParent.processedYData = processedYData; const pointArrayMap = indicator.pointArrayMap || ['y'], valueColumns = {}; // Split legacy two-dimensional values into value columns processedData.yData .forEach((values) => { pointArrayMap.forEach((key, index) => { const column = valueColumns[key] || []; column.push((0,external_highcharts_src_js_default_namespaceObject.isArray)(values) ? values[index] : values); if (!valueColumns[key]) { valueColumns[key] = column; } }); }); // We need to update points to reflect changes in all, // x and y's, values. However, do it only for non-grouped // data - grouping does it for us (#8572) if (oldDataLength && !indicator.hasGroupedData && indicator.visible && indicator.points) { // When data is cropped update only available points (#9493) if (indicator.cropped) { if (indicator.xAxis) { min = indicator.xAxis.min; max = indicator.xAxis.max; } const croppedData = indicator.cropData(table, min, max); indicator.setData(croppedData.modified, false); } else if (indicator.updateAllPoints || // #18710 // Omit addPoint() and removePoint() cases processedData.xData.length !== oldDataLength - 1 && processedData.xData.length !== oldDataLength + 1) { overwriteData = false; this.setData(new Data_DataTableCore({ columns: { x: processedData.xData, ...valueColumns } }), false); } } if (overwriteData) { const columns = valueColumns; columns.x = processedData.xData; // Add the processedData.values to the data table processedData.values.reduce((columns, val, i) => { Object.keys(val).forEach((key) => { if (!columns[key]) { columns[key] = []; } columns[key][i] = val[key]; }); return columns; }, columns); table.setColumns(columns); delete indicator.xColumn; delete indicator.xColumnIsNumbers; } if (indicator.calculateOn.xAxis && indicator.getColumn('x', true).length) { indicator.isDirty = true; indicator.redraw(); } indicator.isDirtyData = !!indicator.linkedSeries.length; (0,external_highcharts_src_js_default_namespaceObject.fireEvent)(indicator, 'updatedData'); // #18689 } /** @internal */ processData() { const series = this, compareToMain = series.options.compareToMain, linkedParent = series.linkedParent; super.processData.apply(series, arguments); if (series.dataModify && linkedParent && linkedParent.dataModify && linkedParent.dataModify.compareValue && compareToMain) { series.dataModify.compareValue = linkedParent.dataModify.compareValue; } return; } } /* * * * Static Properties * * */ /** * Simple moving average indicator (SMA). This series requires `linkedTo` * option to be set. * * @sample {highstock} stock/indicators/sma * Simple moving average indicator * * @extends plotOptions.line * @since 6.0.0 * @excluding allAreas, colorAxis, dragDrop, joinBy, keys, * navigatorOptions, pointInterval, pointIntervalUnit, * pointPlacement, pointRange, pointStart, showInNavigator, * stacking, useOhlcData * @product highstock * @requires stock/indicators/indicators * @optionparent plotOptions.sma */ SMAIndicator.defaultOptions = (0,external_highcharts_src_js_default_namespaceObject.merge)(LineSeries.defaultOptions, { /** * The name of the series as shown in the legend, tooltip etc. If not * set, it will be based on a technical indicator type and default * params. * * @type {string} */ name: void 0, tooltip: { /** * Number of decimals in indicator series. */ valueDecimals: 4 }, /** * The main series ID that indicator will be based on. Required for this * indicator. * * @type {string} */ linkedTo: void 0, /** * Whether to compare indicator to the main series values * or indicator values. * * @sample {highstock} stock/plotoptions/series-comparetomain/ * Difference between comparing SMA values to the main series * and its own values. * * @type {boolean} */ compareToMain: false, /** * Parameters used in calculation of regression series' points. */ params: { /** * The point index which indicator calculations will base. For * example using OHLC data, index=2 means the indicator will be * calculated using Low values. */ index: 3, /** * The base period for indicator calculations. This is the number of * data points which are taken into account for the indicator * calculations. */ period: 14 } }); (0,external_highcharts_src_js_default_namespaceObject.extend)(SMAIndicator.prototype, { calculateOn: { chart: 'init' }, hasDerivedData: true, nameComponents: ['period'], nameSuffixes: [], // E.g. Zig Zag uses extra '%'' in the legend name useCommonDataGrouping: true }); external_highcharts_src_js_default_SeriesRegistry_default().registerSeriesType('sma', SMAIndicator); /* * * * Default Export * * */ /** @internal */ /* harmony default export */ const SMA_SMAIndicator = ((/* unused pure expression or super */ null && (SMAIndicator))); /* * * * API Options * * */ /** * A `SMA` series. If the [type](#series.sma.type) option is not specified, it * is inherited from [chart.type](#chart.type). * * @extends series,plotOptions.sma * @since 6.0.0 * @product highstock * @excluding dataParser, dataURL, useOhlcData * @requires stock/indicators/indicators * @apioption series.sma */ (''); // Adds doclet above to the transpiled file ;// ./code/es-modules/Stock/Indicators/EMA/EMAIndicator.js /* * * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * */ const { sma: EMAIndicator_SMAIndicator } = (external_highcharts_src_js_default_SeriesRegistry_default()).seriesTypes; /* * * * Class * * */ /** * The EMA series type. * * @internal * @class * @name Highcharts.seriesTypes.ema * * @augments Highcharts.Series */ class EMAIndicator extends EMAIndicator_SMAIndicator { /* * * * Functions * * */ accumulatePeriodPoints(period, index, yVal) { let sum = 0, i = 0, y = 0; while (i < period) { y = index < 0 ? yVal[i] : yVal[i][index]; sum = sum + y; i++; } return sum; } calculateEma(xVal, yVal, i, EMApercent, calEMA, index, SMA) { const x = xVal[i - 1], yValue = index < 0 ? yVal[i - 1] : yVal[i - 1][index], y = typeof calEMA === 'undefined' ? SMA : (0,external_highcharts_src_js_default_namespaceObject.correctFloat)((yValue * EMApercent) + (calEMA * (1 - EMApercent))); return [x, y]; } getValues(series, params) { const period = params.period, xVal = series.xData, yVal = series.yData, yValLen = yVal ? yVal.length : 0, EMApercent = 2 / (period + 1), EMA = [], xData = [], yData = []; let calEMA, EMAPoint, i, index = -1, sum = 0, SMA = 0; // Check period, if bigger than points length, skip if (yValLen < period) { return; } // Switch index for OHLC / Candlestick / Arearange if ((0,external_highcharts_src_js_default_namespaceObject.isArray)(yVal[0])) { index = params.index ? params.index : 0; } // Accumulate first N-points sum = this.accumulatePeriodPoints(period, index, yVal); // First point SMA = sum / period; // Calculate value one-by-one for each period in visible data for (i = period; i < yValLen + 1; i++) { EMAPoint = this.calculateEma(xVal, yVal, i, EMApercent, calEMA, index, SMA); EMA.push(EMAPoint); xData.push(EMAPoint[0]); yData.push(EMAPoint[1]); calEMA = EMAPoint[1]; } return { values: EMA, xData: xData, yData: yData }; } } /* * * * Static Properties * * */ /** * Exponential moving average indicator (EMA). This series requires the * `linkedTo` option to be set. * * @sample {highstock} stock/indicators/ema * Exponential moving average indicator * * @extends plotOptions.sma * @since 6.0.0 * @product highstock * @requires stock/indicators/indicators * @optionparent plotOptions.ema */ EMAIndicator.defaultOptions = (0,external_highcharts_src_js_default_namespaceObject.merge)(EMAIndicator_SMAIndicator.defaultOptions, { params: { /** * The point index which indicator calculations will base. For * example using OHLC data, index=2 means the indicator will be * calculated using Low values. * * By default index value used to be set to 0. Since * Highcharts Stock 7 by default index is set to 3 * which means that the ema indicator will be * calculated using Close values. */ index: 3, period: 9 // @merge 14 in v6.2 } }); external_highcharts_src_js_default_SeriesRegistry_default().registerSeriesType('ema', EMAIndicator); /* * * * Default Export * * */ /** @internal */ /* harmony default export */ const EMA_EMAIndicator = ((/* unused pure expression or super */ null && (EMAIndicator))); /* * * * API Options * * */ /** * A `EMA` series. If the [type](#series.ema.type) option is not * specified, it is inherited from [chart.type](#chart.type). * * @extends series,plotOptions.ema * @since 6.0.0 * @product highstock * @excluding dataParser, dataURL * @requires stock/indicators/indicators * @apioption series.ema */ ''; // Adds doclet above to the transpiled file ;// ./code/es-modules/Stock/Indicators/AD/ADIndicator.js /* * * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * */ const { sma: ADIndicator_SMAIndicator } = (external_highcharts_src_js_default_SeriesRegistry_default()).seriesTypes; /* * * * Class * * */ /** * The AD series type. * * @internal * @class * @name Highcharts.seriesTypes.ad * * @augments Highcharts.Series */ class ADIndicator extends ADIndicator_SMAIndicator { /* * * * Static Functions * * */ static populateAverage(xVal, yVal, yValVolume, i, // eslint-disable-next-line @typescript-eslint/no-unused-vars _period) { const high = yVal[i][1], low = yVal[i][2], close = yVal[i][3], volume = yValVolume[i], adY = close === high && close === low || high === low ? 0 : ((2 * close - low - high) / (high - low)) * volume, adX = xVal[i]; return [adX, adY]; } /* * * * Functions * * */ getValues(series, params) { const period = params.period, xVal = series.xData, yVal = series.yData, volumeSeriesID = params.volumeSeriesID, volumeSeries = series.chart.get(volumeSeriesID), yValVolume = volumeSeries?.getColumn('y'), yValLen = yVal ? yVal.length : 0, AD = [], xData = [], yData = []; let len, i, ADPoint; if (xVal.length <= period && yValLen && yVal[0].length !== 4) { return; } if (!volumeSeries) { (0,external_highcharts_src_js_default_namespaceObject.error)('Series ' + volumeSeriesID + ' not found! Check `volumeSeriesID`.', true, series.chart); return; } // When i = period <-- skip first N-points // Calculate value one-by-one for each period in visible data for (i = period; i < yValLen; i++) { len = AD.length; ADPoint = ADIndicator.populateAverage(xVal, yVal, yValVolume, i, period); if (len > 0) { ADPoint[1] += AD[len - 1][1]; } AD.push(ADPoint); xData.push(ADPoint[0]); yData.push(ADPoint[1]); } return { values: AD, xData: xData, yData: yData }; } } /* * * * Static Properties * * */ /** * Accumulation Distribution (AD). This series requires `linkedTo` option to * be set. * * @sample {highstock} stock/indicators/accumulation-distribution * Accumulation/Distribution indicator * * @extends plotOptions.sma * @since 6.0.0 * @product highstock * @requires stock/indicators/indicators * @requires stock/indicators/accumulation-distribution * @optionparent plotOptions.ad */ ADIndicator.defaultOptions = (0,external_highcharts_src_js_default_namespaceObject.merge)(ADIndicator_SMAIndicator.defaultOptions, { /** * @excluding index */ params: { index: void 0, // Unused index, do not inherit (#15362) /** * The id of volume series which is mandatory. * For example using OHLC data, volumeSeriesID='volume' means * the indicator will be calculated using OHLC and volume values. * * @since 6.0.0 */ volumeSeriesID: 'volume' } }); (0,external_highcharts_src_js_default_namespaceObject.extend)(ADIndicator.prototype, { nameComponents: false, nameBase: 'Accumulation/Distribution' }); external_highcharts_src_js_default_SeriesRegistry_default().registerSeriesType('ad', ADIndicator); /* * * * Default Export * * */ /** @internal */ /* harmony default export */ const AD_ADIndicator = (ADIndicator); /* * * * API Options * * */ /** * A `AD` series. If the [type](#series.ad.type) option is not * specified, it is inherited from [chart.type](#chart.type). * * @extends series,plotOptions.ad * @since 6.0.0 * @excluding dataParser, dataURL * @product highstock * @requires stock/indicators/indicators * @requires stock/indicators/accumulation-distribution * @apioption series.ad */ ''; // Add doclet above to transpiled file ;// ./code/es-modules/Stock/Indicators/AO/AOIndicator.js /* * * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * */ const { noop } = (external_highcharts_src_js_default_default()); const { column: { prototype: columnProto }, sma: AOIndicator_SMAIndicator } = (external_highcharts_src_js_default_SeriesRegistry_default()).seriesTypes; /* * * * Class * * */ /** * The AO series type * * @internal * @class * @name Highcharts.seriesTypes.ao * * @augments Highcharts.Series */ class AOIndicator extends AOIndicator_SMAIndicator { /* * * * Functions * * */ drawGraph() { const indicator = this, options = indicator.options, points = indicator.points, userColor = indicator.userOptions.color, positiveColor = options.greaterBarColor, negativeColor = options.lowerBarColor, firstPoint = points[0]; let i; if (!userColor && firstPoint) { firstPoint.color = positiveColor; for (i = 1; i < points.length; i++) { if (points[i].y > points[i - 1].y) { points[i].color = positiveColor; } else if (points[i].y < points[i - 1].y) { points[i].color = negativeColor; } else { points[i].color = points[i - 1].color; } } } } getValues(series) { const shortPeriod = 5, longPeriod = 34, xVal = series.xData || [], yVal = series.yData || [], yValLen = yVal.length, AO = [], // 0- date, 1- Awesome Oscillator xData = [], yData = [], high = 1, low = 2; let shortSMA, // Shorter Period SMA longSMA, // Longer Period SMA awesome, shortLastIndex, longLastIndex, price, i, j, longSum = 0, shortSum = 0; if (xVal.length <= longPeriod || !(0,external_highcharts_src_js_default_namespaceObject.isArray)(yVal[0]) || yVal[0].length !== 4) { return; } for (i = 0; i < longPeriod - 1; i++) { price = (yVal[i][high] + yVal[i][low]) / 2; if (i >= longPeriod - shortPeriod) { shortSum = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(shortSum + price); } longSum = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(longSum + price); } for (j = longPeriod - 1; j < yValLen; j++) { price = (yVal[j][high] + yVal[j][low]) / 2; shortSum = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(shortSum + price); longSum = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(longSum + price); shortSMA = shortSum / shortPeriod; longSMA = longSum / longPeriod; awesome = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(shortSMA - longSMA); AO.push([xVal[j], awesome]); xData.push(xVal[j]); yData.push(awesome); shortLastIndex = j + 1 - shortPeriod; longLastIndex = j + 1 - longPeriod; shortSum = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(shortSum - (yVal[shortLastIndex][high] + yVal[shortLastIndex][low]) / 2); longSum = (0,external_highcharts_src_js_default_namespaceObject.correctFloat)(longSum - (yVal[longLastIndex][high] + yVal[longLastIndex][low]) / 2); } return { values: AO, xData: xData, yData: yData }; } } /* * * * Static Properties * * */ /** * Awesome Oscillator. This series requires the `linkedTo` option to * be set and should be loaded after the `stock/indicators/indicators.js` * * @sample {highstock} stock/indicators/ao * Awesome * * @extends plotOptions.sma * @since 7.0.0 * @product highstock * @excluding allAreas, colorAxis, joinBy, keys, navigatorOptions, * params, pointInterval, pointIntervalUnit, pointPlacement, * pointRange, pointStart, showInNavigator, stacking * @requires stock/indicators/indicators * @requires stock/indicators/ao * @optionparent plotOptions.ao */ AOIndicator.defaultOptions = (0,external_highcharts_src_js_default_namespaceObject.merge)(AOIndicator_SMAIndicator.defaultOptions, { params: { // Index and period are unchangeable, do not inherit (#15362) index: void 0, period: void 0 }, /** * Color of the Awesome oscillator series bar that is greater than the * previous one. Note that if a `color` is defined, the `color` * takes precedence and the `greaterBarColor` is ignored. * * @sample {highstock} stock/indicators/ao/ * greaterBarColor * * @type {Highcharts.ColorType} * @since 7.0.0 */ greaterBarColor: 'var(--highcharts-positive-color)', /** * Color of the Awesome oscillator series bar that is lower than the * previous one. Note that if a `color` is defined, the `color` * takes precedence and the `lowerBarColor` is ignored. * * @sample {highstock} stock/indicators/ao/ * lowerBarColor * * @type {Highcharts.ColorType} * @since 7.0.0 */ lowerBarColor: 'var(--highcharts-negative-color)', threshold: 0, groupPadding: 0.2, pointPadding: 0.2, crisp: false, states: { hover: { halo: { size: 0 } } } }); (0,external_highcharts_src_js_default_namespaceObject.extend)(AOIndicator.prototype, { nameBase: 'AO', nameComponents: void 0, // Columns support: markerAttribs: noop, getColumnMetrics: columnProto.getColumnMetrics, crispCol: columnProto.crispCol, translate: columnProto.translate, drawPoints: columnProto.drawPoints }); external_highcharts_src_js_default_SeriesRegistry_default().registerSeriesType('ao', AOIndicator); /* * * * Default Export * * */ /** @internal */ /* harmony default export */ const AO_AOIndicator = ((/* unused pure expression or super */ null && (AOIndicator))); /* * * * API Options * * */ /** * An `AO` series. If the [type](#series.ao.type) * option is not specified, it is inherited from [chart.type](#chart.type). * * @extends series,plotOptions.ao * @since 7.0.0 * @product highstock * @excluding allAreas, colorAxis, dataParser, dataURL, joinBy, keys,