MrZiggyStardust
MrZiggyStardust

Reputation: 733

Highstock compare previous data point when date does not exist in series

I am using highstock to show fund data in a line graph, the data series I am using is missing dates (weekends mostly). I have no control over the source code of the data series, though I have formatted it by looping through it in JS so it can be used with Highstock. The problem occurs when I use the rangeSelector on missing dates, when I choose From in the range selector to a weekend date (a date that is missing in the data series) the compare percentage starts calculating from the next available data point.

Example

  1. Go to this demo: http://www.highcharts.com/stock/demo/compare
  2. Choose 14 dec, 2014 as the From date.

The calculation starts from 2014-12-15 as the 0 value, which is a monday. I want it to always start the compare percentage at the previous data point, not the next. I would want it to start from 2014-12-12 which is a friday.

How I initiate highstocks in JS:

var opts = {
    chart : {
        backgroundColor: '#f9f9fa',
        borderWidth: 0,
        type: 'line'
    },
    rangeSelector : {
        buttons: [{
            type: 'month',
            count: 3,
            text: '3m'
        }, {
            type: 'month',
            count: 6,
            text: '6m'
        }, {
            type: 'ytd',
            text: 'YTD'
        }, {
            type: 'year',
            count: 1,
            text: '1y'
        }, {
            type: 'all',
            text: 'All'
        }],
        selected : 3,
        inputEnabled: false
    },

    plotOptions: {
        series: {
            compare: 'percent'
        }
    },

    title : {
        text : ''
    },

    navigator : {
        enabled : false
    },

    credits: {
        enabled: false
    },

    series : [{
        name : '',
        data : seriesData,
        lineColor : '#002855',
        tooltip: {
            valueDecimals: 4
        },
        turboThreshold : 0
    }],

    xAxis : {
        dateTimeLabelFormats: {
            millisecond: '%H:%M:%S.%L',
            second: '%H:%M:%S',
            minute: '%H:%M',
            hour: '%H:%M',
            day: '%e %b.',
            week: '%b %y',
            month: '%b %y',
            year: '%Y'
        },
        ordinal: false,
        minTickInterval : 4 * 7 * 24 * 3600 * 1000
    },

    yAxis : {
        labels: {
            format: '{value} %'
        }
    },

    tooltip : {
        valueSuffix : '',
        pointFormat : '<span style="color:{point.color}">\u25CF</span> {point.y} SEK ({point.change}%)<br/>'
    }
};

$(el).highcharts('StockChart', opts);

My seriesData var looks like this after I have formatted it for use in Highstock:

[ 
    { name="2005-01-03", x=1104710400000, y=100 },
    { name="2005-01-04", x=1104796800000, y=99.9983 },
    { name="2005-01-05", x=1104883200000, y=99.9175014 },
    { name="2005-01-07", x=1105056000000, y=100.0739722 },
    // This continues to the current date
]

x is a timestamp.
y is the stock value
name is a string representing the timestamp in x

el is defined before, and is a element node object.

Is it possible to make the compare start at the previous available data point and not the next when a date in the data series does not exist?

Any help regarding this issue will be appreciated!

Edit: Added my solution as an answer below

Upvotes: 0

Views: 635

Answers (1)

MrZiggyStardust
MrZiggyStardust

Reputation: 733

I found afterSetExtremes very useful to modify min and max, I check if the date is a saturday or sunday. If its a saturday I go -1 day back in time, if its a sunday I go -2 days back in time. This should cover all normal weekends for me, and it works quite good. Though it wont cover holidays that occur on weekdays. I also do not modify the max time, though I might need to do that.

My current xAxis:

xAxis : {
    events: {
        afterSetExtremes: function(e){

            var maxTimestamp = this.max,
                minTimestamp = this.min;

            var dateMin = new Date( minTimestamp ),
                dateMax = new Date( maxTimestamp ),
                minDayOfTheWeek = dateMin.getDay();

            // Test to see if its saturday or sunday
            if( minDayOfTheWeek === 6 || minDayOfTheWeek === 0 ){

                if( minDayOfTheWeek === 6 ){
                    dateMin.setDate( dateMin.getDate() - 1 );
                }else if( minDayOfTheWeek === 0 ){
                    dateMin.setDate( dateMin.getDate() - 2 );
                }

                this.setExtremes( dateMin.getTime(), dateMax.getTime() );
            }

        }
    },
    dateTimeLabelFormats: {
        millisecond: '%H:%M:%S.%L',
        second: '%H:%M:%S',
        minute: '%H:%M',
        hour: '%H:%M',
        day: '%e %b.',
        week: '%b %y',
        month: '%b %y',
        year: '%Y'
    },
    ordinal: false,
    minTickInterval : 4 * 7 * 24 * 3600 * 1000
}

And added this to the chart cause afterSetExtremes do not run on load for me:

chart : {
    backgroundColor: '#f9f9fa',
    borderWidth: 0,
    events:{
        load: function(){
            var max = this.xAxis[0].max,
                min = this.xAxis[0].min;

            this.xAxis[0].setExtremes( min, max );
        }
    },
    type: 'line'
}

Upvotes: 1

Related Questions