К сожалению, я не могу согласиться с вашим утверждением. Конечно, индикатор macd
наследует некоторые функции-прототипы и параметры по умолчанию от sma
, но функция getValues
(которая отвечает за вычисление значений) переопределяется новой, где значения рассчитываются так, как вы описано выше. Вот самая важная часть кода этой функции:
getValues: function (series, params) {
var j = 0,
MACD = [],
xMACD = [],
yMACD = [],
signalLine = [],
shortEMA,
longEMA,
i;
if (series.xData.length < params.longPeriod) {
return false;
}
// Calculating the short and long EMA used when calculating the MACD
shortEMA = EMA.prototype.getValues(series,
{
period: params.shortPeriod
}
);
longEMA = EMA.prototype.getValues(series,
{
period: params.longPeriod
}
);
shortEMA = shortEMA.values;
longEMA = longEMA.values;
// Subtract each Y value from the EMA's and create the new dataset
// (MACD)
for (i = 1; i <= shortEMA.length; i++) {
if (
defined(longEMA[i - 1]) &&
defined(longEMA[i - 1][1]) &&
defined(shortEMA[i + params.shortPeriod + 1]) &&
defined(shortEMA[i + params.shortPeriod + 1][0])
) {
MACD.push([
shortEMA[i + params.shortPeriod + 1][0],
0,
null,
shortEMA[i + params.shortPeriod + 1][1] -
longEMA[i - 1][1]
]);
}
}
// Set the Y and X data of the MACD. This is used in calculating the
// signal line.
for (i = 0; i < MACD.length; i++) {
xMACD.push(MACD[i][0]);
yMACD.push([0, null, MACD[i][3]]);
}
// Setting the signalline (Signal Line: X-day EMA of MACD line).
signalLine = EMA.prototype.getValues(
{
xData: xMACD,
yData: yMACD
},
{
period: params.signalPeriod,
index: 2
}
);
signalLine = signalLine.values;
// Setting the MACD Histogram. In comparison to the loop with pure
// MACD this loop uses MACD x value not xData.
for (i = 0; i < MACD.length; i++) {
if (MACD[i][0] >= signalLine[0][0]) { // detect the first point
MACD[i][2] = signalLine[j][1];
yMACD[i] = [0, signalLine[j][1], MACD[i][3]];
if (MACD[i][3] === null) {
MACD[i][1] = 0;
yMACD[i][0] = 0;
} else {
MACD[i][1] = (MACD[i][3] - signalLine[j][1]);
yMACD[i][0] = (MACD[i][3] - signalLine[j][1]);
}
j++;
}
}
return {
values: MACD,
xData: xMACD,
yData: yMACD
};
}
Вот ссылка, где вы можете увидеть весь код индикатора macd.src.js
:
https://code.highcharts.com/stock/indicators/macd.src.js
С уважением!
[EDIT]
После обсуждения в комментариях мы заметили, что EMA в настоящее время рассчитывается на основе значений open
из набора данных OHLC вместо значений close
, и это определенно ошибка. Я сообщил о новой проблеме в нашем репозитории GitHub здесь: https://github.com/highcharts/highcharts/issues/8951, чтобы вы могли следить за ходом ее исправления, но она должна быть исправлена в новой версии Highstock (v7).
Чтобы обойти это, вы можете просто переопределить функцию seriesTypes.macd.prototype.getValues
, чтобы она передавала index: 3
в параметрах при вычислении коротких и длинных EMA
.
Вот код, который нужно применить перед инициализацией любых диаграмм:
(function(H) {
var EMA = H.seriesTypes.ema,
defined = H.defined;
H.seriesTypes.macd.prototype.getValues = function(series, params) {
var j = 0,
MACD = [],
xMACD = [],
yMACD = [],
signalLine = [],
shortEMA,
longEMA,
i;
if (series.xData.length < params.longPeriod) {
return false;
}
// Calculating the short and long EMA used when calculating the MACD
shortEMA = EMA.prototype.getValues(series, {
period: params.shortPeriod,
index: 3
});
longEMA = EMA.prototype.getValues(series, {
period: params.longPeriod,
index: 3
});
shortEMA = shortEMA.values;
longEMA = longEMA.values;
// Subtract each Y value from the EMA's and create the new dataset
// (MACD)
for (i = 1; i <= shortEMA.length; i++) {
if (
defined(longEMA[i - 1]) &&
defined(longEMA[i - 1][1]) &&
defined(shortEMA[i + params.shortPeriod + 1]) &&
defined(shortEMA[i + params.shortPeriod + 1][0])
) {
MACD.push([
shortEMA[i + params.shortPeriod + 1][0],
0,
null,
shortEMA[i + params.shortPeriod + 1][1] -
longEMA[i - 1][1]
]);
}
}
// Set the Y and X data of the MACD. This is used in calculating the
// signal line.
for (i = 0; i < MACD.length; i++) {
xMACD.push(MACD[i][0]);
yMACD.push([0, null, MACD[i][3]]);
}
// Setting the signalline (Signal Line: X-day EMA of MACD line).
signalLine = EMA.prototype.getValues({
xData: xMACD,
yData: yMACD
}, {
period: params.signalPeriod,
index: 2
});
signalLine = signalLine.values;
// Setting the MACD Histogram. In comparison to the loop with pure
// MACD this loop uses MACD x value not xData.
for (i = 0; i < MACD.length; i++) {
if (MACD[i][0] >= signalLine[0][0]) { // detect the first point
MACD[i][2] = signalLine[j][1];
yMACD[i] = [0, signalLine[j][1], MACD[i][3]];
if (MACD[i][3] === null) {
MACD[i][1] = 0;
yMACD[i][0] = 0;
} else {
MACD[i][1] = (MACD[i][3] - signalLine[j][1]);
yMACD[i][0] = (MACD[i][3] - signalLine[j][1]);
}
j++;
}
}
return {
values: MACD,
xData: xMACD,
yData: yMACD
};
}
})(Highcharts)
Живой пример: http://jsfiddle.net/aL1bqn2f/