mfi.src.js 8.0 KB

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