HighCharts dynamic high/low extreme markers - highcharts

I am wanting to display a marker on the highest and lowest point value in view along the y axis on a line series. I know how to add a marker manually but would like to add/remove them dynamically if a zoom/pan or anything else alters the visible high/low points is there a way to know this and the new high/low to add/remove the markers?
A previous SO question asked for similar advice with this mockup image: http://cl.ly/image/1f0m3l241e2S. The answer though is providing it with your data source, which wouldn't update via zoom/pan or streaming data.
I could potentially loop through the data source myself(2D Array), find the high/low and set them, doing the same on zoom/pan events if I can loop through only the zoomed section of the array. Though if I have dataGrouping set to true, the array of values I iterate over may not match up correctly?

You can do this by
1) using the getExtremes() method to get the high/low data points
2) using the afterSetExtremes() event to capture a zoom event and recalculate
A couple of potentially relevant posts:
Highcharts - Diagonal line X/Y axis
Highcharts moving average based on visible data only
You can set this up in a function, to loop through your data and look for a match to the high/low data points, and from them build a scatter series marking the high/low points on the chart.
An example that marks the points both on chart load and zoom:
http://jsfiddle.net/jlbriggs/475ax4eL/
function sample, gets the relevant x value at which to place the marker matching the high/low data point:
$.each(chart.series[0].data, function(i,point) {
if(point.y == maxData && point.x <= maxTime && point.x >= minTime) {
xMax = point.x;
}
if(point.y == minData && point.x <= maxTime && point.x >= minTime) {
console.log(point);
xMin = point.x;
}
});
{{UPDATE:
Important to note this issue:
https://github.com/highslide-software/highcharts.com/issues/985
If you are going to use column or area series, you will need to get the min and max from the series object instead of the getExtremes() method, because the chart internally sets the dataMin to 0 for those series types.
Easy enough to adapt the function accordingly.
And on a similar note, if you are going to use a boxplot, columnrange, or other similar series without an explicit y value, you will have to update accordingly as well.

Related

Highchart EMA, Price & MACD plot

I'm looking to produce a chart like this with data here
I'm trying to play with this chart on codepen
The attached data file has the following values -
1) Date
2) Open, High, Low, AdjustedClose - Plot Candlestick
3) Volume - Plot Volume
4) EMA1 & EMA2 - Plot moving averages on candlestick chart
5) macd_1, macds_1 & macdh_1 - Plot first set of MACD
6) macd_2, macds_2 & macdh_2 - Plot second set of MACD
7) macd_3, macds_3 & macdh_3 - Plot third set of MACD
The moving averages & MACD need not be calculated via javascript. It's already in the JSON data.
Need an export menu on the chart & smoothed plot of the EMA
There are 3 sets of MACD with macd, macds & macdh (histtogram) values all of which need to be on their own panels & have different positive & negative zone colours
The chart title needs to be of some colour centred at the top of chart. when we move mouseover the chart, the OHLC values & date need to be displayed
There is another field in the data called "Entry_type". When the value is "B" (Buy) a green balloon needs to be displayed below the candle & when it is "S" (Sell), a red colour needs to be display above the candle
All the plots need to be on movable panels (movable so to speak in HTML terms). The idea here is if needed then I would need to be able to keep say 2 MACD panels one below the other on left-hand side & move the third one to the right-hand side so that the actual price chart has good amount of vertical space on the page to show data clearly.
Need to set "groupData" to true, which means MACD, EMA & Volume will also need to adjust to that.
I am new to javascript charting which is making my life really hard to get all of this working. Could I please request some help to implement these features?
All you need to do is to prepare the correct data format for each series and create a separate y-axis for each pane. I have prepared a simple example with your data here:
for (i; i < dataLength; i += 1) {
date = new Date(data[i].Date).getTime();
ohlc.push([
date, // the date
data[i].Open, // open
data[i].High, // high
data[i].Low, // low
data[i].Close // close
]);
volume.push([
date, // the date
data[i].Volume // the volume
]);
if (data[i].ema_1) {
ema1.push([date, data[i].ema_1]);
}
}
Live demo: https://codesandbox.io/s/highcharts-react-d-zn9oj?file=/demo.jsx

Highcharts series.remove(false) doesn't update yAxis.datamax

I have a highcharts with multiple y axes. Each y axis has multiple series associated to it based on the measurement unit. For instance if we have 3 series with measurement unit "W", they will be associated to the same y Axis.
Users have the option to remove series at button click. Series are removed in the following way:
chart.series[channelIndex].remove(false);
After a series is removed we update the y axis limits as follows.
If a axis has series with no values, Y axis will have limits set to (0, 10). I add default limits in the following way:
// If there are no data in the series and if no limit was previously set we update the limits to (0, 10)
if (yAxis.dataMax == null && limits.max == null) {
limits.max = 10;
}
yAxis.update({
min: limits.min,
max: limits.max
}, false);
The problem is, that yAxis.datamax is not updated after a series is removed. So even if the yAxis has no series, dataMax and dataMin still have the same values before the series was removed.
I don't understand why y dataMin and dataMax are not updated after a series is removed . So any suggestions why this behavior is present would be very useful.
It's caused by disabling redraw:
chart.series[channelIndex].remove(false);
If you would replace false<=>redraw or just remove false it would work properly. Chart's redraw will recalculate datamin and datamax.

Marker with number in highcharts

I have a scatter plot where some of the values are so close to each other that only one marker is drawn. Is there a way to indicate that there a re more then one entry on this place. I'd like to add a number with items on this location.
You can catch datalabels.formatter and use loop on each series / and each point to check if any points has the same coordinates. Then sum it and return in the funcion.

How to shift data using Series.addPoint without shifting x axis values in highcharts

I have a working time history plot that removes one data point as another one is added after two minutes of data has accumulated. The trouble is that after say 10 minutes it is fairly difficult to see the duration of the data set being displayed (even using tickInterval). Is there a way to display fixed x axis labels after two minutes of data has accumulated? Specifically, I'm looking for truly fixed labels that do not scroll to the left with the data.
I tried using setCategories:
chart.xAxis[0].setCategories(cats, true);
Where cats is an array with sacrificial values prepended that will be removed during the shift, but the x axis labels still scroll left and I don't want that.
Thanks.
Edit:
I guess the way I previously described what I wanted to display on the x axis is not ideal. A better way to display this time (x) axis would be to have -120 on the far left and 0 on the far right. This would still require a non-scrolling x axis where the left most data point is over -120 and the right most data point is over 0.
If I'm following you, you want to shift off the start of the series, but leave the xAxis alone?
You can just set an xAxis min:
xAxis:{
min: 0
}
See example.
EDITS
In response to your comment. I think the easiest thing to do would be to shift the data yourself and then use setData to redraw the series.
newData = [];
var seriesData = chart.series[0].data;
// shift the data
for (var i = 0; i < (seriesData.length - 1); i++){
newData.push({x: seriesData[i].x, y: seriesData[i+1].y});
}
// new point for last
newData.push({x: seriesData[seriesData.length - 1].x,
y: Math.random() * 100});
chart.series[0].setData(newData, true);
Updated fiddle.

Highcharts doesn't display series with lots of data points

I have a chart that I would like to display based on a date range from the user. This particular chart has a data point for every 15 minutes. So there can be a lot of data points for each series if a users selects a large date range. Here is a couple of examples:
623 data points in a series
1470 data points in a series
In the first example the chart does display. In the second example the chart does not display. There is a Highstock demo (52,000 points with data grouping) that works with a lot of data points. I have tried to change the above charts to a highstock chart and still have the same results.
What can I do to fix this?
This is due to the turbo threshold option:
"When a series contains a data array that is longer than this, only one
dimensional arrays of numbers, or two dimensional arrays with x and y
values are allowed. Also, only the first point is tested, and the rest
are assumed to be the same format. This saves expensive data checking
and indexing in long series."
It is set to 1000 points by default. Your chart is not rendering because each point in your series is an object and their number is greater than the threshold.
Here's a jfFiddle demonstrating your plot working with the threshold set to 2000.
Here's the modified section of code:
plotOptions: {
spline: {
turboThreshold: 2000,
...
Another solution would be to encode your series data in a 2-d array instead of having each point represented by and object with x-y properties.
a workaround for turboThreshhold is something like this if you generation your response with PHP:
if(count($responseObj) > 1000){
$modolo = round(count($responseObj) / 1000);
for($i = count($responseObj)-1; $i >= 0 ; $i--){
if(($i % $modolo) != 0){
unset ($responseObj[$i]);
}
}
$responseObj = array_merge($responseObj);
}

Resources