psar.src.js 11 KB

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