major697
major697

Reputation: 1862

Highcharts return undefined value at a lot of data

I write code to return value in chart. I get data from cryptocompare.com (example JSON: link) It's code to use Highcharts:

$.getJSON("<?php echo $chartURL; ?>", function (data) {

    var seriesData = [];
    for (i=0; i<data.length; i++) {
      seriesData.push({
          x: data[i].time,
          y: data[i].open,
          high: data[i].high,
          low: data[i].low,
          close: data[i].close,
          volumeto: data[i].volumeto
      });
    }

    // Create the chart
    Highcharts.stockChart('container', {

        rangeSelector: {
          buttons: [
          {
            type: 'day',
            count: 1,
            text: '1d'
          }, {
            type: 'month',
            count: 1,
            text: '1m'
          }, {
            type: 'month',
            count: 6,
            text: '6m'
          }, {
            type: 'ytd',
            text: 'YTD'
          }, {
            type: 'year',
            count: 1,
            text: '1y'
          }, {
            type: 'all',
            text: 'All'
          }],
            selected: 0
        },

        title: {
            text: 'Chart'
        },
        tooltip:{
            formatter: function() {
                var point = this.points[0].point,
                    txt = '';

                // workaround display bug.
                var emptyline = '<span style="visibility: hidden;">-</span><br/>';
                txt += '<span style="font-size: 10px"><b>' + Highcharts.dateFormat('%A, %e %B %Y', point.x) + '</b></span><br/>\n';
                txt += emptyline;

                  console.log(point.close);
                  // console.log(points);
                  // console.log(point.point.options/1000);

                  var curr = 'USD';
                  txt +=  "<b>Price</b>: " + point.y + " " + curr +'<br/>';
              txt +=  "<b>Price</b>: " + point.y + " " + curr +'<br/>';
              txt +=  "<b>Close</b>: " + point.close + " " + curr +'<br/>';
              txt +=  "<b>High</b>: " + point.high + " " + curr +'<br/>';
              txt +=  "<b>Low</b>: " + point.low + " " + curr +'<br/>';
              txt +=  "<b>Volume</b>: " + point.volumeto + " " + curr +'<br/>';


                return txt;
            }
        },

        series: [{
              type: 'spline',
              name: 'Coin',
              data: seriesData,
              lineWidth: 2,
              pointInterval: 3 * 24 * 3600 * 1000, // three day
              marker: {
                  enabled: null, 
                  fillColor: "lightblue",
                  lineColor: "darkblue",
                  lineWidth: 1,
                  radius: 4
        },
        turboThreshold: 0
        }]
    });
});

I don't know why, but when I change range to All then values: high, low, close, volumeto are undefined. I don't have empty value in JSON. With a small amount of data, all values are displayed correctly I do not know what I'm doing wrong, that the value is returning undefined.

Here is my code: Jsfiddle

Upvotes: 0

Views: 604

Answers (2)

SpiderCode
SpiderCode

Reputation: 10122

Agree with @morganfree.

Alternate way is to use series.userOptions.data and filter out based on x value as shown below:

var currData = point.series.userOptions.data.filter(d => d.x == this.x)[0];

var curr = 'USD';
txt +=  "<b>Price</b>: " + point.y + " " + curr +'<br/>';
txt +=  "<b>Close</b>: " + currData.close + " " + curr +'<br/>';
txt +=  "<b>High</b>: " + currData.high + " " + curr +'<br/>';
txt +=  "<b>Low</b>: " + currData.low + " " + curr +'<br/>';
txt +=  "<b>Volume</b>: " + currData.volumeto + " " + curr +'<br/>';

Here is the JSFiddle

Upvotes: 1

morganfree
morganfree

Reputation: 12472

Highstock uses data grouping feature. When the data is grouped, in the formatter you do not have access to regular points but grouped points which values are trimmed and aggregated.

If the points are grouped, they have dataGroup property which holds the information useful for obtaining raw data.

In the formatter you can do something like this:

formatter: function() {
  const series = this.points[0].series
  let point = this.points[0].point

  if (series.hasGroupedData) {
    const { start, length } = point.dataGroup
    const { cropStart } = series

    const points = series.options.data.slice(start + cropStart, start + cropStart + length)
    const groupedPoint = points.reduce((prev, curr) => ({
      high: Math.max(prev.high, curr.high),
      low: Math.min(prev.low, curr.low),
      volumeto: prev.volumeto + curr.volumeto
    }))

    groupedPoint.x = point.x
    groupedPoint.y = point.y
    groupedPoint.close = points[points.length - 1].close

    point = groupedPoint
  }

  ...

live example: https://jsfiddle.net/qhhusb6f/

Upvotes: 2

Related Questions