OHLCSeries.js 12 KB

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