| @@ -0,0 +1,11 @@ | ||
| /* | ||
| Highcharts JS v6.0.4 (2017-12-15) | ||
| Indicator series type for Highstock | ||
| (c) 2010-2017 Sebastian Bochan | ||
| License: www.highcharts.com/license | ||
| */ | ||
| (function(c){"object"===typeof module&&module.exports?module.exports=c:c(Highcharts)})(function(c){(function(c){var l=c.seriesType;l("ad","sma",{name:"Accumulation/Distribution",params:{volumeSeriesID:"volume"}},{getValues:function(e,f){var g=f.period,n=e.xData,d=e.yData,b=f.volumeSeriesID,a=e.chart.get(b);e=a&&a.yData;f=d?d.length:0;var h=[],p=[],q=[];if(n.length<=g&&f&&4!==d[0].length)return!1;if(!a)return c.error("Series "+b+" not found! Check `volumeSeriesID`.",!0);for(b=g;b<f;b++){var g=h.length, | ||
| a=d[b][1],k=d[b][2],m=d[b][3],l=e[b],a=[n[b],m===a&&m===k||a===k?0:(2*m-k-a)/(a-k)*l];0<g&&(a[1]+=h[g-1][1],a[1]=a[1]);h.push(a);p.push(a[0]);q.push(a[1])}return{values:h,xData:p,yData:q}}})})(c)}); |
| @@ -0,0 +1,144 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * Indicator series type for Highstock | ||
| * | ||
| * (c) 2010-2017 Sebastian Bochan | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
|
|
||
| var seriesType = H.seriesType; | ||
|
|
||
| // Utils: | ||
| function populateAverage(xVal, yVal, yValVolume, i) { | ||
| var high = yVal[i][1], | ||
| low = yVal[i][2], | ||
| close = yVal[i][3], | ||
| volume = yValVolume[i], | ||
| adY = close === high && close === low || high === low ? 0 : ((2 * close - low - high) / (high - low)) * volume, | ||
| adX = xVal[i]; | ||
|
|
||
| return [adX, adY]; | ||
| } | ||
|
|
||
| /** | ||
| * The AD series type. | ||
| * | ||
| * @constructor seriesTypes.ad | ||
| * @augments seriesTypes.sma | ||
| */ | ||
| seriesType('ad', 'sma', | ||
| /** | ||
| * Accumulation Distribution (AD). This series requires `linkedTo` option to be set. | ||
| * | ||
| * @extends {plotOptions.sma} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/accumulation-distribution | ||
| * Accumulation/Distribution indicator | ||
| * @since 6.0.0 | ||
| * @optionparent plotOptions.ad | ||
| */ | ||
| { | ||
| name: 'Accumulation/Distribution', | ||
| params: { | ||
| /** | ||
| * The id of volume series which is mandatory. | ||
| * For example using OHLC data, volumeSeriesID='volume' means | ||
| * the indicator will be calculated using OHLC and volume values. | ||
| * | ||
| * @type {String} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| volumeSeriesID: 'volume' | ||
| } | ||
| }, { | ||
| getValues: function(series, params) { | ||
| var period = params.period, | ||
| xVal = series.xData, | ||
| yVal = series.yData, | ||
| volumeSeriesID = params.volumeSeriesID, | ||
| volumeSeries = series.chart.get(volumeSeriesID), | ||
| yValVolume = volumeSeries && volumeSeries.yData, | ||
| yValLen = yVal ? yVal.length : 0, | ||
| AD = [], | ||
| xData = [], | ||
| yData = [], | ||
| len, i, ADPoint; | ||
|
|
||
| if (xVal.length <= period && yValLen && yVal[0].length !== 4) { | ||
| return false; | ||
| } | ||
|
|
||
| if (!volumeSeries) { | ||
| return H.error( | ||
| 'Series ' + | ||
| volumeSeriesID + | ||
| ' not found! Check `volumeSeriesID`.', | ||
| true | ||
| ); | ||
| } | ||
|
|
||
| // i = period <-- skip first N-points | ||
| // Calculate value one-by-one for each period in visible data | ||
| for (i = period; i < yValLen; i++) { | ||
|
|
||
| len = AD.length; | ||
| ADPoint = populateAverage(xVal, yVal, yValVolume, i, period); | ||
|
|
||
| if (len > 0) { | ||
| ADPoint[1] += AD[len - 1][1]; | ||
| ADPoint[1] = ADPoint[1]; | ||
| } | ||
|
|
||
| AD.push(ADPoint); | ||
|
|
||
| xData.push(ADPoint[0]); | ||
| yData.push(ADPoint[1]); | ||
| } | ||
|
|
||
| return { | ||
| values: AD, | ||
| xData: xData, | ||
| yData: yData | ||
| }; | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * A `AD` series. If the [type](#series.ad.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to | ||
| * [plotOptions.ad](#plotOptions.ad). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.ad | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.ad | ||
| */ | ||
|
|
||
| /** | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.sma.data | ||
| * @product highstock | ||
| * @apioption series.ad.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |
| @@ -0,0 +1,11 @@ | ||
| /* | ||
| Highcharts JS v6.0.4 (2017-12-15) | ||
| Indicator series type for Highstock | ||
| (c) 2010-2017 Sebastian Bochan | ||
| License: www.highcharts.com/license | ||
| */ | ||
| (function(b){"object"===typeof module&&module.exports?module.exports=b:b(Highcharts)})(function(b){(function(b){function n(a,d){return Math.max(a[1]-a[2],d===g?0:Math.abs(a[1]-d[3]),d===g?0:Math.abs(a[2]-d[3]))}var r=b.isArray;b=b.seriesType;var g;b("atr","sma",{name:"ATR (14)",params:{period:14}},{getValues:function(a,d){d=d.period;var b=a.xData,g=(a=a.yData)?a.length:0,h=1,f=0,p=0,k=[],l=[],m=[],e,c,q;q=[[b[0],a[0]]];if(b.length<=d||!r(a[0])||4!==a[0].length)return!1;for(c=1;c<=g;c++)if(q.push([b[c], | ||
| a[c]]),d<h){e=d;var t=b[c-1],u=n(a[c-1],a[c-2]);e=[t,(f*(e-1)+u)/e];f=e[1];k.push(e);l.push(e[0]);m.push(e[1])}else d===h?(f=p/(c-1),k.push([b[c-1],f]),l.push(b[c-1]),m.push(f)):p+=n(a[c-1],a[c-2]),h++;return{values:k,xData:l,yData:m}}})})(b)}); |
| @@ -0,0 +1,155 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * Indicator series type for Highstock | ||
| * | ||
| * (c) 2010-2017 Sebastian Bochan | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
|
|
||
| var isArray = H.isArray, | ||
| seriesType = H.seriesType, | ||
| UNDEFINED; | ||
|
|
||
| // Utils: | ||
| function accumulateAverage(points, xVal, yVal, i) { | ||
| var xValue = xVal[i], | ||
| yValue = yVal[i]; | ||
|
|
||
| points.push([xValue, yValue]); | ||
| } | ||
|
|
||
| function getTR(currentPoint, prevPoint) { | ||
| var pointY = currentPoint, | ||
| prevY = prevPoint, | ||
| HL = pointY[1] - pointY[2], | ||
| HCp = prevY === UNDEFINED ? 0 : Math.abs(pointY[1] - prevY[3]), | ||
| LCp = prevY === UNDEFINED ? 0 : Math.abs(pointY[2] - prevY[3]), | ||
| TR = Math.max(HL, HCp, LCp); | ||
|
|
||
| return TR; | ||
| } | ||
|
|
||
| function populateAverage(points, xVal, yVal, i, period, prevATR) { | ||
| var x = xVal[i - 1], | ||
| TR = getTR(yVal[i - 1], yVal[i - 2]), | ||
| y; | ||
|
|
||
| y = (((prevATR * (period - 1)) + TR) / period); | ||
|
|
||
| return [x, y]; | ||
| } | ||
| /** | ||
| * The ATR series type. | ||
| * | ||
| * @constructor seriesTypes.atr | ||
| * @augments seriesTypes.sma | ||
| */ | ||
| seriesType('atr', 'sma', | ||
| /** | ||
| * Average true range indicator (ATR). This series requires `linkedTo` option to be set. | ||
| * | ||
| * @extends {plotOptions.sma} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/atr ATR indicator | ||
| * @since 6.0.0 | ||
| * @optionparent plotOptions.atr | ||
| */ | ||
| { | ||
| name: 'ATR (14)', | ||
| params: { | ||
| period: 14 | ||
| } | ||
| }, { | ||
| getValues: function(series, params) { | ||
| var period = params.period, | ||
| xVal = series.xData, | ||
| yVal = series.yData, | ||
| yValLen = yVal ? yVal.length : 0, | ||
| xValue = xVal[0], | ||
| yValue = yVal[0], | ||
| range = 1, | ||
| prevATR = 0, | ||
| TR = 0, | ||
| ATR = [], | ||
| xData = [], | ||
| yData = [], | ||
| point, i, points; | ||
|
|
||
| points = [ | ||
| [xValue, yValue] | ||
| ]; | ||
|
|
||
| if ((xVal.length <= period) || !isArray(yVal[0]) || yVal[0].length !== 4) { | ||
| return false; | ||
| } | ||
|
|
||
| for (i = 1; i <= yValLen; i++) { | ||
|
|
||
| accumulateAverage(points, xVal, yVal, i); | ||
|
|
||
| if (period < range) { | ||
| point = populateAverage(points, xVal, yVal, i, period, prevATR); | ||
| prevATR = point[1]; | ||
| ATR.push(point); | ||
| xData.push(point[0]); | ||
| yData.push(point[1]); | ||
|
|
||
| } else if (period === range) { | ||
| prevATR = TR / (i - 1); | ||
| ATR.push([xVal[i - 1], prevATR]); | ||
| xData.push(xVal[i - 1]); | ||
| yData.push(prevATR); | ||
| range++; | ||
| } else { | ||
| TR += getTR(yVal[i - 1], yVal[i - 2]); | ||
| range++; | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| values: ATR, | ||
| xData: xData, | ||
| yData: yData | ||
| }; | ||
| } | ||
|
|
||
| }); | ||
|
|
||
| /** | ||
| * A `ATR` series. If the [type](#series.atr.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to | ||
| * [plotOptions.atr](#plotOptions.atr). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.atr | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.atr | ||
| */ | ||
|
|
||
| /** | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.sma.data | ||
| * @product highstock | ||
| * @apioption series.atr.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |
| @@ -0,0 +1,313 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * Indicator series type for Highstock | ||
| * | ||
| * (c) 2010-2017 Paweł Fus | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
|
|
||
|
|
||
| var each = H.each, | ||
| merge = H.merge, | ||
| isArray = H.isArray, | ||
| SMA = H.seriesTypes.sma; | ||
|
|
||
| // Utils: | ||
| function getStandardDeviation(arr, mean) { | ||
| var variance = 0, | ||
| arrLen = arr.length, | ||
| std = 0, | ||
| i = 0; | ||
|
|
||
| for (; i < arrLen; i++) { | ||
| variance += (arr[i][3] - mean) * (arr[i][3] - mean); | ||
| } | ||
| variance = variance / (arrLen - 1); | ||
|
|
||
| std = Math.sqrt(variance); | ||
| return std; | ||
| } | ||
|
|
||
| H.seriesType('bb', 'sma', | ||
| /** | ||
| * Bollinger bands (BB). This series requires `linkedTo` | ||
| * option to be set and should be loaded after `stock/indicators/indicators.js` file. | ||
| * | ||
| * @extends {plotOptions.sma} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/bollinger-bands | ||
| * Bollinger bands | ||
| * @since 6.0.0 | ||
| * @optionparent plotOptions.bb | ||
| */ | ||
| { | ||
| name: 'BB (20, 2)', | ||
| params: { | ||
| period: 20, | ||
| /** | ||
| * Standard deviation for top and bottom bands. | ||
| * | ||
| * @type {Number} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| standardDeviation: 2, | ||
| index: 3 | ||
| }, | ||
| /** | ||
| * Bottom line options. | ||
| * | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| bottomLine: { | ||
| /** | ||
| * Styles for a bottom line. | ||
| * | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| styles: { | ||
| /** | ||
| * Pixel width of the line. | ||
| * | ||
| * @type {Number} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| lineWidth: 1, | ||
| /** | ||
| * Color of the line. | ||
| * If not set, it's inherited from [plotOptions.bb.color](#plotOptions.bb.color). | ||
| * | ||
| * @type {String} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| lineColor: undefined | ||
| } | ||
| }, | ||
| /** | ||
| * Top line options. | ||
| * | ||
| * @extends {plotOptions.bb.bottomLine} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| topLine: { | ||
| styles: { | ||
| lineWidth: 1, | ||
| lineColor: undefined | ||
| } | ||
| }, | ||
| tooltip: { | ||
| /** | ||
| * The HTML of the point's line in the tooltip. Variables are enclosed | ||
| * by curly brackets. Available variables are point.x, point.y, series. | ||
| * name and series.color and other properties on the same form. Furthermore, | ||
| * point.y can be extended by the `tooltip.valuePrefix` and `tooltip. | ||
| * valueSuffix` variables. This can also be overridden for each series, | ||
| * which makes it a good hook for displaying units. | ||
| * | ||
| * In styled mode, the dot is colored by a class name rather | ||
| * than the point color. | ||
| * | ||
| * @type {String} | ||
| * @sample {highcharts} highcharts/tooltip/pointformat/ A different point format with value suffix | ||
| * @sample {highmaps} maps/tooltip/format/ Format demo | ||
| * @default | ||
| * <span style="color:{point.color}">\u25CF</span> <b> {series.name}</b><br/> | ||
| * Top: {point.top}<br/> | ||
| * Middle: {point.middle}<br/> | ||
| * Bottom: {point.bottom}<br/> | ||
| */ | ||
| pointFormat: '<span style="color:{point.color}">\u25CF</span>' + | ||
| '<b> {series.name}</b><br/>' + | ||
| 'Top: {point.top}<br/>' + | ||
| 'Middle: {point.middle}<br/>' + | ||
| 'Bottom: {point.bottom}<br/>' | ||
| }, | ||
| marker: { | ||
| enabled: false | ||
| }, | ||
| dataGrouping: { | ||
| approximation: 'averages' | ||
| } | ||
| }, /** @lends Highcharts.Series.prototype */ { | ||
| pointArrayMap: ['top', 'middle', 'bottom'], | ||
| pointValKey: 'middle', | ||
| init: function() { | ||
| SMA.prototype.init.apply(this, arguments); | ||
|
|
||
| // Set default color for lines: | ||
| this.options = merge({ | ||
| topLine: { | ||
| styles: { | ||
| lineColor: this.color | ||
| } | ||
| }, | ||
| bottomLine: { | ||
| styles: { | ||
| lineColor: this.color | ||
| } | ||
| } | ||
| }, this.options); | ||
| }, | ||
| toYData: function(point) { | ||
| return [point.top, point.middle, point.bottom]; | ||
| }, | ||
| translate: function() { | ||
| var indicator = this, | ||
| translatedBB = ['plotTop', 'plotMiddle', 'plotBottom']; | ||
|
|
||
| SMA.prototype.translate.apply(indicator, arguments); | ||
|
|
||
| each(indicator.points, function(point) { | ||
| each([point.top, point.middle, point.bottom], function(value, i) { | ||
| if (value !== null) { | ||
| point[translatedBB[i]] = indicator.yAxis.toPixels(value, true); | ||
| } | ||
| }); | ||
| }); | ||
| }, | ||
| drawGraph: function() { | ||
| var indicator = this, | ||
| middleLinePoints = indicator.points, | ||
| pointsLength = middleLinePoints.length, | ||
| middleLineOptions = indicator.options, | ||
| middleLinePath = indicator.graph, | ||
| gappedExtend = { | ||
| options: { | ||
| gapSize: middleLineOptions.gapSize | ||
| } | ||
| }, | ||
| deviations = [ | ||
| [], | ||
| [] | ||
| ], // top and bottom point place holders | ||
| point; | ||
|
|
||
| // Generate points for top and bottom lines: | ||
| while (pointsLength--) { | ||
| point = middleLinePoints[pointsLength]; | ||
| deviations[0].push({ | ||
| plotX: point.plotX, | ||
| plotY: point.plotTop, | ||
| isNull: point.isNull | ||
| }); | ||
| deviations[1].push({ | ||
| plotX: point.plotX, | ||
| plotY: point.plotBottom, | ||
| isNull: point.isNull | ||
| }); | ||
| } | ||
|
|
||
| // Modify options and generate lines: | ||
| each(['topLine', 'bottomLine'], function(lineName, i) { | ||
| indicator.points = deviations[i]; | ||
| indicator.options = merge(middleLineOptions[lineName].styles, gappedExtend); | ||
| indicator.graph = indicator['graph' + lineName]; | ||
| SMA.prototype.drawGraph.call(indicator); | ||
|
|
||
| // Now save lines: | ||
| indicator['graph' + lineName] = indicator.graph; | ||
| }); | ||
|
|
||
| // Restore options and draw a middle line: | ||
| indicator.points = middleLinePoints; | ||
| indicator.options = middleLineOptions; | ||
| indicator.graph = middleLinePath; | ||
| SMA.prototype.drawGraph.call(indicator); | ||
| }, | ||
| getValues: function(series, params) { | ||
| var period = params.period, | ||
| standardDeviation = params.standardDeviation, | ||
| xVal = series.xData, | ||
| yVal = series.yData, | ||
| yValLen = yVal ? yVal.length : 0, | ||
| BB = [], // 0- date, 1-middle line, 2-top line, 3-bottom line | ||
| ML, TL, BL, // middle line, top line and bottom line | ||
| date, | ||
| xData = [], | ||
| yData = [], | ||
| slicedX, | ||
| slicedY, | ||
| stdDev, | ||
| point, | ||
| i; | ||
|
|
||
| // BB requires close value | ||
| if (xVal.length < period || !isArray(yVal[0]) || yVal[0].length !== 4) { | ||
| return false; | ||
| } | ||
|
|
||
| for (i = period; i <= yValLen; i++) { | ||
| slicedX = xVal.slice(i - period, i); | ||
| slicedY = yVal.slice(i - period, i); | ||
|
|
||
| point = SMA.prototype.getValues.call(this, { | ||
| xData: slicedX, | ||
| yData: slicedY | ||
| }, params); | ||
|
|
||
| date = point.xData[0]; | ||
| ML = point.yData[0]; | ||
| stdDev = getStandardDeviation(slicedY, ML); | ||
| TL = ML + standardDeviation * stdDev; | ||
| BL = ML - standardDeviation * stdDev; | ||
|
|
||
| BB.push([date, TL, ML, BL]); | ||
| xData.push(date); | ||
| yData.push([TL, ML, BL]); | ||
| } | ||
|
|
||
| return { | ||
| values: BB, | ||
| xData: xData, | ||
| yData: yData | ||
| }; | ||
| } | ||
| } | ||
| ); | ||
|
|
||
| /** | ||
| * A bollinger bands indicator. If the [type](#series.bb.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to [plotOptions. | ||
| * bb](#plotOptions.bb). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.bb | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.bb | ||
| */ | ||
|
|
||
| /** | ||
| * An array of data points for the series. For the `bb` series type, | ||
| * points are calculated dynamically. | ||
| * | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.line.data | ||
| * @product highstock | ||
| * @apioption series.bb.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |
| @@ -0,0 +1,11 @@ | ||
| /* | ||
| Highcharts JS v6.0.4 (2017-12-15) | ||
| Indicator series type for Highstock | ||
| (c) 2010-2017 Sebastian Bochan | ||
| License: www.highcharts.com/license | ||
| */ | ||
| (function(a){"object"===typeof module&&module.exports?module.exports=a:a(Highcharts)})(function(a){(function(a){function r(c){return a.reduce(c,function(c,a){return c+a},0)}var t=a.isArray,k=a.seriesType;k("cci","sma",{name:"CCI (14)",params:{period:14}},{getValues:function(c,a){a=a.period;var h=c.xData,k=(c=c.yData)?c.length:0,l=[],e,d=1,m=[],n=[],p=[],b,f;if(h.length<=a||!t(c[0])||4!==c[0].length)return!1;for(;d<a;)b=c[d-1],l.push((b[1]+b[2]+b[3])/3),d++;for(d=a;d<=k;d++){b=c[d-1];b=(b[1]+b[2]+ | ||
| b[3])/3;f=l.push(b);e=l.slice(f-a);f=r(e)/a;var u=e.length,q=0,g;for(g=0;g<u;g++)q+=Math.abs(f-e[g]);e=q/a;b=(b-f)/(.015*e);m.push([h[d-1],b]);n.push(h[d-1]);p.push(b)}return{values:m,xData:n,yData:p}}})})(a)}); |
| @@ -0,0 +1,140 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * Indicator series type for Highstock | ||
| * | ||
| * (c) 2010-2017 Sebastian Bochan | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
|
|
||
| var isArray = H.isArray, | ||
| seriesType = H.seriesType; | ||
|
|
||
| // Utils: | ||
| function sumArray(array) { | ||
| return H.reduce(array, function(prev, cur) { | ||
| return prev + cur; | ||
| }, 0); | ||
| } | ||
|
|
||
| function meanDeviation(arr, sma) { | ||
| var len = arr.length, | ||
| sum = 0, | ||
| i; | ||
|
|
||
| for (i = 0; i < len; i++) { | ||
| sum += Math.abs(sma - (arr[i])); | ||
| } | ||
|
|
||
| return sum; | ||
| } | ||
|
|
||
| /** | ||
| * The CCI series type. | ||
| * | ||
| * @constructor seriesTypes.cci | ||
| * @augments seriesTypes.sma | ||
| */ | ||
| seriesType('cci', 'sma', | ||
| /** | ||
| * Commodity Channel Index (CCI). This series requires `linkedTo` option to be set. | ||
| * | ||
| * @extends {plotOptions.sma} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/cci CCI indicator | ||
| * @since 6.0.0 | ||
| * @optionparent plotOptions.cci | ||
| */ | ||
| { | ||
| name: 'CCI (14)', | ||
| params: { | ||
| period: 14 | ||
| } | ||
| }, { | ||
| getValues: function(series, params) { | ||
| var period = params.period, | ||
| xVal = series.xData, | ||
| yVal = series.yData, | ||
| yValLen = yVal ? yVal.length : 0, | ||
| TP = [], | ||
| periodTP = [], | ||
| range = 1, | ||
| CCI = [], | ||
| xData = [], | ||
| yData = [], | ||
| CCIPoint, p, len, smaTP, TPtemp, meanDev, i; | ||
|
|
||
| // CCI requires close value | ||
| if (xVal.length <= period || !isArray(yVal[0]) || yVal[0].length !== 4) { | ||
| return false; | ||
| } | ||
|
|
||
| // accumulate first N-points | ||
| while (range < period) { | ||
| p = yVal[range - 1]; | ||
| TP.push((p[1] + p[2] + p[3]) / 3); | ||
| range++; | ||
| } | ||
|
|
||
| for (i = period; i <= yValLen; i++) { | ||
|
|
||
| p = yVal[i - 1]; | ||
| TPtemp = (p[1] + p[2] + p[3]) / 3; | ||
| len = TP.push(TPtemp); | ||
| periodTP = TP.slice(len - period); | ||
|
|
||
| smaTP = sumArray(periodTP) / period; | ||
| meanDev = meanDeviation(periodTP, smaTP) / period; | ||
|
|
||
| CCIPoint = ((TPtemp - smaTP) / (0.015 * meanDev)); | ||
|
|
||
| CCI.push([xVal[i - 1], CCIPoint]); | ||
| xData.push(xVal[i - 1]); | ||
| yData.push(CCIPoint); | ||
| } | ||
|
|
||
| return { | ||
| values: CCI, | ||
| xData: xData, | ||
| yData: yData | ||
| }; | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * A `CCI` series. If the [type](#series.cci.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to | ||
| * [plotOptions.cci](#plotOptions.cci). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.cci | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.cci | ||
| */ | ||
|
|
||
| /** | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.sma.data | ||
| * @product highstock | ||
| * @apioption series.cci.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |
| @@ -0,0 +1,11 @@ | ||
| /* | ||
| Highcharts JS v6.0.4 (2017-12-15) | ||
| (c) 2010-2017 Highsoft AS | ||
| Author: Sebastian Domas | ||
| License: www.highcharts.com/license | ||
| */ | ||
| (function(c){"object"===typeof module&&module.exports?module.exports=c:c(Highcharts)})(function(c){(function(c){c.seriesType("cmf","sma",{name:"Chaikin Money Flow (14)",params:{period:14,volumeSeriesID:"volume"}},{isValid:function(){var d=this.chart,e=this.options,b=this.linkedParent,d=this.volumeSeries||(this.volumeSeries=d.get(e.params.volumeSeriesID)),f=b&&b.yData&&4===b.yData[0].length;return!!(b&&d&&b.xData&&b.xData.length>=e.params.period&&d.xData&&d.xData.length>=e.params.period&&f)},getValues:function(d, | ||
| e){return this.isValid()?this.getMoneyFlow(d.xData,d.yData,this.volumeSeries.yData,e.period):!1},getMoneyFlow:function(d,e,b,f){function c(b,d){var c=b[1],e=b[2];b=b[3];return null!==d&&null!==c&&null!==e&&null!==b&&c!==e?(b-e-(c-b))/(c-e)*d:(p=a,null)}var r=e.length,h=[],g=0,k=0,m=[],n=[],q=[],a,l,p=-1;if(0<f&&f<=r){for(a=0;a<f;a++)h[a]=c(e[a],b[a]),g+=b[a],k+=h[a];m.push(d[a-1]);n.push(a-p>=f&&0!==g?k/g:null);for(q.push([m[0],n[0]]);a<r;a++)h[a]=c(e[a],b[a]),g-=b[a-f],g+=b[a],k-=h[a-f],k+=h[a], | ||
| l=[d[a],a-p>=f?k/g:null],m.push(l[0]),n.push(l[1]),q.push([l[0],l[1]])}return{values:q,xData:m,yData:n}}})})(c)}); |
| @@ -0,0 +1,214 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * (c) 2010-2017 Highsoft AS | ||
| * Author: Sebastian Domas | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
| /** | ||
| * (c) 2010-2017 Highsoft AS | ||
| * Author: Sebastian Domas | ||
| * | ||
| * Chaikin Money Flow indicator for Highstock | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
|
|
||
|
|
||
| H.seriesType('cmf', 'sma', | ||
| /** | ||
| * Chaikin Money Flow indicator (cmf). | ||
| * | ||
| * @type {Object} | ||
| * @extends {plotOptions.sma} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/cmf/ | ||
| * Chaikin Money Flow indicator | ||
| * @since 6.0.0 | ||
| * @excluding animationLimit | ||
| * @optionparent plotOptions.cmf | ||
| */ | ||
| { | ||
| name: 'Chaikin Money Flow (14)', | ||
| params: { | ||
| period: 14, | ||
|
|
||
| /** | ||
| * The id of another series to use its data as volume data for the indiator calculation. | ||
| */ | ||
| volumeSeriesID: 'volume' | ||
| } | ||
| }, { | ||
| /** | ||
| * Checks if the series and volumeSeries are accessible, number of points.x is longer than period, is series has OHLC data | ||
| * @returns {Boolean} true if series is valid and can be computed, otherwise false | ||
| **/ | ||
| isValid: function() { | ||
| var chart = this.chart, | ||
| options = this.options, | ||
| series = this.linkedParent, | ||
| volumeSeries = this.volumeSeries || (this.volumeSeries = chart.get(options.params.volumeSeriesID)), | ||
| isSeriesOHLC = series && series.yData && series.yData[0].length === 4; | ||
|
|
||
| function isLengthValid(serie) { | ||
| return serie.xData && serie.xData.length >= options.params.period; | ||
| } | ||
|
|
||
| return !!(series && volumeSeries && isLengthValid(series) && isLengthValid(volumeSeries) && isSeriesOHLC); | ||
| }, | ||
|
|
||
| /** | ||
| * @typedef {Object} Values | ||
| * @property {Number[][]} values combined xData and yData values into a tuple | ||
| * @property {Number[]} xData values represent x timestamp values | ||
| * @property {Number[]} yData values represent y values | ||
| **/ | ||
|
|
||
| /** | ||
| * Returns indicator's data | ||
| * @returns {False | Values} Returns false if the indicator is not valid, otherwise returns Values object | ||
| **/ | ||
| getValues: function(series, params) { | ||
| if (!this.isValid()) { | ||
| return false; | ||
| } | ||
|
|
||
| return this.getMoneyFlow( | ||
| series.xData, | ||
| series.yData, | ||
| this.volumeSeries.yData, | ||
| params.period | ||
| ); | ||
| }, | ||
|
|
||
| /** | ||
| * @static | ||
| * @param {Number[]} xData x timestamp values | ||
| * @param {Number[]} seriesYData yData of basic series | ||
| * @param {Number[]} volumeSeriesYData yData of volume series | ||
| * @param {Number} period indicator's param | ||
| * @returns {Values} object containing computed money flow data | ||
| **/ | ||
| getMoneyFlow: function(xData, seriesYData, volumeSeriesYData, period) { | ||
| var len = seriesYData.length, | ||
| moneyFlowVolume = [], | ||
| sumVolume = 0, | ||
| sumMoneyFlowVolume = 0, | ||
| moneyFlowXData = [], | ||
| moneyFlowYData = [], | ||
| values = [], | ||
| i, | ||
| point, | ||
| nullIndex = -1; | ||
|
|
||
| /** | ||
| * Calculates money flow volume, changes i, nullIndex vars from upper scope! | ||
| * @private | ||
| * @param {Number[]} ohlc OHLC point | ||
| * @param {Number} volume Volume point's y value | ||
| * @returns {Number} volume * moneyFlowMultiplier | ||
| **/ | ||
| function getMoneyFlowVolume(ohlc, volume) { | ||
| var high = ohlc[1], | ||
| low = ohlc[2], | ||
| close = ohlc[3], | ||
|
|
||
| isValid = | ||
| volume !== null && | ||
| high !== null && | ||
| low !== null && | ||
| close !== null && | ||
| high !== low; | ||
|
|
||
|
|
||
| /** | ||
| * @private | ||
| * @param {Number} h High value | ||
| * @param {Number} l Low value | ||
| * @param {Number} c Close value | ||
| * @returns {Number} calculated multiplier for the point | ||
| **/ | ||
| function getMoneyFlowMultiplier(h, l, c) { | ||
| return ((c - l) - (h - c)) / (h - l); | ||
| } | ||
|
|
||
| return isValid ? getMoneyFlowMultiplier(high, low, close) * volume : ((nullIndex = i), null); | ||
| } | ||
|
|
||
|
|
||
| if (period > 0 && period <= len) { | ||
| for (i = 0; i < period; i++) { | ||
| moneyFlowVolume[i] = getMoneyFlowVolume(seriesYData[i], volumeSeriesYData[i]); | ||
| sumVolume += volumeSeriesYData[i]; | ||
| sumMoneyFlowVolume += moneyFlowVolume[i]; | ||
| } | ||
|
|
||
| moneyFlowXData.push(xData[i - 1]); | ||
| moneyFlowYData.push(i - nullIndex >= period && sumVolume !== 0 ? sumMoneyFlowVolume / sumVolume : null); | ||
| values.push([moneyFlowXData[0], moneyFlowYData[0]]); | ||
|
|
||
| for (; i < len; i++) { | ||
| moneyFlowVolume[i] = getMoneyFlowVolume(seriesYData[i], volumeSeriesYData[i]); | ||
|
|
||
| sumVolume -= volumeSeriesYData[i - period]; | ||
| sumVolume += volumeSeriesYData[i]; | ||
|
|
||
| sumMoneyFlowVolume -= moneyFlowVolume[i - period]; | ||
| sumMoneyFlowVolume += moneyFlowVolume[i]; | ||
|
|
||
| point = [xData[i], i - nullIndex >= period ? sumMoneyFlowVolume / sumVolume : null]; | ||
|
|
||
| moneyFlowXData.push(point[0]); | ||
| moneyFlowYData.push(point[1]); | ||
| values.push([point[0], point[1]]); | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| values: values, | ||
| xData: moneyFlowXData, | ||
| yData: moneyFlowYData | ||
| }; | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * A `CMF` series. If the [type](#series.cmf.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to [plotOptions. | ||
| * cmf](#plotOptions.cmf). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.cmf | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.cmf | ||
| */ | ||
|
|
||
| /** | ||
| * An array of data points for the series. For the `CMF` series type, | ||
| * points are calculated dynamically. | ||
| * | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.line.data | ||
| * @product highstock | ||
| * @apioption series.cmf.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |
| @@ -0,0 +1,11 @@ | ||
| /* | ||
| Highcharts JS v6.0.4 (2017-12-15) | ||
| Indicator series type for Highstock | ||
| (c) 2010-2017 Sebastian Bochan | ||
| License: www.highcharts.com/license | ||
| */ | ||
| (function(a){"object"===typeof module&&module.exports?module.exports=a:a(Highcharts)})(function(a){(function(a){var q=a.isArray;a=a.seriesType;a("ema","sma",{name:"EMA (14)",params:{index:0,period:14}},{getValues:function(a,g){var b=g.period,h=a.xData,c=a.yData,r=c?c.length:0;a=2/(b+1);var d=0,f=0,n=0,k=[],l=[],m=[],e=-1,p=[];if(h.length<b)return!1;for(q(c[0])&&(e=g.index?g.index:0);f<b;)p.push([h[f],0>e?c[f]:c[f][e]]),n+=0>e?c[f]:c[f][e],f++;g=n/b;for(b=f;b<r;b++)f=0>e?c[b-1]:c[b-1][e],d=[h[b-1], | ||
| 0===d?g:f*a+d*(1-a)],k.push(d),l.push(d[0]),m.push(d[1]),d=d[1],p.push([h[b],0>e?c[b]:c[b][e]]);c=0>e?c[b-1]:c[b-1][e];d=[h[b-1],0===d?void 0:c*a+d*(1-a)];k.push(d);l.push(d[0]);m.push(d[1]);return{values:k,xData:l,yData:m}}})})(a)}); |
| @@ -0,0 +1,152 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * Indicator series type for Highstock | ||
| * | ||
| * (c) 2010-2017 Sebastian Bochan | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
|
|
||
| var isArray = H.isArray, | ||
| seriesType = H.seriesType; | ||
|
|
||
| // Utils: | ||
| function accumulateAverage(points, xVal, yVal, i, index) { | ||
| var xValue = xVal[i], | ||
| yValue = index < 0 ? yVal[i] : yVal[i][index]; | ||
|
|
||
| points.push([xValue, yValue]); | ||
| } | ||
|
|
||
| function populateAverage(points, xVal, yVal, i, EMApercent, calEMA, index, SMA) { | ||
| var x = xVal[i - 1], | ||
| yValue = index < 0 ? yVal[i - 1] : yVal[i - 1][index], | ||
| y; | ||
|
|
||
| y = calEMA === 0 ? SMA : ((yValue * EMApercent) + (calEMA * (1 - EMApercent))); | ||
|
|
||
| return [x, y]; | ||
| } | ||
| /** | ||
| * The EMA series type. | ||
| * | ||
| * @constructor seriesTypes.ema | ||
| * @augments seriesTypes.sma | ||
| */ | ||
| seriesType('ema', 'sma', | ||
| /** | ||
| * Exponential moving average indicator (EMA). This series requires `linkedTo` option to be set. | ||
| * | ||
| * @extends {plotOptions.sma} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/ema | ||
| * Exponential moving average indicator | ||
| * @since 6.0.0 | ||
| * @optionparent plotOptions.ema | ||
| */ | ||
| { | ||
| name: 'EMA (14)', | ||
| params: { | ||
| index: 0, | ||
| period: 14 | ||
| } | ||
| }, { | ||
| getValues: function(series, params) { | ||
| var period = params.period, | ||
| xVal = series.xData, | ||
| yVal = series.yData, | ||
| yValLen = yVal ? yVal.length : 0, | ||
| EMApercent = (2 / (period + 1)), | ||
| calEMA = 0, | ||
| range = 0, | ||
| sum = 0, | ||
| EMA = [], | ||
| xData = [], | ||
| yData = [], | ||
| index = -1, | ||
| points = [], | ||
| SMA = 0, | ||
| i, | ||
| 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; | ||
| } | ||
|
|
||
| // Accumulate first N-points | ||
| while (range < period) { | ||
| accumulateAverage(points, xVal, yVal, range, index); | ||
| sum += index < 0 ? yVal[range] : yVal[range][index]; | ||
| range++; | ||
| } | ||
|
|
||
| // first point | ||
| SMA = sum / period; | ||
|
|
||
| // Calculate value one-by-one for each period in visible data | ||
| for (i = range; i < yValLen; i++) { | ||
| EMAPoint = populateAverage(points, xVal, yVal, i, EMApercent, calEMA, index, SMA); | ||
| EMA.push(EMAPoint); | ||
| xData.push(EMAPoint[0]); | ||
| yData.push(EMAPoint[1]); | ||
| calEMA = EMAPoint[1]; | ||
|
|
||
| accumulateAverage(points, xVal, yVal, i, index); | ||
| } | ||
|
|
||
| EMAPoint = populateAverage(points, xVal, yVal, i, EMApercent, calEMA, index); | ||
| EMA.push(EMAPoint); | ||
| xData.push(EMAPoint[0]); | ||
| yData.push(EMAPoint[1]); | ||
|
|
||
| return { | ||
| values: EMA, | ||
| xData: xData, | ||
| yData: yData | ||
| }; | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * A `EMA` series. If the [type](#series.ema.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to | ||
| * [plotOptions.ema](#plotOptions.ema). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.ema | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.ema | ||
| */ | ||
|
|
||
| /** | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.sma.data | ||
| * @product highstock | ||
| * @apioption series.ema.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |
| @@ -0,0 +1,255 @@ | ||
| /** | ||
| * @license Highcharts JS v6.0.4 (2017-12-15) | ||
| * | ||
| * Indicator series type for Highstock | ||
| * | ||
| * (c) 2010-2017 Pawel Fus, Sebastian Bochan | ||
| * | ||
| * License: www.highcharts.com/license | ||
| */ | ||
| 'use strict'; | ||
| (function(factory) { | ||
| if (typeof module === 'object' && module.exports) { | ||
| module.exports = factory; | ||
| } else { | ||
| factory(Highcharts); | ||
| } | ||
| }(function(Highcharts) { | ||
| (function(H) { | ||
|
|
||
| var each = H.each, | ||
| error = H.error, | ||
| Series = H.Series, | ||
| isArray = H.isArray, | ||
| addEvent = H.addEvent, | ||
| seriesType = H.seriesType; | ||
|
|
||
| /** | ||
| * The SMA series type. | ||
| * | ||
| * @constructor seriesTypes.sma | ||
| * @augments seriesTypes.line | ||
| */ | ||
| seriesType('sma', 'line', | ||
| /** | ||
| * Simple moving average indicator (SMA). This series requires `linkedTo` option to be set. | ||
| * | ||
| * @extends {plotOptions.line} | ||
| * @product highstock | ||
| * @sample {highstock} stock/indicators/sma Simple moving average indicator | ||
| * @since 6.0.0 | ||
| * @excluding | ||
| * allAreas,colorAxis,compare,compareBase,joinBy,keys,stacking, | ||
| * showInNavigator,navigatorOptions,pointInterval,pointIntervalUnit, | ||
| * pointPlacement,pointRange,pointStart,joinBy | ||
| * @optionparent plotOptions.sma | ||
| */ | ||
| { | ||
| /** | ||
| * The series name. | ||
| * | ||
| * @type {String} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| name: 'SMA (14)', | ||
| tooltip: { | ||
| /** | ||
| * Number of decimals in indicator series. | ||
| * | ||
| * @type {Number} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| valueDecimals: 4 | ||
| }, | ||
| /** | ||
| * The main series ID that indicator will be based on. Required for this indicator. | ||
| * | ||
| * @type {String} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| linkedTo: undefined, | ||
| params: { | ||
| /** | ||
| * The point index which indicator calculations will base. | ||
| * For example using OHLC data, index=2 means the indicator will be calculated using Low values. | ||
| * | ||
| * @type {Number} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| index: 0, | ||
| /** | ||
| * The base period for indicator calculations. | ||
| * | ||
| * @type {Number} | ||
| * @since 6.0.0 | ||
| * @product highstock | ||
| */ | ||
| period: 14 | ||
| } | ||
| }, /** @lends Highcharts.Series.prototype */ { | ||
| bindTo: { | ||
| series: true, | ||
| eventName: 'updatedData' | ||
| }, | ||
| calculateOn: 'init', | ||
| init: function(chart, options) { | ||
| var indicator = this; | ||
|
|
||
| Series.prototype.init.call( | ||
| indicator, | ||
| chart, | ||
| options | ||
| ); | ||
|
|
||
| // Make sure we find series which is a base for an indicator | ||
| chart.linkSeries(); | ||
|
|
||
| indicator.dataEventsToUnbind = []; | ||
|
|
||
| function recalculateValues() { | ||
| var processedData = indicator.getValues( | ||
| indicator.linkedParent, | ||
| indicator.options.params | ||
| ) || { | ||
| values: [], | ||
| xData: [], | ||
| yData: [] | ||
| }; | ||
|
|
||
| indicator.xData = processedData.xData; | ||
| indicator.yData = processedData.yData; | ||
| indicator.options.data = processedData.values; | ||
|
|
||
| // Removal of processedXData property is required because on first translate processedXData array is empty | ||
| if (indicator.bindTo.series === false) { | ||
| delete indicator.processedXData; | ||
|
|
||
| indicator.isDirty = true; | ||
| indicator.redraw(); | ||
| } | ||
| indicator.isDirtyData = false; | ||
| } | ||
|
|
||
| if (!indicator.linkedParent) { | ||
| return error( | ||
| 'Series ' + | ||
| indicator.options.linkedTo + | ||
| ' not found! Check `linkedTo`.' | ||
| ); | ||
| } | ||
|
|
||
| indicator.dataEventsToUnbind.push( | ||
| addEvent( | ||
| indicator.bindTo.series ? | ||
| indicator.linkedParent : indicator.linkedParent.xAxis, | ||
| indicator.bindTo.eventName, | ||
| recalculateValues | ||
| ) | ||
| ); | ||
|
|
||
| if (indicator.calculateOn === 'init') { | ||
| recalculateValues(); | ||
| } else { | ||
| var unbinder = addEvent( | ||
| indicator.chart, | ||
| indicator.calculateOn, | ||
| function() { | ||
| recalculateValues(); | ||
| // Call this just once, on init | ||
| unbinder(); | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| return indicator; | ||
| }, | ||
| getValues: function(series, params) { | ||
| var period = params.period, | ||
| xVal = series.xData, | ||
| yVal = series.yData, | ||
| yValLen = yVal.length, | ||
| range = 0, | ||
| sum = 0, | ||
| SMA = [], | ||
| xData = [], | ||
| yData = [], | ||
| index = -1, | ||
| i, | ||
| SMAPoint; | ||
|
|
||
| if (xVal.length < period) { | ||
| return false; | ||
| } | ||
|
|
||
| // Switch index for OHLC / Candlestick / Arearange | ||
| if (isArray(yVal[0])) { | ||
| index = params.index ? params.index : 0; | ||
| } | ||
|
|
||
| // Accumulate first N-points | ||
| while (range < period - 1) { | ||
| sum += index < 0 ? yVal[range] : yVal[range][index]; | ||
| range++; | ||
| } | ||
|
|
||
| // Calculate value one-by-one for each period in visible data | ||
| for (i = range; i < yValLen; i++) { | ||
| sum += index < 0 ? yVal[i] : yVal[i][index]; | ||
|
|
||
| SMAPoint = [xVal[i], sum / period]; | ||
| SMA.push(SMAPoint); | ||
| xData.push(SMAPoint[0]); | ||
| yData.push(SMAPoint[1]); | ||
|
|
||
| sum -= index < 0 ? yVal[i - range] : yVal[i - range][index]; | ||
| } | ||
|
|
||
| return { | ||
| values: SMA, | ||
| xData: xData, | ||
| yData: yData | ||
| }; | ||
| }, | ||
| destroy: function() { | ||
| each(this.dataEventsToUnbind, function(unbinder) { | ||
| unbinder(); | ||
| }); | ||
| Series.prototype.destroy.call(this); | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * A `SMA` series. If the [type](#series.sma.type) option is not | ||
| * specified, it is inherited from [chart.type](#chart.type). | ||
| * | ||
| * For options that apply to multiple series, it is recommended to add | ||
| * them to the [plotOptions.series](#plotOptions.series) options structure. | ||
| * To apply to all series of this specific type, apply it to [plotOptions. | ||
| * sma](#plotOptions.sma). | ||
| * | ||
| * @type {Object} | ||
| * @since 6.0.0 | ||
| * @extends series,plotOptions.sma | ||
| * @excluding data,dataParser,dataURL | ||
| * @product highstock | ||
| * @apioption series.sma | ||
| */ | ||
|
|
||
|
|
||
| /** | ||
| * An array of data points for the series. For the `SMA` series type, | ||
| * points are calculated dynamically. | ||
| * | ||
| * @type {Array<Object|Array>} | ||
| * @since 6.0.0 | ||
| * @extends series.line.data | ||
| * @product highstock | ||
| * @apioption series.sma.data | ||
| */ | ||
|
|
||
| }(Highcharts)); | ||
| })); |