Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1,027 highstock.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -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));
}));

Large diffs are not rendered by default.

@@ -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));
}));