Highcharts.js问题:是否可以不绘制超出MACD指标直方图的线?

时间:2018-12-20 17:00:12

标签: highcharts indicator

我使用Highstock.js库开发一个项目。我要求不要绘制超出MACD指标直方图(https://prnt.sc/lxjoit)的线。在与MACD指示器有关的Highstock.js文档中,有macdLine API:https://api.highcharts.com/highstock/series.macd.macdLine和signalLine API:https://api.highcharts.com/highstock/series.macd.signalLine.zones。这些API仅允许为MACD指示器部件设置颜色(以y轴除)。因此不适合。从文档中还不清楚我们是否不能在直方图之外绘制MACD指标线。您知道是否有可能实现该目标以及如何实现?请告知。

这是JSFiddle中的实时演示,其中显示带有MACD指示器的图表:http://jsfiddle.net/ogorobets/x3tcpq72/14/

var ohlc = JSON.parse(ohlcStringified),
    volume = JSON.parse(volumeStringified);
var wvapSerieData = [];    
var lastDayDate = new Date("December 6, 2018 00:00:00");
var lastDayDateTs = lastDayDate.getTime();

Highcharts.stockChart('container', {
    chart: {
        borderWidth: 1
    },
    title: {
        text: 'Volume Weighted Average Price (VWAP)'
    },
    legend: {
        enabled: true
    },
    yAxis: [{
        height: '30%'
    }, {
        top: '30%',
        height: '35%',
        offset: 0
    }, {
        top: '65%',
        height: '35%',
        offset: 0
    }],
    series: [{
        type: 'candlestick',
        id: 'candlestick',
        name: 'AAPL',
        data: ohlc,
        tooltip: {
            valueDecimals: 2
        }
    }, {
        type: 'column',
        id: 'volume',
        name: 'Volume',
        data: volume,
        yAxis: 1
    }, 
    {
        type: 'macd',
        color: '#f05f5f',
        linkedTo: 'candlestick',
        showInLegend: true,
        enableMouseTracking: true,
        dataGrouping: {
            enabled: false,
        },
        zones:[
            {
                value: 0,
                color: '#f05f5f',
            },
            {
                color: '#31c26d'
            }
        ],
        yAxis: 2
    }]
});

1 个答案:

答案 0 :(得分:1)

不幸的是,MACD指标并未设计成不会在直方图之外绘制MACD指标线。

但是,您可以覆盖用于计算MACD值的方法,并删除直方图之外的第一个值。查看我在下面发布给您的代码和演示。

添加到H.seriesTypes.macd.prototype.getValues方法中的行:

// params.signalPeriod - 1 - amount of points beyond the histroram
MACD.splice(0, params.signalPeriod - 1);
xMACD.splice(0, params.signalPeriod - 1);
yMACD.splice(0, params.signalPeriod - 1);

整个包装代码:

(function(H) {
  H.seriesTypes.macd.prototype.getValues = function(series, params) {
    var j = 0,
        EMA = H.seriesTypes.ema,
      merge = H.merge,
        defined = H.defined,
      correctFloat = H.correctFloat,
      MACD = [],
      xMACD = [],
      yMACD = [],
      signalLine = [],
      shortEMA,
      longEMA,
      i;

    if (series.xData.length < params.longPeriod + params.signalPeriod) {
      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] = correctFloat(MACD[i][3] -
            signalLine[j][1]);
          yMACD[i][0] = correctFloat(MACD[i][3] -
            signalLine[j][1]);
        }

        j++;
      }
    }

    MACD.splice(0, params.signalPeriod - 1);
    xMACD.splice(0, params.signalPeriod - 1);
    yMACD.splice(0, params.signalPeriod - 1);

    return {
      values: MACD,
      xData: xMACD,
      yData: yMACD
    };
  }
})(Highcharts);

演示:
http://jsfiddle.net/1f2m0yz4/

文档:
https://www.highcharts.com/docs/extending-highcharts/extending-highcharts