UNPKG

highcharts-indicators

Version:

Highstock plugin to add technical indicators to charts.

151 lines (128 loc) 3.91 kB
/* global Highcharts module:true */ (function (factory) { if (typeof module === 'object' && module.exports) { module.exports = factory; } else { factory(Highcharts); } }(function (HC) { 'use strict'; /** Each indicator requires mothods: - getDefaultOptions() - returns object with default parameters, like period etc. - getValues(chart, series, options, points) - returns array of calculated values for indicator - getGraph(chart, series, options, values) - returns path, or columns as SVG elements to add. Doesn't add to the chart via renderer! **/ var merge = HC.merge, isArray = HC.isArray, minInArray = HC.Axis.prototype.minInArray, maxInArray = HC.Axis.prototype.maxInArray; HC.Indicator.prototype.ema = { getDefaultOptions: function () { return { period: 14, index: 0, approximation: 'average' }; }, getValues: function (chart, series, options, extraPoints) { var utils = this.utils, params = options.params, period = params.period, xVal = extraPoints[0].concat(series.processedXData || []), // #22 yVal = extraPoints[1].concat(series.processedYData || []), // #22 yValLen = yVal ? yVal.length : 0, EMApercent = (2 / (period + 1)), calEMA = 0, range = 1, xValue = xVal[0], yValue = yVal[0], EMA = [], xData = [], yData = [], index = -1, i, points, EMAPoint; // check period, if bigger than points length, skip if (xVal.length <= period) { return false; } // switch index for OHLC / Candlestick / Arearange if (isArray(yVal[0])) { index = params.index ? params.index : 0; yValue = yVal[0][index]; } // starting point points = [[xValue, yValue]]; // accumulate first N-points while (range !== period) { utils.accumulateAverage(points, xVal, yVal, range, index); range++; } // calculate value one-by-one for each perdio in visible data for (i = range; i < yValLen; i++) { EMAPoint = utils.populateAverage(points, xVal, yVal, i, EMApercent, calEMA, index); EMA.push(EMAPoint); xData.push(EMAPoint[0]); yData.push(EMAPoint[1]); calEMA = EMAPoint[1]; utils.accumulateAverage(points, xVal, yVal, i, index); } EMAPoint = utils.populateAverage(points, xVal, yVal, i, EMApercent, calEMA, index); EMA.push(EMAPoint); xData.push(EMAPoint[0]); yData.push(EMAPoint[1]); // registger extremes for axis; options.yAxisMax = maxInArray(EMA); options.yAxisMin = minInArray(EMA); return { values: EMA, xData: xData, yData: yData }; }, getGraph: function (chart, series, options, values) { var path = [], attrs = {}, xAxis = series.xAxis, yAxis = options.Axis = series.yAxis, ema = values, emaLen = ema.length, emaX, emaY, i; if (options.visible === false) { return false; } options.styles = attrs = merge({ 'stroke-width': 2, stroke: 'red', dashstyle: 'Dash' }, options.styles); path.push('M', xAxis.toPixels(ema[0][0]), yAxis.toPixels(ema[0][1])); for (i = 0; i < emaLen; i++) { emaX = ema[i][0]; emaY = ema[i][1]; path.push('L', xAxis.toPixels(emaX), yAxis.toPixels(emaY)); } return [chart.renderer.path(path).attr(attrs)]; }, utils: { accumulateAverage: function (points, xVal, yVal, i, index) { var xValue = xVal[i], yValue = index < 0 ? yVal[i] : yVal[i][index]; points.push([xValue, yValue]); }, populateAverage: function (points, xVal, yVal, i, EMApercent, calEMA, index) { var x = xVal[i - 1], yValuePrev = index < 0 ? yVal[i - 2] : yVal[i - 2][index], yValue = index < 0 ? yVal[i - 1] : yVal[i - 1][index], prevPoint, y; prevPoint = calEMA === 0 ? yValuePrev : calEMA; y = ((yValue * EMApercent) + (prevPoint * (1 - EMApercent))); return [x, y]; } } }; }));