@dickyindra/klinecharts
Version:
Lightweight k-line chart built with html5 canvas
1,876 lines (1,674 loc) • 558 kB
JavaScript
/**
* @license
* KLineChart v8.3.6-7
* Copyright (c) 2019 lihu.
* Licensed under Apache License 2.0 https://www.apache.org/licenses/LICENSE-2.0
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.klinecharts = {}));
})(this, (function (exports) { 'use strict';
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 成交均线
*/
var averagePrice = {
name: 'AVP',
shortName: 'AVP',
series: 'price',
precision: 2,
plots: [{
key: 'avp',
title: 'AVP: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList) {
var totalTurnover = 0;
var totalVolume = 0;
return dataList.map(function (kLineData) {
var avp = {};
var turnover = kLineData.turnover || 0;
var volume = kLineData.volume || 0;
totalTurnover += turnover;
totalVolume += volume;
if (totalVolume !== 0) {
avp.avp = totalTurnover / totalVolume;
}
return avp;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 多空指标
* 公式: BBI = (MA(CLOSE, M) + MA(CLOSE, N) + MA(CLOSE, O) + MA(CLOSE, P)) / 4
*
*/
var bullAndBearIndex = {
name: 'BBI',
shortName: 'BBI',
series: 'price',
precision: 2,
calcParams: [3, 6, 12, 24],
shouldCheckParamCount: true,
shouldOhlc: true,
plots: [{
key: 'bbi',
title: 'BBI: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var maxPeriod = Math.max.apply(null, params);
var closeSums = [];
var mas = [];
return dataList.map(function (kLineData, i) {
var bbi = {};
var close = kLineData.close;
params.forEach(function (p, index) {
closeSums[index] = (closeSums[index] || 0) + close;
if (i >= p - 1) {
mas[index] = closeSums[index] / p;
closeSums[index] -= dataList[i - (p - 1)].close;
}
});
if (i >= maxPeriod - 1) {
var maSum = 0;
mas.forEach(function (ma) {
maSum += ma;
});
bbi.bbi = maSum / 4;
}
return bbi;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* DMA
* 公式:DIF:MA(CLOSE,N1)-MA(CLOSE,N2);DIFMA:MA(DIF,M)
*/
var differentOfMovingAverage = {
name: 'DMA',
shortName: 'DMA',
calcParams: [10, 50, 10],
plots: [{
key: 'dma',
title: 'DMA: ',
type: 'line'
}, {
key: 'ama',
title: 'AMA: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var maxPeriod = Math.max(params[0], params[1]);
var closeSum1 = 0;
var closeSum2 = 0;
var dmaSum = 0;
var result = [];
dataList.forEach(function (kLineData, i) {
var dma = {};
var close = kLineData.close;
closeSum1 += close;
closeSum2 += close;
var ma1;
var ma2;
if (i >= params[0] - 1) {
ma1 = closeSum1 / params[0];
closeSum1 -= dataList[i - (params[0] - 1)].close;
}
if (i >= params[1] - 1) {
ma2 = closeSum2 / params[1];
closeSum2 -= dataList[i - (params[1] - 1)].close;
}
if (i >= maxPeriod - 1) {
var dif = ma1 - ma2;
dma.dma = dif;
dmaSum += dif;
if (i >= maxPeriod + params[2] - 2) {
dma.ama = dmaSum / params[2];
dmaSum -= result[i - (params[2] - 1)].dma;
}
}
result.push(dma);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* DMI
*
* MTR:=EXPMEMA(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(REF(CLOSE,1)-LOW)),N)
* HD :=HIGH-REF(HIGH,1);
* LD :=REF(LOW,1)-LOW;
* DMP:=EXPMEMA(IF(HD>0&&HD>LD,HD,0),N);
* DMM:=EXPMEMA(IF(LD>0&&LD>HD,LD,0),N);
*
* PDI: DMP*100/MTR;
* MDI: DMM*100/MTR;
* ADX: EXPMEMA(ABS(MDI-PDI)/(MDI+PDI)*100,MM);
* ADXR:EXPMEMA(ADX,MM);
* 公式含义:
* MTR赋值:最高价-最低价和最高价-昨收的绝对值的较大值和昨收-最低价的绝对值的较大值的N日指数平滑移动平均
* HD赋值:最高价-昨日最高价
* LD赋值:昨日最低价-最低价
* DMP赋值:如果HD>0并且HD>LD,返回HD,否则返回0的N日指数平滑移动平均
* DMM赋值:如果LD>0并且LD>HD,返回LD,否则返回0的N日指数平滑移动平均
* 输出PDI:DMP*100/MTR
* 输出MDI:DMM*100/MTR
* 输出ADX:MDI-PDI的绝对值/(MDI+PDI)*100的MM日指数平滑移动平均
* 输出ADXR:ADX的MM日指数平滑移动平均
*
*/
var directionalMovementIndex = {
name: 'DMI',
shortName: 'DMI',
calcParams: [14, 6],
plots: [{
key: 'pdi',
title: 'PDI: ',
type: 'line'
}, {
key: 'mdi',
title: 'MDI: ',
type: 'line'
}, {
key: 'adx',
title: 'ADX: ',
type: 'line'
}, {
key: 'adxr',
title: 'ADXR: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var trSum = 0;
var hSum = 0;
var lSum = 0;
var mtr = 0;
var dmp = 0;
var dmm = 0;
var dxSum = 0;
var adx = 0;
var result = [];
dataList.forEach(function (kLineData, i) {
var dmi = {};
var preKLineData = dataList[i - 1] || kLineData;
var preClose = preKLineData.close;
var high = kLineData.high;
var low = kLineData.low;
var hl = high - low;
var hcy = Math.abs(high - preClose);
var lcy = Math.abs(preClose - low);
var hhy = high - preKLineData.high;
var lyl = preKLineData.low - low;
var tr = Math.max(Math.max(hl, hcy), lcy);
var h = hhy > 0 && hhy > lyl ? hhy : 0;
var l = lyl > 0 && lyl > hhy ? lyl : 0;
trSum += tr;
hSum += h;
lSum += l;
if (i >= params[0] - 1) {
if (i > params[0] - 1) {
mtr = mtr - mtr / params[0] + tr;
dmp = dmp - dmp / params[0] + h;
dmm = dmm - dmm / params[0] + l;
} else {
mtr = trSum;
dmp = hSum;
dmm = lSum;
}
var pdi = 0;
var mdi = 0;
if (mtr !== 0) {
pdi = dmp * 100 / mtr;
mdi = dmm * 100 / mtr;
}
dmi.pdi = pdi;
dmi.mdi = mdi;
var dx = 0;
if (mdi + pdi !== 0) {
dx = Math.abs(mdi - pdi) / (mdi + pdi) * 100;
}
dxSum += dx;
if (i >= params[0] * 2 - 2) {
if (i > params[0] * 2 - 2) {
adx = (adx * (params[0] - 1) + dx) / params[0];
} else {
adx = dxSum / params[0];
}
dmi.adx = adx;
if (i >= params[0] * 2 + params[1] - 3) {
dmi.adxr = (result[i - (params[1] - 1)].adx + adx) / 2;
}
}
}
result.push(dmi);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* EMV 简易波动指标
* 公式:
* A=(今日最高+今日最低)/2
* B=(前日最高+前日最低)/2
* C=今日最高-今日最低
* EM=(A-B)*C/今日成交额
* EMV=N日内EM的累和
* MAEMV=EMV的M日的简单移动平均
*
*/
var easeOfMovementValue = {
name: 'EMV',
shortName: 'EMV',
calcParams: [14, 9],
plots: [{
key: 'emv',
title: 'EMV: ',
type: 'line'
}, {
key: 'maEmv',
title: 'MAEMV: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var emSum = 0;
var emvSum = 0;
var emList = [];
var result = [];
dataList.forEach(function (kLineData, i) {
var emv = {};
var preKLineData = dataList[i - 1] || kLineData;
var high = kLineData.high;
var low = kLineData.low;
var turnover = kLineData.turnover || 0;
var halfHl = (high + low) / 2;
var preHalfHl = (preKLineData.high + preKLineData.low) / 2;
var hl = high - low;
var em = 0;
if (turnover !== 0) {
em = (halfHl - preHalfHl) * hl / turnover;
}
emList.push(em);
emSum += em;
if (i >= params[0] - 1) {
emv.emv = emSum;
emSum -= emList[i - (params[0] - 1)];
emvSum += emv.emv;
if (i >= params[0] + params[1] - 2) {
emv.maEmv = emvSum / params[1];
emvSum -= result[i - (params[1] - 1)].emv;
}
}
result.push(emv);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* EMA 指数移动平均
*/
var exponentialMovingAverage = {
name: 'EMA',
shortName: 'EMA',
series: 'price',
calcParams: [6, 12, 20],
precision: 2,
shouldCheckParamCount: false,
shouldOhlc: true,
plots: [{
key: 'ema6',
title: 'EMA6: ',
type: 'line'
}, {
key: 'ema12',
title: 'EMA12: ',
type: 'line'
}, {
key: 'ema20',
title: 'EMA20: ',
type: 'line'
}],
regeneratePlots: function regeneratePlots(params) {
return params.map(function (p) {
return {
key: "ema".concat(p),
title: "EMA".concat(p, ": "),
type: 'line'
};
});
},
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params,
plots = _ref.plots;
var closeSum = 0;
var emaValues = [];
return dataList.map(function (kLineData, i) {
var ema = {};
var close = kLineData.close;
closeSum += close;
params.forEach(function (p, index) {
if (i >= p - 1) {
if (i > p - 1) {
emaValues[index] = (2 * close + (p - 1) * emaValues[index]) / (p + 1);
} else {
emaValues[index] = closeSum / p;
}
ema[plots[index].key] = emaValues[index];
}
});
return ema;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* MA 移动平均
*/
var movingAverage = {
name: 'MA',
shortName: 'MA',
series: 'price',
calcParams: [5, 10, 30, 60],
precision: 2,
shouldCheckParamCount: false,
shouldOhlc: true,
plots: [{
key: 'ma5',
title: 'MA5: ',
type: 'line'
}, {
key: 'ma10',
title: 'MA10: ',
type: 'line'
}, {
key: 'ma30',
title: 'MA30: ',
type: 'line'
}, {
key: 'ma60',
title: 'MA60: ',
type: 'line'
}],
regeneratePlots: function regeneratePlots(params) {
return params.map(function (p) {
return {
key: "ma".concat(p),
title: "MA".concat(p, ": "),
type: 'line'
};
});
},
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params,
plots = _ref.plots;
var closeSums = [];
return dataList.map(function (kLineData, i) {
var ma = {};
var close = kLineData.close;
params.forEach(function (p, index) {
closeSums[index] = (closeSums[index] || 0) + close;
if (i >= p - 1) {
ma[plots[index].key] = closeSums[index] / p;
closeSums[index] -= dataList[i - (p - 1)].close;
}
});
return ma;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* MACD:参数快线移动平均、慢线移动平均、移动平均,
* 默认参数值12、26、9。
* 公式:⒈首先分别计算出收盘价12日指数平滑移动平均线与26日指数平滑移动平均线,分别记为EMA(12)与EMA(26)。
* ⒉求这两条指数平滑移动平均线的差,即:DIFF = EMA(SHORT) - EMA(LONG)。
* ⒊再计算DIFF的M日的平均的指数平滑移动平均线,记为DEA。
* ⒋最后用DIFF减DEA,得MACD。MACD通常绘制成围绕零轴线波动的柱形图。MACD柱状大于0涨颜色,小于0跌颜色。
*/
var movingAverageConvergenceDivergence = {
name: 'MACD',
shortName: 'MACD',
calcParams: [12, 26, 9],
plots: [{
key: 'dif',
title: 'DIF: ',
type: 'line'
}, {
key: 'dea',
title: 'DEA: ',
type: 'line'
}, {
key: 'macd',
title: 'MACD: ',
type: 'bar',
baseValue: 0,
color: function color(data, options) {
var current = data.current;
var macd = (current.technicalIndicatorData || {}).macd;
if (macd > 0) {
return options.bar.upColor;
} else if (macd < 0) {
return options.bar.downColor;
} else {
return options.bar.noChangeColor;
}
},
isStroke: function isStroke(data) {
var prev = data.prev,
current = data.current;
var macd = (current.technicalIndicatorData || {}).macd;
var preMacd = (prev.technicalIndicatorData || {}).macd;
return preMacd < macd;
}
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var closeSum = 0;
var emaShort;
var emaLong;
var dif = 0;
var difSum = 0;
var dea = 0;
var maxPeriod = Math.max(params[0], params[1]);
return dataList.map(function (kLineData, i) {
var macd = {};
var close = kLineData.close;
closeSum += close;
if (i >= params[0] - 1) {
if (i > params[0] - 1) {
emaShort = (2 * close + (params[0] - 1) * emaShort) / (params[0] + 1);
} else {
emaShort = closeSum / params[0];
}
}
if (i >= params[1] - 1) {
if (i > params[1] - 1) {
emaLong = (2 * close + (params[1] - 1) * emaLong) / (params[1] + 1);
} else {
emaLong = closeSum / params[1];
}
}
if (i >= maxPeriod - 1) {
dif = emaShort - emaLong;
macd.dif = dif;
difSum += dif;
if (i >= maxPeriod + params[2] - 2) {
if (i > maxPeriod + params[2] - 2) {
dea = (dif * 2 + dea * (params[2] - 1)) / (params[2] + 1);
} else {
dea = difSum / params[2];
}
macd.macd = (dif - dea) * 2;
macd.dea = dea;
}
}
return macd;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* sma
*/
var simpleMovingAverage = {
name: 'SMA',
shortName: 'SMA',
series: 'price',
calcParams: [12, 2],
precision: 2,
plots: [{
key: 'sma',
title: 'SMA: ',
type: 'line'
}],
shouldCheckParamCount: true,
shouldOhlc: true,
calcTechnicalIndicator: function calcTechnicalIndicator(kLineDataList, _ref) {
var params = _ref.params;
var closeSum = 0;
var smaValue = 0;
return kLineDataList.map(function (kLineData, i) {
var sma = {};
var close = kLineData.close;
closeSum += close;
if (i >= params[0] - 1) {
if (i > params[0] - 1) {
smaValue = (close * params[1] + smaValue * (params[0] - params[1] + 1)) / (params[0] + 1);
} else {
smaValue = closeSum / params[0];
}
sma.sma = smaValue;
}
return sma;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http:*www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* trix
*
* TR=收盘价的N日指数移动平均的N日指数移动平均的N日指数移动平均;
* TRIX=(TR-昨日TR)/昨日TR*100;
* MATRIX=TRIX的M日简单移动平均;
* 默认参数N设为12,默认参数M设为9;
* 默认参数12、9
* 公式:MTR:=EMA(EMA(EMA(CLOSE,N),N),N)
* TRIX:(MTR-REF(MTR,1))/REF(MTR,1)*100;
* TRMA:MA(TRIX,M)
*
*/
var tripleExponentiallySmoothedAverage = {
name: 'TRIX',
shortName: 'TRIX',
calcParams: [12, 9],
plots: [{
key: 'trix',
title: 'TRIX: ',
type: 'line'
}, {
key: 'maTrix',
title: 'MATRIX: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var closeSum = 0;
var ema1;
var ema2;
var oldTr;
var ema1Sum = 0;
var ema2Sum = 0;
var trixSum = 0;
var result = [];
dataList.forEach(function (kLineData, i) {
var trix = {};
var close = kLineData.close;
closeSum += close;
if (i >= params[0] - 1) {
if (i > params[0] - 1) {
ema1 = (2 * close + (params[0] - 1) * ema1) / (params[0] + 1);
} else {
ema1 = closeSum / params[0];
}
ema1Sum += ema1;
if (i >= params[0] * 2 - 2) {
if (i > params[0] * 2 - 2) {
ema2 = (2 * ema1 + (params[0] - 1) * ema2) / (params[0] + 1);
} else {
ema2 = ema1Sum / params[0];
}
ema2Sum += ema2;
if (i >= params[0] * 3 - 3) {
var tr;
var trixValue = 0;
if (i > params[0] * 3 - 3) {
tr = (2 * ema2 + (params[0] - 1) * oldTr) / (params[0] + 1);
trixValue = (tr - oldTr) / oldTr * 100;
} else {
tr = ema2Sum / params[0];
}
oldTr = tr;
trix.trix = trixValue;
trixSum += trixValue;
if (i >= params[0] * 3 + params[1] - 4) {
trix.maTrix = trixSum / params[1];
trixSum -= result[i - (params[1] - 1)].trix;
}
}
}
}
result.push(trix);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* BRAR
* 默认参数是26。
* 公式N日BR=N日内(H-CY)之和除以N日内(CY-L)之和*100,
* 其中,H为当日最高价,L为当日最低价,CY为前一交易日的收盘价,N为设定的时间参数。
* N日AR=(N日内(H-O)之和除以N日内(O-L)之和)*100,
* 其中,H为当日最高价,L为当日最低价,O为当日开盘价,N为设定的时间参数
*
*/
var brar = {
name: 'BRAR',
shortName: 'BRAR',
calcParams: [26],
plots: [{
key: 'br',
title: 'BR: ',
type: 'line'
}, {
key: 'ar',
title: 'AR: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var hcy = 0;
var cyl = 0;
var ho = 0;
var ol = 0;
return dataList.map(function (kLineData, i) {
var brar = {};
var high = kLineData.high;
var low = kLineData.low;
var open = kLineData.open;
var preClose = (dataList[i - 1] || kLineData).close;
ho += high - open;
ol += open - low;
hcy += high - preClose;
cyl += preClose - low;
if (i >= params[0] - 1) {
if (ol !== 0) {
brar.ar = ho / ol * 100;
} else {
brar.ar = 0;
}
if (cyl !== 0) {
brar.br = hcy / cyl * 100;
} else {
brar.br = 0;
}
var agoKLineData = dataList[i - (params[0] - 1)];
var agoHigh = agoKLineData.high;
var agoLow = agoKLineData.low;
var agoOpen = agoKLineData.open;
var agoPreClose = (dataList[i - params[0]] || dataList[i - (params[0] - 1)]).close;
hcy -= agoHigh - agoPreClose;
cyl -= agoPreClose - agoLow;
ho -= agoHigh - agoOpen;
ol -= agoOpen - agoLow;
}
return brar;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http:*www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* MID:=REF(HIGH+LOW,1)/2;
* CR:SUM(MAX(0,HIGH-MID),N)/SUM(MAX(0,MID-LOW),N)*100;
* MA1:REF(MA(CR,M1),M1/2.5+1);
* MA2:REF(MA(CR,M2),M2/2.5+1);
* MA3:REF(MA(CR,M3),M3/2.5+1);
* MA4:REF(MA(CR,M4),M4/2.5+1);
* MID赋值:(昨日最高价+昨日最低价)/2
* 输出带状能量线:0和最高价-MID的较大值的N日累和/0和MID-最低价的较大值的N日累和*100
* 输出MA1:M1(5)/2.5+1日前的CR的M1(5)日简单移动平均
* 输出MA2:M2(10)/2.5+1日前的CR的M2(10)日简单移动平均
* 输出MA3:M3(20)/2.5+1日前的CR的M3(20)日简单移动平均
* 输出MA4:M4/2.5+1日前的CR的M4日简单移动平均
*
*/
var currentRatio = {
name: 'CR',
shortName: 'CR',
calcParams: [26, 10, 20, 40, 60],
plots: [{
key: 'cr',
title: 'CR: ',
type: 'line'
}, {
key: 'ma1',
title: 'MA1: ',
type: 'line'
}, {
key: 'ma2',
title: 'MA2: ',
type: 'line'
}, {
key: 'ma3',
title: 'MA3: ',
type: 'line'
}, {
key: 'ma4',
title: 'MA4: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var ma1ForwardPeriod = Math.ceil(params[1] / 2.5 + 1);
var ma2ForwardPeriod = Math.ceil(params[2] / 2.5 + 1);
var ma3ForwardPeriod = Math.ceil(params[3] / 2.5 + 1);
var ma4ForwardPeriod = Math.ceil(params[4] / 2.5 + 1);
var ma1Sum = 0;
var ma1List = [];
var ma2Sum = 0;
var ma2List = [];
var ma3Sum = 0;
var ma3List = [];
var ma4Sum = 0;
var ma4List = [];
var result = [];
dataList.forEach(function (kLineData, i) {
var cr = {};
var preData = dataList[i - 1] || kLineData;
var preMid = (preData.high + preData.close + preData.low + preData.open) / 4;
var highSubPreMid = Math.max(0, kLineData.high - preMid);
var preMidSubLow = Math.max(0, preMid - kLineData.low);
if (i >= params[0] - 1) {
if (preMidSubLow !== 0) {
cr.cr = highSubPreMid / preMidSubLow * 100;
} else {
cr.cr = 0;
}
ma1Sum += cr.cr;
ma2Sum += cr.cr;
ma3Sum += cr.cr;
ma4Sum += cr.cr;
if (i >= params[0] + params[1] - 2) {
ma1List.push(ma1Sum / params[1]);
if (i >= params[0] + params[1] + ma1ForwardPeriod - 3) {
cr.ma1 = ma1List[ma1List.length - 1 - ma1ForwardPeriod];
}
ma1Sum -= result[i - (params[1] - 1)].cr;
}
if (i >= params[0] + params[2] - 2) {
ma2List.push(ma2Sum / params[2]);
if (i >= params[0] + params[2] + ma2ForwardPeriod - 3) {
cr.ma2 = ma2List[ma2List.length - 1 - ma2ForwardPeriod];
}
ma2Sum -= result[i - (params[2] - 1)].cr;
}
if (i >= params[0] + params[3] - 2) {
ma3List.push(ma3Sum / params[3]);
if (i >= params[0] + params[3] + ma3ForwardPeriod - 3) {
cr.ma3 = ma3List[ma3List.length - 1 - ma3ForwardPeriod];
}
ma3Sum -= result[i - (params[3] - 1)].cr;
}
if (i >= params[0] + params[4] - 2) {
ma4List.push(ma4Sum / params[4]);
if (i >= params[0] + params[4] + ma4ForwardPeriod - 3) {
cr.ma4 = ma4List[ma4List.length - 1 - ma4ForwardPeriod];
}
ma4Sum -= result[i - (params[4] - 1)].cr;
}
}
result.push(cr);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* mtm
* 公式 MTM(N日)=C-CN
*/
var momentum = {
name: 'MTM',
shortName: 'MTM',
calcParams: [12, 6],
plots: [{
key: 'mtm',
title: 'MTM: ',
type: 'line'
}, {
key: 'maMtm',
title: 'MAMTM: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var mtmSum = 0;
var result = [];
dataList.forEach(function (kLineData, i) {
var mtm = {};
if (i >= params[0]) {
var close = kLineData.close;
var agoClose = dataList[i - params[0]].close;
mtm.mtm = close - agoClose;
mtmSum += mtm.mtm;
if (i >= params[0] + params[1] - 1) {
mtm.maMtm = mtmSum / params[1];
mtmSum -= result[i - (params[1] - 1)].mtm;
}
}
result.push(mtm);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* PSY
* 公式:PSY=N日内的上涨天数/N×100%。
*/
var psychologicalLine = {
name: 'PSY',
shortName: 'PSY',
calcParams: [12, 6],
plots: [{
key: 'psy',
title: 'PSY: ',
type: 'line'
}, {
key: 'maPsy',
title: 'MAPSY: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var upCount = 0;
var psySum = 0;
var upList = [];
var result = [];
dataList.forEach(function (kLineData, i) {
var psy = {};
var preClose = (dataList[i - 1] || kLineData).close;
var upFlag = kLineData.close - preClose > 0 ? 1 : 0;
upList.push(upFlag);
upCount += upFlag;
if (i >= params[0] - 1) {
psy.psy = upCount / params[0] * 100;
psySum += psy.psy;
if (i >= params[0] + params[1] - 2) {
psy.maPsy = psySum / params[1];
psySum -= result[i - (params[1] - 1)].psy;
}
upCount -= upList[i - (params[0] - 1)];
}
result.push(psy);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 变动率指标
* 公式:ROC = (CLOSE - REF(CLOSE, N)) / REF(CLOSE, N)
*/
var rateOfChange = {
name: 'ROC',
shortName: 'ROC',
calcParams: [12, 6],
shouldCheckParamCount: true,
plots: [{
key: 'roc',
title: 'ROC: ',
type: 'line'
}, {
key: 'maRoc',
title: 'MAROC: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(kLineDataList, _ref) {
var params = _ref.params;
var result = [];
var rocSum = 0;
kLineDataList.forEach(function (kLineData, i) {
var roc = {};
if (i >= params[0] - 1) {
var close = kLineData.close;
var agoClose = (kLineDataList[i - params[0]] || kLineDataList[i - (params[0] - 1)]).close;
if (agoClose !== 0) {
roc.roc = (close - agoClose) / agoClose * 100;
} else {
roc.roc = 0;
}
rocSum += roc.roc;
if (i >= params[0] - 1 + params[1] - 1) {
roc.maRoc = rocSum / params[1];
rocSum -= result[i - (params[1] - 1)].roc;
}
}
result.push(roc);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* VR
* VR=(UVS+1/2PVS)/(DVS+1/2PVS)
* 24天以来凡是股价上涨那一天的成交量都称为AV,将24天内的AV总和相加后称为UVS
* 24天以来凡是股价下跌那一天的成交量都称为BV,将24天内的BV总和相加后称为DVS
* 24天以来凡是股价不涨不跌,则那一天的成交量都称为CV,将24天内的CV总和相加后称为PVS
*
*/
var volumeRatio = {
name: 'VR',
shortName: 'VR',
calcParams: [26, 6],
plots: [{
key: 'vr',
title: 'VR: ',
type: 'line'
}, {
key: 'maVr',
title: 'MAVR: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var uvs = 0;
var dvs = 0;
var pvs = 0;
var vrSum = 0;
var result = [];
dataList.forEach(function (kLineData, i) {
var vr = {};
var close = kLineData.close;
var preClose = (dataList[i - 1] || kLineData).close;
var volume = kLineData.volume;
if (close > preClose) {
uvs += volume;
} else if (close < preClose) {
dvs += volume;
} else {
pvs += volume;
}
if (i >= params[0] - 1) {
var halfPvs = pvs / 2;
if (dvs + halfPvs === 0) {
vr.vr = 0;
} else {
vr.vr = (uvs + halfPvs) / (dvs + halfPvs) * 100;
}
vrSum += vr.vr;
if (i >= params[0] + params[1] - 2) {
vr.maVr = vrSum / params[1];
vrSum -= result[i - (params[1] - 1)].vr;
}
var agoData = dataList[i - (params[0] - 1)];
var agoPreData = dataList[i - params[0]] || agoData;
var agoClose = agoData.close;
var agoVolume = agoData.volume;
if (agoClose > agoPreData.close) {
uvs -= agoVolume;
} else if (agoClose < agoPreData.close) {
dvs -= agoVolume;
} else {
pvs -= agoVolume;
}
}
result.push(vr);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var awesomeOscillator = {
name: 'AO',
shortName: 'AO',
calcParams: [5, 34],
shouldCheckParamCount: true,
plots: [{
key: 'ao',
title: 'AO: ',
type: 'bar',
baseValue: 0,
color: function color(data, options) {
var prev = data.prev,
current = data.current;
var preAo = (prev.technicalIndicatorData || {}).ao;
var ao = (current.technicalIndicatorData || {}).ao;
if (ao > preAo) {
return options.bar.upColor;
} else {
return options.bar.downColor;
}
},
isStroke: function isStroke(data) {
var prev = data.prev,
current = data.current;
var preAo = (prev.technicalIndicatorData || {}).ao;
var ao = (current.technicalIndicatorData || {}).ao;
return ao > preAo;
}
}],
calcTechnicalIndicator: function calcTechnicalIndicator(kLineDataList, _ref) {
var params = _ref.params;
var maxPeriod = Math.max(params[0], params[1]);
var shortSum = 0;
var longSum = 0;
var short = 0;
var long = 0;
return kLineDataList.map(function (kLineData, i) {
var ao = {};
var middle = (kLineData.low + kLineData.high) / 2;
shortSum += middle;
longSum += middle;
if (i >= params[0] - 1) {
short = shortSum / params[0];
var agoKLineData = kLineDataList[i - (params[0] - 1)];
shortSum -= (agoKLineData.low + agoKLineData.high) / 2;
}
if (i >= params[1] - 1) {
long = longSum / params[1];
var _agoKLineData = kLineDataList[i - (params[1] - 1)];
longSum -= (_agoKLineData.low + _agoKLineData.high) / 2;
}
if (i >= maxPeriod - 1) {
ao.ao = short - long;
}
return ao;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* BIAS
* 乖离率=[(当日收盘价-N日平均价)/N日平均价]*100%
*/
var bias = {
name: 'BIAS',
shortName: 'BIAS',
calcParams: [6, 12, 24],
shouldCheckParamCount: false,
plots: [{
key: 'bias6',
title: 'BIAS6: ',
type: 'line'
}, {
key: 'bias12',
title: 'BIAS12: ',
type: 'line'
}, {
key: 'bias24',
title: 'BIAS24: ',
type: 'line'
}],
regeneratePlots: function regeneratePlots(params) {
return params.map(function (p) {
return {
key: "bias".concat(p),
title: "BIAS".concat(p, ": "),
type: 'line'
};
});
},
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params,
plots = _ref.plots;
var closeSums = [];
return dataList.map(function (kLineData, i) {
var bias = {};
var close = kLineData.close;
params.forEach(function (p, index) {
closeSums[index] = (closeSums[index] || 0) + close;
if (i >= p - 1) {
var mean = closeSums[index] / params[index];
bias[plots[index].key] = (close - mean) / mean * 100;
closeSums[index] -= dataList[i - (p - 1)].close;
}
});
return bias;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* CCI
* CCI(N日)=(TP-MA)÷MD÷0.015
* 其中,TP=(最高价+最低价+收盘价)÷3
* MA=近N日TP价的累计之和÷N
* MD=近N日TP - 当前MA绝对值的累计之和÷N
*
*/
var commodityChannelIndex = {
name: 'CCI',
shortName: 'CCI',
calcParams: [20],
plots: [{
key: 'cci',
title: 'CCI: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var p = params[0] - 1;
var tpSum = 0;
var tpList = [];
return dataList.map(function (kLineData, i) {
var cci = {};
var tp = (kLineData.high + kLineData.low + kLineData.close) / 3;
tpSum += tp;
tpList.push(tp);
if (i >= p) {
var maTp = tpSum / params[0];
var sliceTpList = tpList.slice(i - p, i + 1);
var sum = 0;
sliceTpList.forEach(function (tp) {
sum += Math.abs(tp - maTp);
});
var md = sum / params[0];
cci.cci = md !== 0 ? (tp - maTp) / md / 0.015 : 0;
var agoTp = (dataList[i - p].high + dataList[i - p].low + dataList[i - p].close) / 3;
tpSum -= agoTp;
}
return cci;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* RSI
* RSI = SUM(MAX(CLOSE - REF(CLOSE,1),0),N) / SUM(ABS(CLOSE - REF(CLOSE,1)),N) × 100
*/
var relativeStrengthIndex = {
name: 'RSI',
shortName: 'RSI',
calcParams: [6, 12, 24],
shouldCheckParamCount: false,
plots: [{
key: 'rsi1',
title: 'RSI1: ',
type: 'line'
}, {
key: 'rsi2',
title: 'RSI2: ',
type: 'line'
}, {
key: 'rsi3',
title: 'RSI3: ',
type: 'line'
}],
regeneratePlots: function regeneratePlots(params) {
return params.map(function (_, index) {
var num = index + 1;
return {
key: "rsi".concat(num),
title: "RSI".concat(num, ": "),
type: 'line'
};
});
},
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params,
plots = _ref.plots;
var sumCloseAs = [];
var sumCloseBs = [];
return dataList.map(function (kLineData, i) {
var rsi = {};
var preClose = (dataList[i - 1] || kLineData).close;
var tmp = kLineData.close - preClose;
params.forEach(function (p, index) {
if (tmp > 0) {
sumCloseAs[index] = (sumCloseAs[index] || 0) + tmp;
} else {
sumCloseBs[index] = (sumCloseBs[index] || 0) + Math.abs(tmp);
}
if (i >= p - 1) {
if (sumCloseBs[index] !== 0) {
rsi[plots[index].key] = 100 - 100.0 / (1 + sumCloseAs[index] / sumCloseBs[index]);
} else {
rsi[plots[index].key] = 0;
}
var agoData = dataList[i - (p - 1)];
var agoPreData = dataList[i - p] || agoData;
var agoTmp = agoData.close - agoPreData.close;
if (agoTmp > 0) {
sumCloseAs[index] -= agoTmp;
} else {
sumCloseBs[index] -= Math.abs(agoTmp);
}
}
});
return rsi;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 计算n周期内最高和最低
* @param dataList
* @returns {{ln: number, hn: number}}
*/
function calcHnLn() {
var dataList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var hn = Number.MIN_SAFE_INTEGER;
var ln = Number.MAX_SAFE_INTEGER;
dataList.forEach(function (data) {
hn = Math.max(data.high, hn);
ln = Math.min(data.low, ln);
});
return {
hn: hn,
ln: ln
};
}
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* KDJ
*
* 当日K值=2/3×前一日K值+1/3×当日RSV
* 当日D值=2/3×前一日D值+1/3×当日K值
* 若无前一日K 值与D值,则可分别用50来代替。
* J值=3*当日K值-2*当日D值
*/
var stockIndicatorKDJ = {
name: 'KDJ',
shortName: 'KDJ',
calcParams: [9, 3, 3],
plots: [{
key: 'k',
title: 'K: ',
type: 'line'
}, {
key: 'd',
title: 'D: ',
type: 'line'
}, {
key: 'j',
title: 'J: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var result = [];
dataList.forEach(function (kLineData, i) {
var kdj = {};
var close = kLineData.close;
if (i >= params[0] - 1) {
var lhn = calcHnLn(dataList.slice(i - (params[0] - 1), i + 1));
var ln = lhn.ln;
var hn = lhn.hn;
var hnSubLn = hn - ln;
var rsv = (close - ln) / (hnSubLn === 0 ? 1 : hnSubLn) * 100;
kdj.k = ((params[1] - 1) * (result[i - 1].k || 50) + rsv) / params[1];
kdj.d = ((params[2] - 1) * (result[i - 1].d || 50) + kdj.k) / params[2];
kdj.j = 3.0 * kdj.k - 2.0 * kdj.d;
}
result.push(kdj);
});
return result;
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* WR
* 公式 WR(N) = 100 * [ C - HIGH(N) ] / [ HIGH(N)-LOW(N) ]
*/
var williamsR = {
name: 'WR',
shortName: 'WR',
calcParams: [6, 10, 14],
shouldCheckParamCount: false,
plots: [{
key: 'wr1',
title: 'WR1: ',
type: 'line'
}, {
key: 'wr2',
title: 'WR2: ',
type: 'line'
}, {
key: 'wr3',
title: 'WR3: ',
type: 'line'
}],
regeneratePlots: function regeneratePlots(params) {
return params.map(function (_, i) {
return {
key: "wr".concat(i + 1),
title: "WR".concat(i + 1, ": "),
type: 'line'
};
});
},
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params,
plots = _ref.plots;
return dataList.map(function (kLineData, i) {
var wr = {};
var close = kLineData.close;
params.forEach(function (param, index) {
var p = param - 1;
if (i >= p) {
var hln = calcHnLn(dataList.slice(i - p, i + 1));
var hn = hln.hn;
var ln = hln.ln;
var hnSubLn = hn - ln;
wr[plots[index].key] = hnSubLn === 0 ? 0 : (close - hn) / hnSubLn * 100;
}
});
return wr;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 计算布林指标中的标准差
* @param dataList
* @param ma
* @return {number}
*/
function getBollMd(dataList, ma) {
var dataSize = dataList.length;
var sum = 0;
dataList.forEach(function (data) {
var closeMa = data.close - ma;
sum += closeMa * closeMa;
});
var b = sum > 0;
sum = Math.abs(sum);
var md = Math.sqrt(sum / dataSize);
return b ? md : -1 * md;
}
/**
* BOLL
*/
var bollingerBands = {
name: 'BOLL',
shortName: 'BOLL',
calcParams: [20, {
value: 2,
allowDecimal: true
}],
precision: 2,
shouldOhlc: true,
plots: [{
key: 'up',
title: 'UP: ',
type: 'line'
}, {
key: 'mid',
title: 'MID: ',
type: 'line'
}, {
key: 'dn',
title: 'DN: ',
type: 'line'
}],
calcTechnicalIndicator: function calcTechnicalIndicator(dataList, _ref) {
var params = _ref.params;
var p = params[0] - 1;
var closeSum = 0;
return dataList.map(function (kLineData, i) {
var close = kLineData.close;
var boll = {};
closeSum += close;
if (i >= p) {
boll.mid = closeSum / params[0];
var md = getBollMd(dataList.slice(i - p, i + 1), boll.mid);
boll.up = boll.mid + params[1] * md;
boll.dn = boll.mid - params[1] * md;
closeSum -= dataList[i - p].close;
}
return boll;
});
}
};
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var stopAndReverse = {
name: 'SAR',
shortName: 'SAR',
series: 'price',
calcParams: [2, 2, 20],
precision: 2,
shouldOhlc: true,
plots: [{
key: 'sar',
title: 'SAR: ',
type: 'circle',
color: function color(data, options) {
var current = data.current;
var kLineData = current.kLineData || {};
var technicalIndicatorData = current.technicalIndicatorData || {};
var halfHL = (kLineData.high + kLineData.low) / 2;
if (technicalIndicatorData.sar < halfHL) {
return optio