indicators.src.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. /**
  2. * @license Highstock JS v9.0.1 (2021-02-16)
  3. *
  4. * Indicator series type for Highstock
  5. *
  6. * (c) 2010-2021 Pawel Fus, Sebastian Bochan
  7. *
  8. * License: www.highcharts.com/license
  9. */
  10. 'use strict';
  11. (function (factory) {
  12. if (typeof module === 'object' && module.exports) {
  13. factory['default'] = factory;
  14. module.exports = factory;
  15. } else if (typeof define === 'function' && define.amd) {
  16. define('highcharts/indicators/indicators', ['highcharts', 'highcharts/modules/stock'], function (Highcharts) {
  17. factory(Highcharts);
  18. factory.Highcharts = Highcharts;
  19. return factory;
  20. });
  21. } else {
  22. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  23. }
  24. }(function (Highcharts) {
  25. var _modules = Highcharts ? Highcharts._modules : {};
  26. function _registerModule(obj, path, args, fn) {
  27. if (!obj.hasOwnProperty(path)) {
  28. obj[path] = fn.apply(null, args);
  29. }
  30. }
  31. _registerModule(_modules, 'Mixins/IndicatorRequired.js', [_modules['Core/Utilities.js']], function (U) {
  32. /**
  33. *
  34. * (c) 2010-2021 Daniel Studencki
  35. *
  36. * License: www.highcharts.com/license
  37. *
  38. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  39. *
  40. * */
  41. var error = U.error;
  42. /* eslint-disable no-invalid-this, valid-jsdoc */
  43. var requiredIndicatorMixin = {
  44. /**
  45. * Check whether given indicator is loaded,
  46. else throw error.
  47. * @private
  48. * @param {Highcharts.Indicator} indicator
  49. * Indicator constructor function.
  50. * @param {string} requiredIndicator
  51. * Required indicator type.
  52. * @param {string} type
  53. * Type of indicator where function was called (parent).
  54. * @param {Highcharts.IndicatorCallbackFunction} callback
  55. * Callback which is triggered if the given indicator is loaded.
  56. * Takes indicator as an argument.
  57. * @param {string} errMessage
  58. * Error message that will be logged in console.
  59. * @return {boolean}
  60. * Returns false when there is no required indicator loaded.
  61. */
  62. isParentLoaded: function (indicator,
  63. requiredIndicator,
  64. type,
  65. callback,
  66. errMessage) {
  67. if (indicator) {
  68. return callback ? callback(indicator) : true;
  69. }
  70. error(errMessage || this.generateMessage(type, requiredIndicator));
  71. return false;
  72. },
  73. /**
  74. * @private
  75. * @param {string} indicatorType
  76. * Indicator type
  77. * @param {string} required
  78. * Required indicator
  79. * @return {string}
  80. * Error message
  81. */
  82. generateMessage: function (indicatorType, required) {
  83. return 'Error: "' + indicatorType +
  84. '" indicator type requires "' + required +
  85. '" indicator loaded before. Please read docs: ' +
  86. 'https://api.highcharts.com/highstock/plotOptions.' +
  87. indicatorType;
  88. }
  89. };
  90. return requiredIndicatorMixin;
  91. });
  92. _registerModule(_modules, 'Stock/Indicators/SMA/SMAComposition.js', [_modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (SeriesRegistry, U) {
  93. /* *
  94. *
  95. * License: www.highcharts.com/license
  96. *
  97. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  98. *
  99. * */
  100. var Series = SeriesRegistry.series,
  101. ohlcProto = SeriesRegistry.seriesTypes.ohlc.prototype;
  102. var addEvent = U.addEvent,
  103. extend = U.extend;
  104. /* *
  105. *
  106. * Composition
  107. *
  108. * */
  109. addEvent(Series, 'init', function (eventOptions) {
  110. // eslint-disable-next-line no-invalid-this
  111. var series = this,
  112. options = eventOptions.options;
  113. if (options.useOhlcData &&
  114. options.id !== 'highcharts-navigator-series') {
  115. extend(series, {
  116. pointValKey: ohlcProto.pointValKey,
  117. keys: ohlcProto.keys,
  118. pointArrayMap: ohlcProto.pointArrayMap,
  119. toYData: ohlcProto.toYData
  120. });
  121. }
  122. });
  123. addEvent(Series, 'afterSetOptions', function (e) {
  124. var options = e.options,
  125. dataGrouping = options.dataGrouping;
  126. if (dataGrouping &&
  127. options.useOhlcData &&
  128. options.id !== 'highcharts-navigator-series') {
  129. dataGrouping.approximation = 'ohlc';
  130. }
  131. });
  132. });
  133. _registerModule(_modules, 'Stock/Indicators/SMA/SMAIndicator.js', [_modules['Mixins/IndicatorRequired.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (RequiredIndicatorMixin, SeriesRegistry, U) {
  134. /* *
  135. *
  136. * License: www.highcharts.com/license
  137. *
  138. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  139. *
  140. * */
  141. var __extends = (this && this.__extends) || (function () {
  142. var extendStatics = function (d,
  143. b) {
  144. extendStatics = Object.setPrototypeOf ||
  145. ({ __proto__: [] } instanceof Array && function (d,
  146. b) { d.__proto__ = b; }) ||
  147. function (d,
  148. b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  149. return extendStatics(d, b);
  150. };
  151. return function (d, b) {
  152. extendStatics(d, b);
  153. function __() { this.constructor = d; }
  154. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  155. };
  156. })();
  157. var LineSeries = SeriesRegistry.seriesTypes.line;
  158. var addEvent = U.addEvent,
  159. error = U.error,
  160. extend = U.extend,
  161. isArray = U.isArray,
  162. merge = U.merge,
  163. pick = U.pick,
  164. splat = U.splat;
  165. var generateMessage = RequiredIndicatorMixin.generateMessage;
  166. /* *
  167. *
  168. * Class
  169. *
  170. * */
  171. /**
  172. * The SMA series type.
  173. *
  174. * @private
  175. */
  176. var SMAIndicator = /** @class */ (function (_super) {
  177. __extends(SMAIndicator, _super);
  178. function SMAIndicator() {
  179. /* *
  180. *
  181. * Static Properties
  182. *
  183. * */
  184. var _this = _super !== null && _super.apply(this,
  185. arguments) || this;
  186. /* *
  187. *
  188. * Properties
  189. *
  190. * */
  191. _this.data = void 0;
  192. _this.dataEventsToUnbind = void 0;
  193. _this.linkedParent = void 0;
  194. _this.options = void 0;
  195. _this.points = void 0;
  196. return _this;
  197. /* eslint-enable valid-jsdoc */
  198. }
  199. /* *
  200. *
  201. * Functions
  202. *
  203. * */
  204. /* eslint-disable valid-jsdoc */
  205. /**
  206. * @private
  207. */
  208. SMAIndicator.prototype.destroy = function () {
  209. this.dataEventsToUnbind.forEach(function (unbinder) {
  210. unbinder();
  211. });
  212. _super.prototype.destroy.apply(this, arguments);
  213. };
  214. /**
  215. * @private
  216. */
  217. SMAIndicator.prototype.getName = function () {
  218. var name = this.name,
  219. params = [];
  220. if (!name) {
  221. (this.nameComponents || []).forEach(function (component, index) {
  222. params.push(this.options.params[component] +
  223. pick(this.nameSuffixes[index], ''));
  224. }, this);
  225. name = (this.nameBase || this.type.toUpperCase()) +
  226. (this.nameComponents ? ' (' + params.join(', ') + ')' : '');
  227. }
  228. return name;
  229. };
  230. /**
  231. * @private
  232. */
  233. SMAIndicator.prototype.getValues = function (series, params) {
  234. var period = params.period,
  235. xVal = series.xData,
  236. yVal = series.yData,
  237. yValLen = yVal.length,
  238. range = 0,
  239. sum = 0,
  240. SMA = [],
  241. xData = [],
  242. yData = [],
  243. index = -1,
  244. i,
  245. SMAPoint;
  246. if (xVal.length < period) {
  247. return;
  248. }
  249. // Switch index for OHLC / Candlestick / Arearange
  250. if (isArray(yVal[0])) {
  251. index = params.index ? params.index : 0;
  252. }
  253. // Accumulate first N-points
  254. while (range < period - 1) {
  255. sum += index < 0 ? yVal[range] : yVal[range][index];
  256. range++;
  257. }
  258. // Calculate value one-by-one for each period in visible data
  259. for (i = range; i < yValLen; i++) {
  260. sum += index < 0 ? yVal[i] : yVal[i][index];
  261. SMAPoint = [xVal[i], sum / period];
  262. SMA.push(SMAPoint);
  263. xData.push(SMAPoint[0]);
  264. yData.push(SMAPoint[1]);
  265. sum -= (index < 0 ?
  266. yVal[i - range] :
  267. yVal[i - range][index]);
  268. }
  269. return {
  270. values: SMA,
  271. xData: xData,
  272. yData: yData
  273. };
  274. };
  275. /**
  276. * @private
  277. */
  278. SMAIndicator.prototype.init = function (chart, options) {
  279. var indicator = this,
  280. requiredIndicators = indicator.requireIndicators();
  281. // Check whether all required indicators are loaded.
  282. if (!requiredIndicators.allLoaded) {
  283. return error(generateMessage(indicator.type, requiredIndicators.needed));
  284. }
  285. _super.prototype.init.call(indicator, chart, options);
  286. // Make sure we find series which is a base for an indicator
  287. chart.linkSeries();
  288. indicator.dataEventsToUnbind = [];
  289. /**
  290. * @private
  291. * @return {void}
  292. */
  293. function recalculateValues() {
  294. var oldData = indicator.points || [],
  295. oldDataLength = (indicator.xData || []).length,
  296. processedData = (indicator.getValues(indicator.linkedParent,
  297. indicator.options.params) || {
  298. values: [],
  299. xData: [],
  300. yData: []
  301. }),
  302. croppedDataValues = [],
  303. overwriteData = true,
  304. oldFirstPointIndex,
  305. oldLastPointIndex,
  306. croppedData,
  307. min,
  308. max,
  309. i;
  310. // We need to update points to reflect changes in all,
  311. // x and y's, values. However, do it only for non-grouped
  312. // data - grouping does it for us (#8572)
  313. if (oldDataLength &&
  314. !indicator.hasGroupedData &&
  315. indicator.visible &&
  316. indicator.points) {
  317. // When data is cropped update only avaliable points (#9493)
  318. if (indicator.cropped) {
  319. if (indicator.xAxis) {
  320. min = indicator.xAxis.min;
  321. max = indicator.xAxis.max;
  322. }
  323. croppedData = indicator.cropData(processedData.xData, processedData.yData, min, max);
  324. for (i = 0; i < croppedData.xData.length; i++) {
  325. // (#10774)
  326. croppedDataValues.push([
  327. croppedData.xData[i]
  328. ].concat(splat(croppedData.yData[i])));
  329. }
  330. oldFirstPointIndex = processedData.xData.indexOf(indicator.xData[0]);
  331. oldLastPointIndex = processedData.xData.indexOf(indicator.xData[indicator.xData.length - 1]);
  332. // Check if indicator points should be shifted (#8572)
  333. if (oldFirstPointIndex === -1 &&
  334. oldLastPointIndex === processedData.xData.length - 2) {
  335. if (croppedDataValues[0][0] === oldData[0].x) {
  336. croppedDataValues.shift();
  337. }
  338. }
  339. indicator.updateData(croppedDataValues);
  340. // Omit addPoint() and removePoint() cases
  341. }
  342. else if (processedData.xData.length !== oldDataLength - 1 &&
  343. processedData.xData.length !== oldDataLength + 1) {
  344. overwriteData = false;
  345. indicator.updateData(processedData.values);
  346. }
  347. }
  348. if (overwriteData) {
  349. indicator.xData = processedData.xData;
  350. indicator.yData = processedData.yData;
  351. indicator.options.data = processedData.values;
  352. }
  353. // Removal of processedXData property is required because on
  354. // first translate processedXData array is empty
  355. if (indicator.bindTo.series === false) {
  356. delete indicator.processedXData;
  357. indicator.isDirty = true;
  358. indicator.redraw();
  359. }
  360. indicator.isDirtyData = false;
  361. }
  362. if (!indicator.linkedParent) {
  363. return error('Series ' +
  364. indicator.options.linkedTo +
  365. ' not found! Check `linkedTo`.', false, chart);
  366. }
  367. indicator.dataEventsToUnbind.push(addEvent(indicator.bindTo.series ?
  368. indicator.linkedParent :
  369. indicator.linkedParent.xAxis, indicator.bindTo.eventName, recalculateValues));
  370. if (indicator.calculateOn === 'init') {
  371. recalculateValues();
  372. }
  373. else {
  374. var unbinder = addEvent(indicator.chart,
  375. indicator.calculateOn,
  376. function () {
  377. recalculateValues();
  378. // Call this just once, on init
  379. unbinder();
  380. });
  381. }
  382. // return indicator;
  383. };
  384. /**
  385. * @private
  386. */
  387. SMAIndicator.prototype.processData = function () {
  388. var series = this,
  389. compareToMain = series.options.compareToMain,
  390. linkedParent = series.linkedParent;
  391. _super.prototype.processData.apply(series, arguments);
  392. if (linkedParent && linkedParent.compareValue && compareToMain) {
  393. series.compareValue = linkedParent.compareValue;
  394. }
  395. return;
  396. };
  397. /**
  398. * @private
  399. */
  400. SMAIndicator.prototype.requireIndicators = function () {
  401. var obj = {
  402. allLoaded: true
  403. };
  404. // Check whether all required indicators are loaded, else return
  405. // the object with missing indicator's name.
  406. this.requiredIndicators.forEach(function (indicator) {
  407. if (SeriesRegistry.seriesTypes[indicator]) {
  408. SeriesRegistry.seriesTypes[indicator].prototype.requireIndicators();
  409. }
  410. else {
  411. obj.allLoaded = false;
  412. obj.needed = indicator;
  413. }
  414. });
  415. return obj;
  416. };
  417. /**
  418. * The parameter allows setting line series type and use OHLC indicators.
  419. * Data in OHLC format is required.
  420. *
  421. * @sample {highstock} stock/indicators/use-ohlc-data
  422. * Plot line on Y axis
  423. *
  424. * @type {boolean}
  425. * @product highstock
  426. * @apioption plotOptions.line.useOhlcData
  427. */
  428. /**
  429. * Simple moving average indicator (SMA). This series requires `linkedTo`
  430. * option to be set.
  431. *
  432. * @sample stock/indicators/sma
  433. * Simple moving average indicator
  434. *
  435. * @extends plotOptions.line
  436. * @since 6.0.0
  437. * @excluding allAreas, colorAxis, dragDrop, joinBy, keys,
  438. * navigatorOptions, pointInterval, pointIntervalUnit,
  439. * pointPlacement, pointRange, pointStart, showInNavigator,
  440. * stacking, useOhlcData
  441. * @product highstock
  442. * @requires stock/indicators/indicators
  443. * @optionparent plotOptions.sma
  444. */
  445. SMAIndicator.defaultOptions = merge(LineSeries.defaultOptions, {
  446. /**
  447. * The name of the series as shown in the legend, tooltip etc. If not
  448. * set, it will be based on a technical indicator type and default
  449. * params.
  450. *
  451. * @type {string}
  452. */
  453. name: void 0,
  454. tooltip: {
  455. /**
  456. * Number of decimals in indicator series.
  457. */
  458. valueDecimals: 4
  459. },
  460. /**
  461. * The main series ID that indicator will be based on. Required for this
  462. * indicator.
  463. *
  464. * @type {string}
  465. */
  466. linkedTo: void 0,
  467. /**
  468. * Whether to compare indicator to the main series values
  469. * or indicator values.
  470. *
  471. * @sample {highstock} stock/plotoptions/series-comparetomain/
  472. * Difference between comparing SMA values to the main series
  473. * and its own values.
  474. *
  475. * @type {boolean}
  476. */
  477. compareToMain: false,
  478. /**
  479. * Paramters used in calculation of regression series' points.
  480. */
  481. params: {
  482. /**
  483. * The point index which indicator calculations will base. For
  484. * example using OHLC data, index=2 means the indicator will be
  485. * calculated using Low values.
  486. */
  487. index: 0,
  488. /**
  489. * The base period for indicator calculations. This is the number of
  490. * data points which are taken into account for the indicator
  491. * calculations.
  492. */
  493. period: 14
  494. }
  495. });
  496. return SMAIndicator;
  497. }(LineSeries));
  498. extend(SMAIndicator.prototype, {
  499. bindTo: {
  500. series: true,
  501. eventName: 'updatedData'
  502. },
  503. calculateOn: 'init',
  504. hasDerivedData: true,
  505. nameComponents: ['period'],
  506. nameSuffixes: [],
  507. // Defines on which other indicators is this indicator based on.
  508. requiredIndicators: [],
  509. useCommonDataGrouping: true
  510. });
  511. SeriesRegistry.registerSeriesType('sma', SMAIndicator);
  512. /* *
  513. *
  514. * Default Export
  515. *
  516. * */
  517. /* *
  518. *
  519. * API Options
  520. *
  521. * */
  522. /**
  523. * A `SMA` series. If the [type](#series.sma.type) option is not specified, it
  524. * is inherited from [chart.type](#chart.type).
  525. *
  526. * @extends series,plotOptions.sma
  527. * @since 6.0.0
  528. * @product highstock
  529. * @excluding dataParser, dataURL, useOhlcData
  530. * @requires stock/indicators/indicators
  531. * @apioption series.sma
  532. */
  533. ''; // adds doclet above to the transpiled file
  534. return SMAIndicator;
  535. });
  536. _registerModule(_modules, 'masters/indicators/indicators.src.js', [], function () {
  537. });
  538. }));