psar.src.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /**
  2. * @license Highstock JS v8.0.0 (2019-12-10)
  3. *
  4. * Parabolic SAR 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/psar', ['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/psar.src.js', [_modules['parts/Globals.js']], function (H) {
  32. /* *
  33. *
  34. * Parabolic SAR indicator for Highstock
  35. *
  36. * (c) 2010-2019 Grzegorz Blachliński
  37. *
  38. * License: www.highcharts.com/license
  39. *
  40. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  41. *
  42. * */
  43. /* eslint-disable require-jsdoc */
  44. // Utils:
  45. function toFixed(a, n) {
  46. return parseFloat(a.toFixed(n));
  47. }
  48. function calculateDirection(previousDirection, low, high, PSAR) {
  49. if ((previousDirection === 1 && low > PSAR) ||
  50. (previousDirection === -1 && high > PSAR)) {
  51. return 1;
  52. }
  53. return -1;
  54. }
  55. /* *
  56. * Method for calculating acceleration factor
  57. * dir - direction
  58. * pDir - previous Direction
  59. * eP - extreme point
  60. * pEP - previous extreme point
  61. * inc - increment for acceleration factor
  62. * maxAcc - maximum acceleration factor
  63. * initAcc - initial acceleration factor
  64. */
  65. function getAccelerationFactor(dir, pDir, eP, pEP, pAcc, inc, maxAcc, initAcc) {
  66. if (dir === pDir) {
  67. if (dir === 1 && (eP > pEP)) {
  68. return (pAcc === maxAcc) ? maxAcc : toFixed(pAcc + inc, 2);
  69. }
  70. if (dir === -1 && (eP < pEP)) {
  71. return (pAcc === maxAcc) ? maxAcc : toFixed(pAcc + inc, 2);
  72. }
  73. return pAcc;
  74. }
  75. return initAcc;
  76. }
  77. function getExtremePoint(high, low, previousDirection, previousExtremePoint) {
  78. if (previousDirection === 1) {
  79. return (high > previousExtremePoint) ? high : previousExtremePoint;
  80. }
  81. return (low < previousExtremePoint) ? low : previousExtremePoint;
  82. }
  83. function getEPMinusPSAR(EP, PSAR) {
  84. return EP - PSAR;
  85. }
  86. function getAccelerationFactorMultiply(accelerationFactor, EPMinusSAR) {
  87. return accelerationFactor * EPMinusSAR;
  88. }
  89. /* *
  90. * Method for calculating PSAR
  91. * pdir - previous direction
  92. * sDir - second previous Direction
  93. * PSAR - previous PSAR
  94. * pACCMultiply - previous acceleration factor multiply
  95. * sLow - second previous low
  96. * pLow - previous low
  97. * sHigh - second previous high
  98. * pHigh - previous high
  99. * pEP - previous extreme point
  100. */
  101. function getPSAR(pdir, sDir, PSAR, pACCMulti, sLow, pLow, pHigh, sHigh, pEP) {
  102. if (pdir === sDir) {
  103. if (pdir === 1) {
  104. return (PSAR + pACCMulti < Math.min(sLow, pLow)) ?
  105. PSAR + pACCMulti :
  106. Math.min(sLow, pLow);
  107. }
  108. return (PSAR + pACCMulti > Math.max(sHigh, pHigh)) ?
  109. PSAR + pACCMulti :
  110. Math.max(sHigh, pHigh);
  111. }
  112. return pEP;
  113. }
  114. /* eslint-enable require-jsdoc */
  115. /**
  116. * The Parabolic SAR series type.
  117. *
  118. * @private
  119. * @class
  120. * @name Highcharts.seriesTypes.psar
  121. *
  122. * @augments Highcharts.Series
  123. */
  124. H.seriesType('psar', 'sma',
  125. /**
  126. * Parabolic SAR. This series requires `linkedTo`
  127. * option to be set and should be loaded
  128. * after `stock/indicators/indicators.js` file.
  129. *
  130. * @sample stock/indicators/psar
  131. * Parabolic SAR Indicator
  132. *
  133. * @extends plotOptions.sma
  134. * @since 6.0.0
  135. * @product highstock
  136. * @requires stock/indicators/indicators
  137. * @requires stock/indicators/psar
  138. * @optionparent plotOptions.psar
  139. */
  140. {
  141. lineWidth: 0,
  142. marker: {
  143. enabled: true
  144. },
  145. states: {
  146. hover: {
  147. lineWidthPlus: 0
  148. }
  149. },
  150. /**
  151. * @excluding period
  152. */
  153. params: {
  154. /**
  155. * The initial value for acceleration factor.
  156. * Acceleration factor is starting with this value
  157. * and increases by specified increment each time
  158. * the extreme point makes a new high.
  159. * AF can reach a maximum of maxAccelerationFactor,
  160. * no matter how long the uptrend extends.
  161. */
  162. initialAccelerationFactor: 0.02,
  163. /**
  164. * The Maximum value for acceleration factor.
  165. * AF can reach a maximum of maxAccelerationFactor,
  166. * no matter how long the uptrend extends.
  167. */
  168. maxAccelerationFactor: 0.2,
  169. /**
  170. * Acceleration factor increases by increment each time
  171. * the extreme point makes a new high.
  172. *
  173. * @since 6.0.0
  174. */
  175. increment: 0.02,
  176. /**
  177. * Index from which PSAR is starting calculation
  178. *
  179. * @since 6.0.0
  180. */
  181. index: 2,
  182. /**
  183. * Number of maximum decimals that are used in PSAR calculations.
  184. *
  185. * @since 6.0.0
  186. */
  187. decimals: 4
  188. }
  189. }, {
  190. nameComponents: false,
  191. getValues: function (series, params) {
  192. var xVal = series.xData, yVal = series.yData,
  193. // Extreme point is the lowest low for falling and highest high
  194. // for rising psar - and we are starting with falling
  195. extremePoint = yVal[0][1], accelerationFactor = params.initialAccelerationFactor, maxAccelerationFactor = params.maxAccelerationFactor, increment = params.increment,
  196. // Set initial acc factor (for every new trend!)
  197. initialAccelerationFactor = params.initialAccelerationFactor, PSAR = yVal[0][2], decimals = params.decimals, index = params.index, PSARArr = [], xData = [], yData = [], previousDirection = 1, direction, EPMinusPSAR, accelerationFactorMultiply, newDirection, prevLow, prevPrevLow, prevHigh, prevPrevHigh, newExtremePoint, high, low, ind;
  198. if (index >= yVal.length) {
  199. return;
  200. }
  201. for (ind = 0; ind < index; ind++) {
  202. extremePoint = Math.max(yVal[ind][1], extremePoint);
  203. PSAR = Math.min(yVal[ind][2], toFixed(PSAR, decimals));
  204. }
  205. direction = (yVal[ind][1] > PSAR) ? 1 : -1;
  206. EPMinusPSAR = getEPMinusPSAR(extremePoint, PSAR);
  207. accelerationFactor = params.initialAccelerationFactor;
  208. accelerationFactorMultiply = getAccelerationFactorMultiply(accelerationFactor, EPMinusPSAR);
  209. PSARArr.push([xVal[index], PSAR]);
  210. xData.push(xVal[index]);
  211. yData.push(toFixed(PSAR, decimals));
  212. for (ind = index + 1; ind < yVal.length; ind++) {
  213. prevLow = yVal[ind - 1][2];
  214. prevPrevLow = yVal[ind - 2][2];
  215. prevHigh = yVal[ind - 1][1];
  216. prevPrevHigh = yVal[ind - 2][1];
  217. high = yVal[ind][1];
  218. low = yVal[ind][2];
  219. // Null points break PSAR
  220. if (prevPrevLow !== null &&
  221. prevPrevHigh !== null &&
  222. prevLow !== null &&
  223. prevHigh !== null &&
  224. high !== null &&
  225. low !== null) {
  226. PSAR = getPSAR(direction, previousDirection, PSAR, accelerationFactorMultiply, prevPrevLow, prevLow, prevHigh, prevPrevHigh, extremePoint);
  227. newExtremePoint = getExtremePoint(high, low, direction, extremePoint);
  228. newDirection = calculateDirection(previousDirection, low, high, PSAR);
  229. accelerationFactor = getAccelerationFactor(newDirection, direction, newExtremePoint, extremePoint, accelerationFactor, increment, maxAccelerationFactor, initialAccelerationFactor);
  230. EPMinusPSAR = getEPMinusPSAR(newExtremePoint, PSAR);
  231. accelerationFactorMultiply = getAccelerationFactorMultiply(accelerationFactor, EPMinusPSAR);
  232. PSARArr.push([xVal[ind], toFixed(PSAR, decimals)]);
  233. xData.push(xVal[ind]);
  234. yData.push(toFixed(PSAR, decimals));
  235. previousDirection = direction;
  236. direction = newDirection;
  237. extremePoint = newExtremePoint;
  238. }
  239. }
  240. return {
  241. values: PSARArr,
  242. xData: xData,
  243. yData: yData
  244. };
  245. }
  246. });
  247. /**
  248. * A `PSAR` series. If the [type](#series.psar.type) option is not specified, it
  249. * is inherited from [chart.type](#chart.type).
  250. *
  251. * @extends series,plotOptions.psar
  252. * @since 6.0.0
  253. * @product highstock
  254. * @excluding dataParser, dataURL
  255. * @requires stock/indicators/indicators
  256. * @requires stock/indicators/psar
  257. * @apioption series.psar
  258. */
  259. ''; // to include the above in the js output
  260. });
  261. _registerModule(_modules, 'masters/indicators/psar.src.js', [], function () {
  262. });
  263. }));