CMFIndicator.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /* *
  2. *
  3. * (c) 2010-2020 Highsoft AS
  4. *
  5. * Author: Sebastian Domas
  6. *
  7. * Chaikin Money Flow indicator for Highstock
  8. *
  9. * License: www.highcharts.com/license
  10. *
  11. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  12. *
  13. * */
  14. 'use strict';
  15. import U from '../../Core/Utilities.js';
  16. var seriesType = U.seriesType;
  17. /**
  18. * The CMF series type.
  19. *
  20. * @private
  21. * @class
  22. * @name Highcharts.seriesTypes.cmf
  23. *
  24. * @augments Highcharts.Series
  25. */
  26. seriesType('cmf', 'sma',
  27. /**
  28. * Chaikin Money Flow indicator (cmf).
  29. *
  30. * @sample stock/indicators/cmf/
  31. * Chaikin Money Flow indicator
  32. *
  33. * @extends plotOptions.sma
  34. * @since 6.0.0
  35. * @excluding animationLimit
  36. * @product highstock
  37. * @requires stock/indicators/indicators
  38. * @requires stock/indicators/cmf
  39. * @optionparent plotOptions.cmf
  40. */
  41. {
  42. params: {
  43. period: 14,
  44. /**
  45. * The id of another series to use its data as volume data for the
  46. * indiator calculation.
  47. */
  48. volumeSeriesID: 'volume'
  49. }
  50. },
  51. /**
  52. * @lends Highcharts.Series#
  53. */
  54. {
  55. nameBase: 'Chaikin Money Flow',
  56. /**
  57. * Checks if the series and volumeSeries are accessible, number of
  58. * points.x is longer than period, is series has OHLC data
  59. * @private
  60. * @param {Highcharts.CMFIndicator} this indicator to use.
  61. * @return {boolean} True if series is valid and can be computed,
  62. * otherwise false.
  63. */
  64. isValid: function () {
  65. var chart = this.chart, options = this.options, series = this.linkedParent, volumeSeries = (this.volumeSeries ||
  66. (this.volumeSeries =
  67. chart.get(options.params.volumeSeriesID))), isSeriesOHLC = (series &&
  68. series.yData &&
  69. series.yData[0].length === 4);
  70. /**
  71. * @private
  72. * @param {Highcharts.Series} serie to check length validity on.
  73. * @return {boolean|undefined} true if length is valid.
  74. */
  75. function isLengthValid(serie) {
  76. return serie.xData &&
  77. serie.xData.length >= options.params.period;
  78. }
  79. return !!(series &&
  80. volumeSeries &&
  81. isLengthValid(series) &&
  82. isLengthValid(volumeSeries) && isSeriesOHLC);
  83. },
  84. /**
  85. * Returns indicator's data.
  86. * @private
  87. * @param {Highcharts.CMFIndicator} this indicator to use.
  88. * @param {Highcharts.Series} series to calculate values from
  89. * @param {Highcharts.CMFIndicatorParamsOptions} params to pass
  90. * @return {boolean|Highcharts.IndicatorNullableValuesObject} Returns false if the
  91. * indicator is not valid, otherwise returns Values object.
  92. */
  93. getValues: function (series, params) {
  94. if (!this.isValid()) {
  95. return;
  96. }
  97. return this.getMoneyFlow(series.xData, series.yData, this.volumeSeries.yData, params.period);
  98. },
  99. /**
  100. * @private
  101. * @param {Array<number>} xData - x timestamp values
  102. * @param {Array<number>} seriesYData - yData of basic series
  103. * @param {Array<number>} volumeSeriesYData - yData of volume series
  104. * @param {number} period - indicator's param
  105. * @return {Highcharts.IndicatorNullableValuesObject} object containing computed money
  106. * flow data
  107. */
  108. getMoneyFlow: function (xData, seriesYData, volumeSeriesYData, period) {
  109. var len = seriesYData.length, moneyFlowVolume = [], sumVolume = 0, sumMoneyFlowVolume = 0, moneyFlowXData = [], moneyFlowYData = [], values = [], i, point, nullIndex = -1;
  110. /**
  111. * Calculates money flow volume, changes i, nullIndex vars from
  112. * upper scope!
  113. * @private
  114. * @param {Array<number>} ohlc - OHLC point
  115. * @param {number} volume - Volume point's y value
  116. * @return {number|null} - volume * moneyFlowMultiplier
  117. **/
  118. function getMoneyFlowVolume(ohlc, volume) {
  119. var high = ohlc[1], low = ohlc[2], close = ohlc[3], isValid = volume !== null &&
  120. high !== null &&
  121. low !== null &&
  122. close !== null &&
  123. high !== low;
  124. /**
  125. * @private
  126. * @param {number} h - High value
  127. * @param {number} l - Low value
  128. * @param {number} c - Close value
  129. * @return {number} calculated multiplier for the point
  130. **/
  131. function getMoneyFlowMultiplier(h, l, c) {
  132. return ((c - l) - (h - c)) / (h - l);
  133. }
  134. return isValid ?
  135. getMoneyFlowMultiplier(high, low, close) * volume :
  136. ((nullIndex = i), null);
  137. }
  138. if (period > 0 && period <= len) {
  139. for (i = 0; i < period; i++) {
  140. moneyFlowVolume[i] = getMoneyFlowVolume(seriesYData[i], volumeSeriesYData[i]);
  141. sumVolume += volumeSeriesYData[i];
  142. sumMoneyFlowVolume += moneyFlowVolume[i];
  143. }
  144. moneyFlowXData.push(xData[i - 1]);
  145. moneyFlowYData.push(i - nullIndex >= period && sumVolume !== 0 ?
  146. sumMoneyFlowVolume / sumVolume :
  147. null);
  148. values.push([moneyFlowXData[0], moneyFlowYData[0]]);
  149. for (; i < len; i++) {
  150. moneyFlowVolume[i] = getMoneyFlowVolume(seriesYData[i], volumeSeriesYData[i]);
  151. sumVolume -= volumeSeriesYData[i - period];
  152. sumVolume += volumeSeriesYData[i];
  153. sumMoneyFlowVolume -= moneyFlowVolume[i - period];
  154. sumMoneyFlowVolume += moneyFlowVolume[i];
  155. point = [
  156. xData[i],
  157. i - nullIndex >= period ?
  158. sumMoneyFlowVolume / sumVolume :
  159. null
  160. ];
  161. moneyFlowXData.push(point[0]);
  162. moneyFlowYData.push(point[1]);
  163. values.push([point[0], point[1]]);
  164. }
  165. }
  166. return {
  167. values: values,
  168. xData: moneyFlowXData,
  169. yData: moneyFlowYData
  170. };
  171. }
  172. });
  173. /**
  174. * A `CMF` series. If the [type](#series.cmf.type) option is not
  175. * specified, it is inherited from [chart.type](#chart.type).
  176. *
  177. * @extends series,plotOptions.cmf
  178. * @since 6.0.0
  179. * @product highstock
  180. * @excluding dataParser, dataURL
  181. * @requires stock/indicators/indicators
  182. * @requires stock/indicators/cmf
  183. * @apioption series.cmf
  184. */
  185. ''; // adds doclet above to the transpiled file