Reputation: 1820
I have a candlestick and volume chart similar to here, but with custom colors for the volume bars and candlesticks. This works fine until the graph is redrawn or grouped due to new data being added or a range selector button press. When the graph is redrawn or grouped, neither the candle color nor the volume bar color seems to be transferring properly. I'm using the following redraw function, but it does not seem to be having any effect. Strangely, each time the data is grouped in a new data grouping, the volume bars will display the correct color when you hover over them, and will stay the correct color until the graph is redrawn. Here is the fiddle showing this condition. My redraw function is below.
EDIT: If the fiddle is giving a 500 error, try here
Is there any way to fix this or get it so I can draw the colors correctly?
const redraw = (event) => {
const chartTarget = event.target;
if (chartTarget.series[0].hasGroupedData) {
// Get all the candlesticks that are shown
const candlesticks = chartTarget.series[0].points;
// Get all the volume bards that are shown
const volumeBars = chartTarget.series[1].points;
// Go through the candle chart and volume points and update the colors
for (let i = 0; i < candlesticks.length; i++) {
const candle = candlesticks[i];
const volumeBar = volumeBars[i];
if (candle.close > candle.open) {
const color = 'green';
volumeBar.color = color;
candle.color = color;
} else if (candle.close < candle.open) {
const color = 'red';
candle.color = color;
volumeBar.color = color;
}
}
}
};
Upvotes: 0
Views: 833
Reputation: 5826
Everything seems to work fine if you use the solution from this post: Highcharts update grouped data point color
const color = 'green';
volumeBar.graphic.css({
color: color
});
candle.graphic.css({
color: color
});
Live demo: http://jsfiddle.net/BlackLabel/w7nv82r2/
Upvotes: 0
Reputation: 216
I've been banging my head on the same problem all weekend. I'm not at all a highcharts expert, but here's what I came up with. It was inspired by this question and this question.
The relevant portion of the fiddle is:
Highcharts.stockChart('container', {
chart: {
events: {
load: function(event) {
// Get the volume series by id.
var volSeries = this.series.find(function(s) {
return s.userOptions.id === 'volume';
});
// Override the pointAttribs function on the volume series.
volSeries.pointAttribs = (function(original) {
return function(point, state) {
// Call the original pointAttribs function.
var attribs = original.apply(this, arguments);
// Get the price series using the id.
var priceSeries = point.series.chart.series.find(function(s) {
return s.userOptions.id === 'price';
});
// Find the candle corresponding to the current volume point.
var candle;
if (point.series.hasGroupedData) {
// With grouped data, we need to find the candle from the grouped data.
var datagroup = point.dataGroup;
var groupIdx = point.series.groupMap.indexOf(datagroup);
candle = priceSeries.groupedData[groupIdx];
} else {
// Non-grouped data, we can just use the normal data.
candle = priceSeries.data[point.index];
}
// Choose the color for the volume point based on the candle properties.
var color = 'blue';
if (candle.close > candle.open) {
color = 'green';
} else if (candle.close < candle.open) {
color = 'red';
}
// Set the volume point's attribute(s) accordingly.
attribs.fill = color;
// Return the updated attributes.
return attribs;
};
})(volSeries.pointAttribs);
// Need to call update so the changes get taken into account on first draw.
this.update({});
}
}
},
...
Basically, we override the pointAttribs function on the volume series so that we can do the color calculation. The pointAttribs function is an internal function, so use at your own risk.
Performance wise, this shouldn't be too expensive - for non-grouped data it's using pre-existing indexes; for grouped data it has to use indexOf on the series.groupMap to get the index.
The volume series colors are set with standard candlestick options - "color" and "upColor", there's also "lineColor" and "upLineColor" options available.
Upvotes: 2