OHLCSeries.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /* *
  2. *
  3. * (c) 2010-2020 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. import H from '../Core/Globals.js';
  12. import Point from '../Core/Series/Point.js';
  13. import U from '../Core/Utilities.js';
  14. var seriesType = U.seriesType;
  15. var seriesTypes = H.seriesTypes;
  16. /**
  17. * The ohlc series type.
  18. *
  19. * @private
  20. * @class
  21. * @name Highcharts.seriesTypes.ohlc
  22. *
  23. * @augments Highcharts.Series
  24. */
  25. seriesType('ohlc', 'column'
  26. /**
  27. * An OHLC chart is a style of financial chart used to describe price
  28. * movements over time. It displays open, high, low and close values per
  29. * data point.
  30. *
  31. * @sample stock/demo/ohlc/
  32. * OHLC chart
  33. *
  34. * @extends plotOptions.column
  35. * @excluding borderColor, borderRadius, borderWidth, crisp, stacking,
  36. * stack
  37. * @product highstock
  38. * @optionparent plotOptions.ohlc
  39. */
  40. , {
  41. /**
  42. * The approximate pixel width of each group. If for example a series
  43. * with 30 points is displayed over a 600 pixel wide plot area, no
  44. * grouping is performed. If however the series contains so many points
  45. * that the spacing is less than the groupPixelWidth, Highcharts will
  46. * try to group it into appropriate groups so that each is more or less
  47. * two pixels wide. Defaults to `5`.
  48. *
  49. * @type {number}
  50. * @default 5
  51. * @product highstock
  52. * @apioption plotOptions.ohlc.dataGrouping.groupPixelWidth
  53. */
  54. /**
  55. * The pixel width of the line/border. Defaults to `1`.
  56. *
  57. * @sample {highstock} stock/plotoptions/ohlc-linewidth/
  58. * A greater line width
  59. *
  60. * @type {number}
  61. * @default 1
  62. * @product highstock
  63. *
  64. * @private
  65. */
  66. lineWidth: 1,
  67. tooltip: {
  68. pointFormat: '<span style="color:{point.color}">\u25CF</span> ' +
  69. '<b> {series.name}</b><br/>' +
  70. 'Open: {point.open}<br/>' +
  71. 'High: {point.high}<br/>' +
  72. 'Low: {point.low}<br/>' +
  73. 'Close: {point.close}<br/>'
  74. },
  75. threshold: null,
  76. states: {
  77. /**
  78. * @extends plotOptions.column.states.hover
  79. * @product highstock
  80. */
  81. hover: {
  82. /**
  83. * The pixel width of the line representing the OHLC point.
  84. *
  85. * @type {number}
  86. * @default 3
  87. * @product highstock
  88. */
  89. lineWidth: 3
  90. }
  91. },
  92. /**
  93. * Determines which one of `open`, `high`, `low`, `close` values should
  94. * be represented as `point.y`, which is later used to set dataLabel
  95. * position and [compare](#plotOptions.series.compare).
  96. *
  97. * @sample {highstock} stock/plotoptions/ohlc-pointvalkey/
  98. * Possible values
  99. *
  100. * @type {string}
  101. * @default close
  102. * @validvalue ["open", "high", "low", "close"]
  103. * @product highstock
  104. * @apioption plotOptions.ohlc.pointValKey
  105. */
  106. /**
  107. * @default close
  108. * @apioption plotOptions.ohlc.colorKey
  109. */
  110. /**
  111. * Line color for up points.
  112. *
  113. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  114. * @product highstock
  115. * @apioption plotOptions.ohlc.upColor
  116. */
  117. stickyTracking: true
  118. },
  119. /**
  120. * @lends Highcharts.seriesTypes.ohlc
  121. */
  122. {
  123. /* eslint-disable valid-jsdoc */
  124. directTouch: false,
  125. pointArrayMap: ['open', 'high', 'low', 'close'],
  126. toYData: function (point) {
  127. // return a plain array for speedy calculation
  128. return [point.open, point.high, point.low, point.close];
  129. },
  130. pointValKey: 'close',
  131. pointAttrToOptions: {
  132. stroke: 'color',
  133. 'stroke-width': 'lineWidth'
  134. },
  135. /**
  136. * @private
  137. * @function Highcarts.seriesTypes.ohlc#init
  138. * @return {void}
  139. */
  140. init: function () {
  141. seriesTypes.column.prototype.init.apply(this, arguments);
  142. this.options.stacking = void 0; // #8817
  143. },
  144. /**
  145. * Postprocess mapping between options and SVG attributes
  146. *
  147. * @private
  148. * @function Highcharts.seriesTypes.ohlc#pointAttribs
  149. * @param {Highcharts.OHLCPoint} point
  150. * @param {string} state
  151. * @return {Highcharts.SVGAttributes}
  152. */
  153. pointAttribs: function (point, state) {
  154. var attribs = seriesTypes.column.prototype.pointAttribs.call(this, point, state), options = this.options;
  155. delete attribs.fill;
  156. if (!point.options.color &&
  157. options.upColor &&
  158. point.open < point.close) {
  159. attribs.stroke = options.upColor;
  160. }
  161. return attribs;
  162. },
  163. /**
  164. * Translate data points from raw values x and y to plotX and plotY
  165. *
  166. * @private
  167. * @function Highcharts.seriesTypes.ohlc#translate
  168. * @return {void}
  169. */
  170. translate: function () {
  171. var series = this, yAxis = series.yAxis, hasModifyValue = !!series.modifyValue, translated = [
  172. 'plotOpen',
  173. 'plotHigh',
  174. 'plotLow',
  175. 'plotClose',
  176. 'yBottom'
  177. ]; // translate OHLC for
  178. seriesTypes.column.prototype.translate.apply(series);
  179. // Do the translation
  180. series.points.forEach(function (point) {
  181. [point.open, point.high, point.low, point.close, point.low]
  182. .forEach(function (value, i) {
  183. if (value !== null) {
  184. if (hasModifyValue) {
  185. value = series.modifyValue(value);
  186. }
  187. point[translated[i]] =
  188. yAxis.toPixels(value, true);
  189. }
  190. });
  191. // Align the tooltip to the high value to avoid covering the
  192. // point
  193. point.tooltipPos[1] =
  194. point.plotHigh + yAxis.pos - series.chart.plotTop;
  195. });
  196. },
  197. /**
  198. * Draw the data points
  199. *
  200. * @private
  201. * @function Highcharts.seriesTypes.ohlc#drawPoints
  202. * @return {void}
  203. */
  204. drawPoints: function () {
  205. var series = this, points = series.points, chart = series.chart,
  206. /**
  207. * Extend vertical stem to open and close values.
  208. */
  209. extendStem = function (path, halfStrokeWidth, openOrClose) {
  210. var start = path[0];
  211. var end = path[1];
  212. // We don't need to worry about crisp - openOrClose value
  213. // is already crisped and halfStrokeWidth should remove it.
  214. if (typeof start[2] === 'number') {
  215. start[2] = Math.max(openOrClose + halfStrokeWidth, start[2]);
  216. }
  217. if (typeof end[2] === 'number') {
  218. end[2] = Math.min(openOrClose - halfStrokeWidth, end[2]);
  219. }
  220. };
  221. points.forEach(function (point) {
  222. var plotOpen, plotClose, crispCorr, halfWidth, path, graphic = point.graphic, crispX, isNew = !graphic, strokeWidth;
  223. if (typeof point.plotY !== 'undefined') {
  224. // Create and/or update the graphic
  225. if (!graphic) {
  226. point.graphic = graphic = chart.renderer.path()
  227. .add(series.group);
  228. }
  229. if (!chart.styledMode) {
  230. graphic.attr(series.pointAttribs(point, (point.selected && 'select'))); // #3897
  231. }
  232. // crisp vector coordinates
  233. strokeWidth = graphic.strokeWidth();
  234. crispCorr = (strokeWidth % 2) / 2;
  235. // #2596:
  236. crispX = Math.round(point.plotX) - crispCorr;
  237. halfWidth = Math.round(point.shapeArgs.width / 2);
  238. // the vertical stem
  239. path = [
  240. ['M', crispX, Math.round(point.yBottom)],
  241. ['L', crispX, Math.round(point.plotHigh)]
  242. ];
  243. // open
  244. if (point.open !== null) {
  245. plotOpen = Math.round(point.plotOpen) + crispCorr;
  246. path.push(['M', crispX, plotOpen], ['L', crispX - halfWidth, plotOpen]);
  247. extendStem(path, strokeWidth / 2, plotOpen);
  248. }
  249. // close
  250. if (point.close !== null) {
  251. plotClose = Math.round(point.plotClose) + crispCorr;
  252. path.push(['M', crispX, plotClose], ['L', crispX + halfWidth, plotClose]);
  253. extendStem(path, strokeWidth / 2, plotClose);
  254. }
  255. graphic[isNew ? 'attr' : 'animate']({ d: path })
  256. .addClass(point.getClassName(), true);
  257. }
  258. });
  259. },
  260. animate: null // Disable animation
  261. /* eslint-enable valid-jsdoc */
  262. },
  263. /**
  264. * @lends Highcharts.seriesTypes.ohlc.prototype.pointClass.prototype
  265. */
  266. {
  267. /* eslint-disable valid-jsdoc */
  268. /**
  269. * Extend the parent method by adding up or down to the class name.
  270. * @private
  271. * @function Highcharts.seriesTypes.ohlc#getClassName
  272. * @return {string}
  273. */
  274. getClassName: function () {
  275. return Point.prototype.getClassName.call(this) +
  276. (this.open < this.close ?
  277. ' highcharts-point-up' :
  278. ' highcharts-point-down');
  279. }
  280. /* eslint-enable valid-jsdoc */
  281. });
  282. /**
  283. * A `ohlc` series. If the [type](#series.ohlc.type) option is not
  284. * specified, it is inherited from [chart.type](#chart.type).
  285. *
  286. * @extends series,plotOptions.ohlc
  287. * @excluding dataParser, dataURL
  288. * @product highstock
  289. * @apioption series.ohlc
  290. */
  291. /**
  292. * An array of data points for the series. For the `ohlc` series type,
  293. * points can be given in the following ways:
  294. *
  295. * 1. An array of arrays with 5 or 4 values. In this case, the values correspond
  296. * to `x,open,high,low,close`. If the first value is a string, it is applied
  297. * as the name of the point, and the `x` value is inferred. The `x` value can
  298. * also be omitted, in which case the inner arrays should be of length 4\.
  299. * Then the `x` value is automatically calculated, either starting at 0 and
  300. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  301. * series options.
  302. * ```js
  303. * data: [
  304. * [0, 6, 5, 6, 7],
  305. * [1, 9, 4, 8, 2],
  306. * [2, 6, 3, 4, 10]
  307. * ]
  308. * ```
  309. *
  310. * 2. An array of objects with named values. The following snippet shows only a
  311. * few settings, see the complete options set below. If the total number of
  312. * data points exceeds the series'
  313. * [turboThreshold](#series.ohlc.turboThreshold), this option is not
  314. * available.
  315. * ```js
  316. * data: [{
  317. * x: 1,
  318. * open: 3,
  319. * high: 4,
  320. * low: 5,
  321. * close: 2,
  322. * name: "Point2",
  323. * color: "#00FF00"
  324. * }, {
  325. * x: 1,
  326. * open: 4,
  327. * high: 3,
  328. * low: 6,
  329. * close: 7,
  330. * name: "Point1",
  331. * color: "#FF00FF"
  332. * }]
  333. * ```
  334. *
  335. * @type {Array<Array<(number|string),number,number,number>|Array<(number|string),number,number,number,number>|*>}
  336. * @extends series.arearange.data
  337. * @excluding y, marker
  338. * @product highstock
  339. * @apioption series.ohlc.data
  340. */
  341. /**
  342. * The closing value of each data point.
  343. *
  344. * @type {number}
  345. * @product highstock
  346. * @apioption series.ohlc.data.close
  347. */
  348. /**
  349. * The opening value of each data point.
  350. *
  351. * @type {number}
  352. * @product highstock
  353. * @apioption series.ohlc.data.open
  354. */
  355. ''; // adds doclets above to transpilat