ichimoku-kinko-hyo.src.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. /**
  2. * @license Highstock JS v8.2.0 (2020-08-20)
  3. *
  4. * Indicator series type for Highstock
  5. *
  6. * (c) 2010-2019 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/ichimoku-kinko-hyo', ['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, 'Stock/Indicators/IKHIndicator.js', [_modules['Core/Globals.js'], _modules['Core/Color.js'], _modules['Core/Utilities.js']], function (H, Color, U) {
  32. /* *
  33. *
  34. * License: www.highcharts.com/license
  35. *
  36. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  37. *
  38. * */
  39. /* eslint-enable @typescript-eslint/interface-name-prefix */
  40. var color = Color.parse;
  41. var defined = U.defined,
  42. isArray = U.isArray,
  43. merge = U.merge,
  44. objectEach = U.objectEach,
  45. seriesType = U.seriesType;
  46. var UNDEFINED,
  47. SMA = H.seriesTypes.sma;
  48. /* eslint-disable require-jsdoc */
  49. // Utils:
  50. function maxHigh(arr) {
  51. return arr.reduce(function (max, res) {
  52. return Math.max(max, res[1]);
  53. }, -Infinity);
  54. }
  55. function minLow(arr) {
  56. return arr.reduce(function (min, res) {
  57. return Math.min(min, res[2]);
  58. }, Infinity);
  59. }
  60. function highlowLevel(arr) {
  61. return {
  62. high: maxHigh(arr),
  63. low: minLow(arr)
  64. };
  65. }
  66. function getClosestPointRange(axis) {
  67. var closestDataRange,
  68. loopLength,
  69. distance,
  70. xData,
  71. i;
  72. axis.series.forEach(function (series) {
  73. if (series.xData) {
  74. xData = series.xData;
  75. loopLength = series.xIncrement ? 1 : xData.length - 1;
  76. for (i = loopLength; i > 0; i--) {
  77. distance = xData[i] - xData[i - 1];
  78. if (closestDataRange === UNDEFINED ||
  79. distance < closestDataRange) {
  80. closestDataRange = distance;
  81. }
  82. }
  83. }
  84. });
  85. return closestDataRange;
  86. }
  87. // Check two lines intersection (line a1-a2 and b1-b2)
  88. // Source: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
  89. function checkLineIntersection(a1, a2, b1, b2) {
  90. if (a1 && a2 && b1 && b2) {
  91. var saX = a2.plotX - a1.plotX, // Auxiliary section a2-a1 X
  92. saY = a2.plotY - a1.plotY, // Auxiliary section a2-a1 Y
  93. sbX = b2.plotX - b1.plotX, // Auxiliary section b2-b1 X
  94. sbY = b2.plotY - b1.plotY, // Auxiliary section b2-b1 Y
  95. sabX = a1.plotX - b1.plotX, // Auxiliary section a1-b1 X
  96. sabY = a1.plotY - b1.plotY, // Auxiliary section a1-b1 Y
  97. // First degree Bézier parameters
  98. u,
  99. t;
  100. u = (-saY * sabX + saX * sabY) / (-sbX * saY + saX * sbY);
  101. t = (sbX * sabY - sbY * sabX) / (-sbX * saY + saX * sbY);
  102. if (u >= 0 && u <= 1 && t >= 0 && t <= 1) {
  103. return {
  104. plotX: a1.plotX + (t * saX),
  105. plotY: a1.plotY + (t * saY)
  106. };
  107. }
  108. }
  109. return false;
  110. }
  111. // Parameter opt (indicator options object) include indicator, points,
  112. // nextPoints, color, options, gappedExtend and graph properties
  113. function drawSenkouSpan(opt) {
  114. var indicator = opt.indicator;
  115. indicator.points = opt.points;
  116. indicator.nextPoints = opt.nextPoints;
  117. indicator.color = opt.color;
  118. indicator.options = merge(opt.options.senkouSpan.styles, opt.gap);
  119. indicator.graph = opt.graph;
  120. indicator.fillGraph = true;
  121. SMA.prototype.drawGraph.call(indicator);
  122. }
  123. // Data integrity in Ichimoku is different than default "averages":
  124. // Point: [undefined, value, value, ...] is correct
  125. // Point: [undefined, undefined, undefined, ...] is incorrect
  126. H.approximations['ichimoku-averages'] = function () {
  127. var ret = [],
  128. isEmptyRange;
  129. [].forEach.call(arguments, function (arr, i) {
  130. ret.push(H.approximations.average(arr));
  131. isEmptyRange = !isEmptyRange && typeof ret[i] === 'undefined';
  132. });
  133. // Return undefined when first elem. is undefined and let
  134. // sum method handle null (#7377)
  135. return isEmptyRange ? void 0 : ret;
  136. };
  137. /* eslint-enable require-jsdoc */
  138. /**
  139. * The IKH series type.
  140. *
  141. * @private
  142. * @class
  143. * @name Highcharts.seriesTypes.ikh
  144. *
  145. * @augments Highcharts.Series
  146. */
  147. seriesType('ikh', 'sma',
  148. /**
  149. * Ichimoku Kinko Hyo (IKH). This series requires `linkedTo` option to be
  150. * set.
  151. *
  152. * @sample stock/indicators/ichimoku-kinko-hyo
  153. * Ichimoku Kinko Hyo indicator
  154. *
  155. * @extends plotOptions.sma
  156. * @since 6.0.0
  157. * @excluding allAreas, colorAxis, compare, compareBase, joinBy, keys,
  158. * navigatorOptions, pointInterval, pointIntervalUnit,
  159. * pointPlacement, pointRange, pointStart, showInNavigator,
  160. * stacking
  161. * @product highstock
  162. * @requires stock/indicators/indicators
  163. * @requires stock/indicators/ichimoku-kinko-hyo
  164. * @optionparent plotOptions.ikh
  165. */
  166. {
  167. params: {
  168. period: 26,
  169. /**
  170. * The base period for Tenkan calculations.
  171. */
  172. periodTenkan: 9,
  173. /**
  174. * The base period for Senkou Span B calculations
  175. */
  176. periodSenkouSpanB: 52
  177. },
  178. marker: {
  179. enabled: false
  180. },
  181. tooltip: {
  182. pointFormat: '<span style="color:{point.color}">\u25CF</span> <b> {series.name}</b><br/>' +
  183. 'TENKAN SEN: {point.tenkanSen:.3f}<br/>' +
  184. 'KIJUN SEN: {point.kijunSen:.3f}<br/>' +
  185. 'CHIKOU SPAN: {point.chikouSpan:.3f}<br/>' +
  186. 'SENKOU SPAN A: {point.senkouSpanA:.3f}<br/>' +
  187. 'SENKOU SPAN B: {point.senkouSpanB:.3f}<br/>'
  188. },
  189. /**
  190. * The styles for Tenkan line
  191. */
  192. tenkanLine: {
  193. styles: {
  194. /**
  195. * Pixel width of the line.
  196. */
  197. lineWidth: 1,
  198. /**
  199. * Color of the line.
  200. *
  201. * @type {Highcharts.ColorString}
  202. */
  203. lineColor: void 0
  204. }
  205. },
  206. /**
  207. * The styles for Kijun line
  208. */
  209. kijunLine: {
  210. styles: {
  211. /**
  212. * Pixel width of the line.
  213. */
  214. lineWidth: 1,
  215. /**
  216. * Color of the line.
  217. *
  218. * @type {Highcharts.ColorString}
  219. */
  220. lineColor: void 0
  221. }
  222. },
  223. /**
  224. * The styles for Chikou line
  225. */
  226. chikouLine: {
  227. styles: {
  228. /**
  229. * Pixel width of the line.
  230. */
  231. lineWidth: 1,
  232. /**
  233. * Color of the line.
  234. *
  235. * @type {Highcharts.ColorString}
  236. */
  237. lineColor: void 0
  238. }
  239. },
  240. /**
  241. * The styles for Senkou Span A line
  242. */
  243. senkouSpanA: {
  244. styles: {
  245. /**
  246. * Pixel width of the line.
  247. */
  248. lineWidth: 1,
  249. /**
  250. * Color of the line.
  251. *
  252. * @type {Highcharts.ColorString}
  253. */
  254. lineColor: void 0
  255. }
  256. },
  257. /**
  258. * The styles for Senkou Span B line
  259. */
  260. senkouSpanB: {
  261. styles: {
  262. /**
  263. * Pixel width of the line.
  264. */
  265. lineWidth: 1,
  266. /**
  267. * Color of the line.
  268. *
  269. * @type {Highcharts.ColorString}
  270. */
  271. lineColor: void 0
  272. }
  273. },
  274. /**
  275. * The styles for area between Senkou Span A and B.
  276. */
  277. senkouSpan: {
  278. /**
  279. * Color of the area between Senkou Span A and B,
  280. * when Senkou Span A is above Senkou Span B. Note that if
  281. * a `style.fill` is defined, the `color` takes precedence and
  282. * the `style.fill` is ignored.
  283. *
  284. * @see [senkouSpan.styles.fill](#series.ikh.senkouSpan.styles.fill)
  285. *
  286. * @sample stock/indicators/ichimoku-kinko-hyo
  287. * Ichimoku Kinko Hyo color
  288. *
  289. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  290. * @since 7.0.0
  291. * @apioption plotOptions.ikh.senkouSpan.color
  292. */
  293. /**
  294. * Color of the area between Senkou Span A and B,
  295. * when Senkou Span A is under Senkou Span B.
  296. *
  297. * @sample stock/indicators/ikh-negative-color
  298. * Ichimoku Kinko Hyo negativeColor
  299. *
  300. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  301. * @since 7.0.0
  302. * @apioption plotOptions.ikh.senkouSpan.negativeColor
  303. */
  304. styles: {
  305. /**
  306. * Color of the area between Senkou Span A and B.
  307. *
  308. * @deprecated
  309. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  310. */
  311. fill: 'rgba(255, 0, 0, 0.5)'
  312. }
  313. },
  314. dataGrouping: {
  315. approximation: 'ichimoku-averages'
  316. }
  317. },
  318. /**
  319. * @lends Highcharts.Series#
  320. */
  321. {
  322. pointArrayMap: [
  323. 'tenkanSen',
  324. 'kijunSen',
  325. 'chikouSpan',
  326. 'senkouSpanA',
  327. 'senkouSpanB'
  328. ],
  329. pointValKey: 'tenkanSen',
  330. nameComponents: ['periodSenkouSpanB', 'period', 'periodTenkan'],
  331. init: function () {
  332. SMA.prototype.init.apply(this, arguments);
  333. // Set default color for lines:
  334. this.options = merge({
  335. tenkanLine: {
  336. styles: {
  337. lineColor: this.color
  338. }
  339. },
  340. kijunLine: {
  341. styles: {
  342. lineColor: this.color
  343. }
  344. },
  345. chikouLine: {
  346. styles: {
  347. lineColor: this.color
  348. }
  349. },
  350. senkouSpanA: {
  351. styles: {
  352. lineColor: this.color,
  353. fill: color(this.color).setOpacity(0.5).get()
  354. }
  355. },
  356. senkouSpanB: {
  357. styles: {
  358. lineColor: this.color,
  359. fill: color(this.color).setOpacity(0.5).get()
  360. }
  361. },
  362. senkouSpan: {
  363. styles: {
  364. fill: color(this.color).setOpacity(0.2).get()
  365. }
  366. }
  367. }, this.options);
  368. },
  369. toYData: function (point) {
  370. return [
  371. point.tenkanSen,
  372. point.kijunSen,
  373. point.chikouSpan,
  374. point.senkouSpanA,
  375. point.senkouSpanB
  376. ];
  377. },
  378. translate: function () {
  379. var indicator = this;
  380. SMA.prototype.translate.apply(indicator);
  381. indicator.points.forEach(function (point) {
  382. indicator.pointArrayMap.forEach(function (value) {
  383. if (defined(point[value])) {
  384. point['plot' + value] =
  385. indicator.yAxis.toPixels(point[value], true);
  386. // Add extra parameters for support tooltip in moved
  387. // lines
  388. point.plotY = point['plot' + value];
  389. point.tooltipPos = [
  390. point.plotX,
  391. point['plot' + value]
  392. ];
  393. point.isNull = false;
  394. }
  395. });
  396. });
  397. },
  398. // One does not simply
  399. // Render five linesZ
  400. // And an arearange
  401. // In just one series..
  402. drawGraph: function () {
  403. var indicator = this,
  404. mainLinePoints = (indicator.points),
  405. pointsLength = mainLinePoints.length,
  406. mainLineOptions = (indicator.options),
  407. mainLinePath = (indicator.graph),
  408. mainColor = indicator.color,
  409. gappedExtend = {
  410. options: {
  411. gapSize: mainLineOptions.gapSize
  412. }
  413. },
  414. pointArrayMapLength = indicator.pointArrayMap.length,
  415. allIchimokuPoints = [[],
  416. [],
  417. [],
  418. [],
  419. [],
  420. []],
  421. ikhMap = {
  422. tenkanLine: allIchimokuPoints[0],
  423. kijunLine: allIchimokuPoints[1],
  424. chikouLine: allIchimokuPoints[2],
  425. senkouSpanA: allIchimokuPoints[3],
  426. senkouSpanB: allIchimokuPoints[4],
  427. senkouSpan: allIchimokuPoints[5]
  428. },
  429. intersectIndexColl = [],
  430. senkouSpanOptions = indicator.options.senkouSpan,
  431. color = (senkouSpanOptions.color ||
  432. senkouSpanOptions.styles.fill),
  433. negativeColor = (senkouSpanOptions.negativeColor),
  434. // Points to create color and negativeColor senkouSpan
  435. points = [
  436. [],
  437. [] // Points negative color
  438. ],
  439. // For span, we need an access to the next points, used in
  440. // getGraphPath()
  441. nextPoints = [
  442. [],
  443. [] // NextPoints negative color
  444. ],
  445. lineIndex = 0,
  446. position,
  447. point,
  448. i,
  449. startIntersect,
  450. endIntersect,
  451. sectionPoints,
  452. sectionNextPoints,
  453. pointsPlotYSum,
  454. nextPointsPlotYSum,
  455. senkouSpanTempColor,
  456. concatArrIndex,
  457. j,
  458. k;
  459. indicator.ikhMap = ikhMap;
  460. // Generate points for all lines and spans lines:
  461. while (pointsLength--) {
  462. point = mainLinePoints[pointsLength];
  463. for (i = 0; i < pointArrayMapLength; i++) {
  464. position = indicator.pointArrayMap[i];
  465. if (defined(point[position])) {
  466. allIchimokuPoints[i].push({
  467. plotX: point.plotX,
  468. plotY: point['plot' + position],
  469. isNull: false
  470. });
  471. }
  472. }
  473. if (negativeColor &&
  474. pointsLength !== mainLinePoints.length - 1) {
  475. // Check if lines intersect
  476. var index = ikhMap.senkouSpanB.length - 1,
  477. intersect = checkLineIntersection(ikhMap.senkouSpanA[index - 1],
  478. ikhMap.senkouSpanA[index],
  479. ikhMap.senkouSpanB[index - 1],
  480. ikhMap.senkouSpanB[index]),
  481. intersectPointObj = {
  482. plotX: intersect.plotX,
  483. plotY: intersect.plotY,
  484. isNull: false,
  485. intersectPoint: true
  486. };
  487. if (intersect) {
  488. // Add intersect point to ichimoku points collection
  489. // Create senkouSpan sections
  490. ikhMap.senkouSpanA.splice(index, 0, intersectPointObj);
  491. ikhMap.senkouSpanB.splice(index, 0, intersectPointObj);
  492. intersectIndexColl.push(index);
  493. }
  494. }
  495. }
  496. // Modify options and generate lines:
  497. objectEach(ikhMap, function (values, lineName) {
  498. if (mainLineOptions[lineName] &&
  499. lineName !== 'senkouSpan') {
  500. // First line is rendered by default option
  501. indicator.points = allIchimokuPoints[lineIndex];
  502. indicator.options = merge(mainLineOptions[lineName].styles, gappedExtend);
  503. indicator.graph = indicator['graph' + lineName];
  504. indicator.fillGraph = false;
  505. indicator.color = mainColor;
  506. SMA.prototype.drawGraph.call(indicator);
  507. // Now save line
  508. indicator['graph' + lineName] = indicator.graph;
  509. }
  510. lineIndex++;
  511. });
  512. // Generate senkouSpan area:
  513. // If graphColection exist then remove svg
  514. // element and indicator property
  515. if (indicator.graphCollection) {
  516. indicator.graphCollection.forEach(function (graphName) {
  517. indicator[graphName].destroy();
  518. delete indicator[graphName];
  519. });
  520. }
  521. // Clean grapCollection or initialize it
  522. indicator.graphCollection = [];
  523. // When user set negativeColor property
  524. if (negativeColor &&
  525. ikhMap.senkouSpanA[0] &&
  526. ikhMap.senkouSpanB[0]) {
  527. // Add first and last point to senkouSpan area sections
  528. intersectIndexColl.unshift(0);
  529. intersectIndexColl.push(ikhMap.senkouSpanA.length - 1);
  530. // Populate points and nextPoints arrays
  531. for (j = 0; j < intersectIndexColl.length - 1; j++) {
  532. startIntersect = intersectIndexColl[j];
  533. endIntersect = intersectIndexColl[j + 1];
  534. sectionPoints = ikhMap.senkouSpanB.slice(startIntersect, endIntersect + 1);
  535. sectionNextPoints = ikhMap.senkouSpanA.slice(startIntersect, endIntersect + 1);
  536. // Add points to color or negativeColor arrays
  537. // Check the middle point (if exist)
  538. if (Math.floor(sectionPoints.length / 2) >= 1) {
  539. var x = Math.floor(sectionPoints.length / 2);
  540. // When middle points has equal values
  541. // Compare all ponints plotY value sum
  542. if (sectionPoints[x].plotY ===
  543. sectionNextPoints[x].plotY) {
  544. pointsPlotYSum = 0;
  545. nextPointsPlotYSum = 0;
  546. for (k = 0; k < sectionPoints.length; k++) {
  547. pointsPlotYSum +=
  548. sectionPoints[k].plotY;
  549. nextPointsPlotYSum +=
  550. sectionNextPoints[k].plotY;
  551. }
  552. concatArrIndex = (pointsPlotYSum > nextPointsPlotYSum ? 0 : 1);
  553. points[concatArrIndex] = (points[concatArrIndex].concat(sectionPoints));
  554. nextPoints[concatArrIndex] = (nextPoints[concatArrIndex].concat(sectionNextPoints));
  555. }
  556. else {
  557. // Compare middle point of the section
  558. concatArrIndex = (sectionPoints[x].plotY >
  559. sectionNextPoints[x].plotY ?
  560. 0 : 1);
  561. points[concatArrIndex] = (points[concatArrIndex].concat(sectionPoints));
  562. nextPoints[concatArrIndex] = (nextPoints[concatArrIndex].concat(sectionNextPoints));
  563. }
  564. }
  565. else {
  566. // Compare first point of the section
  567. concatArrIndex = (sectionPoints[0].plotY >
  568. sectionNextPoints[0].plotY ?
  569. 0 : 1);
  570. points[concatArrIndex] = (points[concatArrIndex].concat(sectionPoints));
  571. nextPoints[concatArrIndex] = (nextPoints[concatArrIndex].concat(sectionNextPoints));
  572. }
  573. }
  574. // Render color and negativeColor paths
  575. [
  576. 'graphsenkouSpanColor', 'graphsenkouSpanNegativeColor'
  577. ].forEach(function (areaName, i) {
  578. if (points[i].length && nextPoints[i].length) {
  579. senkouSpanTempColor = (i === 0) ?
  580. color : negativeColor;
  581. drawSenkouSpan({
  582. indicator: indicator,
  583. points: points[i],
  584. nextPoints: nextPoints[i],
  585. color: senkouSpanTempColor,
  586. options: mainLineOptions,
  587. gap: gappedExtend,
  588. graph: indicator[areaName]
  589. });
  590. // Now save line
  591. indicator[areaName] = indicator.graph;
  592. indicator.graphCollection.push(areaName);
  593. }
  594. });
  595. }
  596. else {
  597. // When user set only senkouSpan style.fill property
  598. drawSenkouSpan({
  599. indicator: indicator,
  600. points: ikhMap.senkouSpanB,
  601. nextPoints: ikhMap.senkouSpanA,
  602. color: color,
  603. options: mainLineOptions,
  604. gap: gappedExtend,
  605. graph: indicator.graphsenkouSpan
  606. });
  607. // Now save line
  608. indicator.graphsenkouSpan = indicator.graph;
  609. }
  610. // Clean temporary properties:
  611. delete indicator.nextPoints;
  612. delete indicator.fillGraph;
  613. // Restore options and draw the Tenkan line:
  614. indicator.points = mainLinePoints;
  615. indicator.options = mainLineOptions;
  616. indicator.graph = mainLinePath;
  617. },
  618. getGraphPath: function (points) {
  619. var indicator = this,
  620. path = [],
  621. spanA,
  622. spanAarr = [];
  623. points = points || this.points;
  624. // Render Senkou Span
  625. if (indicator.fillGraph && indicator.nextPoints) {
  626. spanA = SMA.prototype.getGraphPath.call(indicator,
  627. // Reverse points, so Senkou Span A will start from the end:
  628. indicator.nextPoints);
  629. spanA[0][0] = 'L';
  630. path = SMA.prototype.getGraphPath.call(indicator, points);
  631. spanAarr = spanA.slice(0, path.length);
  632. for (var i = spanAarr.length - 1; i >= 0; i--) {
  633. path.push(spanAarr[i]);
  634. }
  635. }
  636. else {
  637. path = SMA.prototype.getGraphPath.apply(indicator, arguments);
  638. }
  639. return path;
  640. },
  641. getValues: function (series, params) {
  642. var period = params.period,
  643. periodTenkan = params.periodTenkan,
  644. periodSenkouSpanB = params.periodSenkouSpanB,
  645. xVal = series.xData,
  646. yVal = series.yData,
  647. xAxis = series.xAxis,
  648. yValLen = (yVal && yVal.length) || 0,
  649. closestPointRange = getClosestPointRange(xAxis),
  650. IKH = [],
  651. xData = [],
  652. dateStart,
  653. date,
  654. slicedTSY,
  655. slicedKSY,
  656. slicedSSBY,
  657. pointTS,
  658. pointKS,
  659. pointSSB,
  660. i,
  661. TS,
  662. KS,
  663. CS,
  664. SSA,
  665. SSB;
  666. // Ikh requires close value
  667. if (xVal.length <= period ||
  668. !isArray(yVal[0]) ||
  669. yVal[0].length !== 4) {
  670. return;
  671. }
  672. // Add timestamps at the beginning
  673. dateStart = xVal[0] - (period * closestPointRange);
  674. for (i = 0; i < period; i++) {
  675. xData.push(dateStart + i * closestPointRange);
  676. }
  677. for (i = 0; i < yValLen; i++) {
  678. // Tenkan Sen
  679. if (i >= periodTenkan) {
  680. slicedTSY = yVal.slice(i - periodTenkan, i);
  681. pointTS = highlowLevel(slicedTSY);
  682. TS = (pointTS.high + pointTS.low) / 2;
  683. }
  684. if (i >= period) {
  685. slicedKSY = yVal.slice(i - period, i);
  686. pointKS = highlowLevel(slicedKSY);
  687. KS = (pointKS.high + pointKS.low) / 2;
  688. SSA = (TS + KS) / 2;
  689. }
  690. if (i >= periodSenkouSpanB) {
  691. slicedSSBY = yVal.slice(i - periodSenkouSpanB, i);
  692. pointSSB = highlowLevel(slicedSSBY);
  693. SSB = (pointSSB.high + pointSSB.low) / 2;
  694. }
  695. CS = yVal[i][3];
  696. date = xVal[i];
  697. if (IKH[i] === UNDEFINED) {
  698. IKH[i] = [];
  699. }
  700. if (IKH[i + period] === UNDEFINED) {
  701. IKH[i + period] = [];
  702. }
  703. IKH[i + period][0] = TS;
  704. IKH[i + period][1] = KS;
  705. IKH[i + period][2] = UNDEFINED;
  706. IKH[i][2] = CS;
  707. if (i <= period) {
  708. IKH[i + period][3] = UNDEFINED;
  709. IKH[i + period][4] = UNDEFINED;
  710. }
  711. if (IKH[i + 2 * period] === UNDEFINED) {
  712. IKH[i + 2 * period] = [];
  713. }
  714. IKH[i + 2 * period][3] = SSA;
  715. IKH[i + 2 * period][4] = SSB;
  716. xData.push(date);
  717. }
  718. // Add timestamps for further points
  719. for (i = 1; i <= period; i++) {
  720. xData.push(date + i * closestPointRange);
  721. }
  722. return {
  723. values: IKH,
  724. xData: xData,
  725. yData: IKH
  726. };
  727. }
  728. });
  729. /**
  730. * A `IKH` series. If the [type](#series.ikh.type) option is not
  731. * specified, it is inherited from [chart.type](#chart.type).
  732. *
  733. * @extends series,plotOptions.ikh
  734. * @since 6.0.0
  735. * @product highstock
  736. * @excluding dataParser, dataURL
  737. * @requires stock/indicators/indicators
  738. * @requires stock/indicators/ichimoku-kinko-hyo
  739. * @apioption series.ikh
  740. */
  741. ''; // add doclet above to transpiled file
  742. });
  743. _registerModule(_modules, 'masters/indicators/ichimoku-kinko-hyo.src.js', [], function () {
  744. });
  745. }));