mfi.src.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * @license Highstock JS v8.1.2 (2020-06-16)
  3. *
  4. * Money Flow Index indicator for Highstock
  5. *
  6. * (c) 2010-2019 Grzegorz Blachliński
  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/mfi', ['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, 'indicators/mfi.src.js', [_modules['parts/Utilities.js']], function (U) {
  32. /* *
  33. *
  34. * Money Flow Index indicator for Highstock
  35. *
  36. * (c) 2010-2020 Grzegorz Blachliński
  37. *
  38. * License: www.highcharts.com/license
  39. *
  40. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  41. *
  42. * */
  43. var error = U.error, isArray = U.isArray, seriesType = U.seriesType;
  44. /* eslint-disable require-jsdoc */
  45. // Utils:
  46. function sumArray(array) {
  47. return array.reduce(function (prev, cur) {
  48. return prev + cur;
  49. });
  50. }
  51. function toFixed(a, n) {
  52. return parseFloat(a.toFixed(n));
  53. }
  54. function calculateTypicalPrice(point) {
  55. return (point[1] + point[2] + point[3]) / 3;
  56. }
  57. function calculateRawMoneyFlow(typicalPrice, volume) {
  58. return typicalPrice * volume;
  59. }
  60. /* eslint-enable require-jsdoc */
  61. /**
  62. * The MFI series type.
  63. *
  64. * @private
  65. * @class
  66. * @name Highcharts.seriesTypes.mfi
  67. *
  68. * @augments Highcharts.Series
  69. */
  70. seriesType('mfi', 'sma',
  71. /**
  72. * Money Flow Index. This series requires `linkedTo` option to be set and
  73. * should be loaded after the `stock/indicators/indicators.js` file.
  74. *
  75. * @sample stock/indicators/mfi
  76. * Money Flow Index Indicator
  77. *
  78. * @extends plotOptions.sma
  79. * @since 6.0.0
  80. * @product highstock
  81. * @requires stock/indicators/indicators
  82. * @requires stock/indicators/mfi
  83. * @optionparent plotOptions.mfi
  84. */
  85. {
  86. /**
  87. * @excluding index
  88. */
  89. params: {
  90. period: 14,
  91. /**
  92. * The id of volume series which is mandatory.
  93. * For example using OHLC data, volumeSeriesID='volume' means
  94. * the indicator will be calculated using OHLC and volume values.
  95. */
  96. volumeSeriesID: 'volume',
  97. /**
  98. * Number of maximum decimals that are used in MFI calculations.
  99. */
  100. decimals: 4
  101. }
  102. },
  103. /**
  104. * @lends Highcharts.Series#
  105. */
  106. {
  107. nameBase: 'Money Flow Index',
  108. getValues: function (series, params) {
  109. var period = params.period, xVal = series.xData, yVal = series.yData, yValLen = yVal ? yVal.length : 0, decimals = params.decimals,
  110. // MFI starts calculations from the second point
  111. // Cause we need to calculate change between two points
  112. range = 1, volumeSeries = series.chart.get(params.volumeSeriesID), yValVolume = (volumeSeries && volumeSeries.yData), MFI = [], isUp = false, xData = [], yData = [], positiveMoneyFlow = [], negativeMoneyFlow = [], newTypicalPrice, oldTypicalPrice, rawMoneyFlow, negativeMoneyFlowSum, positiveMoneyFlowSum, moneyFlowRatio, MFIPoint, i;
  113. if (!volumeSeries) {
  114. error('Series ' +
  115. params.volumeSeriesID +
  116. ' not found! Check `volumeSeriesID`.', true, series.chart);
  117. return;
  118. }
  119. // MFI requires high low and close values
  120. if ((xVal.length <= period) || !isArray(yVal[0]) ||
  121. yVal[0].length !== 4 ||
  122. !yValVolume) {
  123. return;
  124. }
  125. // Calculate first typical price
  126. newTypicalPrice = calculateTypicalPrice(yVal[range]);
  127. // Accumulate first N-points
  128. while (range < period + 1) {
  129. // Calculate if up or down
  130. oldTypicalPrice = newTypicalPrice;
  131. newTypicalPrice = calculateTypicalPrice(yVal[range]);
  132. isUp = newTypicalPrice >= oldTypicalPrice;
  133. // Calculate raw money flow
  134. rawMoneyFlow = calculateRawMoneyFlow(newTypicalPrice, yValVolume[range]);
  135. // Add to array
  136. positiveMoneyFlow.push(isUp ? rawMoneyFlow : 0);
  137. negativeMoneyFlow.push(isUp ? 0 : rawMoneyFlow);
  138. range++;
  139. }
  140. for (i = range - 1; i < yValLen; i++) {
  141. if (i > range - 1) {
  142. // Remove first point from array
  143. positiveMoneyFlow.shift();
  144. negativeMoneyFlow.shift();
  145. // Calculate if up or down
  146. oldTypicalPrice = newTypicalPrice;
  147. newTypicalPrice = calculateTypicalPrice(yVal[i]);
  148. isUp = newTypicalPrice > oldTypicalPrice;
  149. // Calculate raw money flow
  150. rawMoneyFlow = calculateRawMoneyFlow(newTypicalPrice, yValVolume[i]);
  151. // Add to array
  152. positiveMoneyFlow.push(isUp ? rawMoneyFlow : 0);
  153. negativeMoneyFlow.push(isUp ? 0 : rawMoneyFlow);
  154. }
  155. // Calculate sum of negative and positive money flow:
  156. negativeMoneyFlowSum = sumArray(negativeMoneyFlow);
  157. positiveMoneyFlowSum = sumArray(positiveMoneyFlow);
  158. moneyFlowRatio = positiveMoneyFlowSum / negativeMoneyFlowSum;
  159. MFIPoint = toFixed(100 - (100 / (1 + moneyFlowRatio)), decimals);
  160. MFI.push([xVal[i], MFIPoint]);
  161. xData.push(xVal[i]);
  162. yData.push(MFIPoint);
  163. }
  164. return {
  165. values: MFI,
  166. xData: xData,
  167. yData: yData
  168. };
  169. }
  170. });
  171. /**
  172. * A `MFI` series. If the [type](#series.mfi.type) option is not specified, it
  173. * is inherited from [chart.type](#chart.type).
  174. *
  175. * @extends series,plotOptions.mfi
  176. * @since 6.0.0
  177. * @excluding dataParser, dataURL
  178. * @product highstock
  179. * @requires stock/indicators/indicators
  180. * @requires stock/indicators/mfi
  181. * @apioption series.mfi
  182. */
  183. ''; // to include the above in the js output
  184. });
  185. _registerModule(_modules, 'masters/indicators/mfi.src.js', [], function () {
  186. });
  187. }));