I have a problem in javascript with building financial candlestick charts. I made a chart with apex.js and it displays the correct data where it should be but the color of the chart doesn't change, when the stock price is going up candlestick should be green when it goes down it should be red but on some stocks candlestick in always red and on some stocks it works fine. Here are the images, both charts use the same code but different data because it's different stock but that doesn't mean it should be displayed like this.
Here is code for chart:
<div id="chart">
</div>
<script>
var options = {
series: [{
name: 'OHLC',
data: [
{% for stock in stocks %}
{
x: new Date("{{stock.date}}"),
y: [Number("{{stock.open}}"), Number("{{stock.high}}"), Number("{{stock.low}}"), Number("{{stock.price}}")],
},
{% endfor %}
]
},
],
chart: {
type: 'candlestick',
},
title: {
text: '{{ticker}} Stock ',
align: 'center'
},
yaxis: {
tooltip: {
enabled: true
}
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
</script>
I am using Django in the backend so here is a function that returns chart data:
#login_required(login_url='stock:login')
def chart(request, ticker):
stocks = Stock.objects.filter(ticker = ticker).order_by('date')
context = {'stocks':stocks, 'ticker':ticker}
return render(request, 'stock_app/chart.html', context)
I am struggling with this for a few days and didn't even make slight progress, can anyone help me or at least tell me where the issue could be I would be really thankful. I check the database, data, and code, switched a few services, and used chart.js, plotly, and a few others and it's always the same issue. I also checked data on yahoo finance for stocks that are not displayed correctly and data is correct.
Usually, when you replace libraries and the issue prevails, the problem cannot be the library; instead the provided data might contain wrong information that lead to an indifferent resolution on your chart.
I see that you don't specify the candlestick colors specifically inside the specification, so this might be worth a shot, albeit its probably only basis configuration:
plotOptions: {
candlestick: {
colors: {
upward: '#3C90EB',
downward: '#DF7D46'
}
}
}
https://apexcharts.com/docs/chart-types/candlestick/
However, if the problem is the data itself you should rather provide an excerpt of a faulty stock and also one where it works just fine. Without stepping too deeply into Apex, maybe High/Low or Opening/Closing is mixed or wrong.
It is hard to say what is going on without your dataset. However, I suspect a lack of configuration of your xaxis, especially because your time scale does not seem consistent. Could you put this in your options and see what happens?
xaxis: {
type: 'datetime'
},
You can also have a category axis with a candlestick chart, but you may need extra configuration (a formatter, for example...). See this official demo: Category x-axis – ApexCharts.js
I paste the example below for convenience.
var options = {
series: [{
name: 'candle',
data: [
{
x: new Date(1538778600000),
y: [6629.81, 6650.5, 6623.04, 6633.33]
},
{
x: new Date(1538780400000),
y: [6632.01, 6643.59, 6620, 6630.11]
},
{
x: new Date(1538782200000),
y: [6630.71, 6648.95, 6623.34, 6635.65]
},
{
x: new Date(1538784000000),
y: [6635.65, 6651, 6629.67, 6638.24]
},
{
x: new Date(1538785800000),
y: [6638.24, 6640, 6620, 6624.47]
},
{
x: new Date(1538787600000),
y: [6624.53, 6636.03, 6621.68, 6624.31]
},
{
x: new Date(1538789400000),
y: [6624.61, 6632.2, 6617, 6626.02]
},
{
x: new Date(1538791200000),
y: [6627, 6627.62, 6584.22, 6603.02]
},
{
x: new Date(1538793000000),
y: [6605, 6608.03, 6598.95, 6604.01]
},
{
x: new Date(1538794800000),
y: [6604.5, 6614.4, 6602.26, 6608.02]
},
{
x: new Date(1538796600000),
y: [6608.02, 6610.68, 6601.99, 6608.91]
},
{
x: new Date(1538798400000),
y: [6608.91, 6618.99, 6608.01, 6612]
},
{
x: new Date(1538800200000),
y: [6612, 6615.13, 6605.09, 6612]
},
{
x: new Date(1538802000000),
y: [6612, 6624.12, 6608.43, 6622.95]
},
{
x: new Date(1538803800000),
y: [6623.91, 6623.91, 6615, 6615.67]
},
{
x: new Date(1538805600000),
y: [6618.69, 6618.74, 6610, 6610.4]
},
{
x: new Date(1538807400000),
y: [6611, 6622.78, 6610.4, 6614.9]
},
{
x: new Date(1538809200000),
y: [6614.9, 6626.2, 6613.33, 6623.45]
},
{
x: new Date(1538811000000),
y: [6623.48, 6627, 6618.38, 6620.35]
},
{
x: new Date(1538812800000),
y: [6619.43, 6620.35, 6610.05, 6615.53]
},
{
x: new Date(1538814600000),
y: [6615.53, 6617.93, 6610, 6615.19]
},
{
x: new Date(1538816400000),
y: [6615.19, 6621.6, 6608.2, 6620]
},
{
x: new Date(1538818200000),
y: [6619.54, 6625.17, 6614.15, 6620]
},
{
x: new Date(1538820000000),
y: [6620.33, 6634.15, 6617.24, 6624.61]
},
{
x: new Date(1538821800000),
y: [6625.95, 6626, 6611.66, 6617.58]
},
{
x: new Date(1538823600000),
y: [6619, 6625.97, 6595.27, 6598.86]
},
{
x: new Date(1538825400000),
y: [6598.86, 6598.88, 6570, 6587.16]
},
{
x: new Date(1538827200000),
y: [6588.86, 6600, 6580, 6593.4]
},
{
x: new Date(1538829000000),
y: [6593.99, 6598.89, 6585, 6587.81]
},
{
x: new Date(1538830800000),
y: [6587.81, 6592.73, 6567.14, 6578]
},
{
x: new Date(1538832600000),
y: [6578.35, 6581.72, 6567.39, 6579]
},
{
x: new Date(1538834400000),
y: [6579.38, 6580.92, 6566.77, 6575.96]
},
{
x: new Date(1538836200000),
y: [6575.96, 6589, 6571.77, 6588.92]
},
{
x: new Date(1538838000000),
y: [6588.92, 6594, 6577.55, 6589.22]
},
{
x: new Date(1538839800000),
y: [6589.3, 6598.89, 6589.1, 6596.08]
},
{
x: new Date(1538841600000),
y: [6597.5, 6600, 6588.39, 6596.25]
},
{
x: new Date(1538843400000),
y: [6598.03, 6600, 6588.73, 6595.97]
},
{
x: new Date(1538845200000),
y: [6595.97, 6602.01, 6588.17, 6602]
},
{
x: new Date(1538847000000),
y: [6602, 6607, 6596.51, 6599.95]
},
{
x: new Date(1538848800000),
y: [6600.63, 6601.21, 6590.39, 6591.02]
},
{
x: new Date(1538850600000),
y: [6591.02, 6603.08, 6591, 6591]
},
{
x: new Date(1538852400000),
y: [6591, 6601.32, 6585, 6592]
},
{
x: new Date(1538854200000),
y: [6593.13, 6596.01, 6590, 6593.34]
},
{
x: new Date(1538856000000),
y: [6593.34, 6604.76, 6582.63, 6593.86]
},
{
x: new Date(1538857800000),
y: [6593.86, 6604.28, 6586.57, 6600.01]
},
{
x: new Date(1538859600000),
y: [6601.81, 6603.21, 6592.78, 6596.25]
},
{
x: new Date(1538861400000),
y: [6596.25, 6604.2, 6590, 6602.99]
},
{
x: new Date(1538863200000),
y: [6602.99, 6606, 6584.99, 6587.81]
},
{
x: new Date(1538865000000),
y: [6587.81, 6595, 6583.27, 6591.96]
},
{
x: new Date(1538866800000),
y: [6591.97, 6596.07, 6585, 6588.39]
},
{
x: new Date(1538868600000),
y: [6587.6, 6598.21, 6587.6, 6594.27]
},
{
x: new Date(1538870400000),
y: [6596.44, 6601, 6590, 6596.55]
},
{
x: new Date(1538872200000),
y: [6598.91, 6605, 6596.61, 6600.02]
},
{
x: new Date(1538874000000),
y: [6600.55, 6605, 6589.14, 6593.01]
},
{
x: new Date(1538875800000),
y: [6593.15, 6605, 6592, 6603.06]
},
{
x: new Date(1538877600000),
y: [6603.07, 6604.5, 6599.09, 6603.89]
},
{
x: new Date(1538879400000),
y: [6604.44, 6604.44, 6600, 6603.5]
},
{
x: new Date(1538881200000),
y: [6603.5, 6603.99, 6597.5, 6603.86]
},
{
x: new Date(1538883000000),
y: [6603.85, 6605, 6600, 6604.07]
},
{
x: new Date(1538884800000),
y: [6604.98, 6606, 6604.07, 6606]
},
]
}],
chart: {
height: 350,
type: 'candlestick',
},
title: {
text: 'CandleStick Chart - Category X-axis',
align: 'left'
},
annotations: {
xaxis: [
{
x: 'Oct 06 14:00',
borderColor: '#00E396',
label: {
borderColor: '#00E396',
style: {
fontSize: '12px',
color: '#fff',
background: '#00E396'
},
orientation: 'horizontal',
offsetY: 7,
text: 'Annotation Test'
}
}
]
},
tooltip: {
enabled: true,
},
xaxis: {
type: 'category',
labels: {
formatter: function(val) {
return dayjs(val).format('MMM DD HH:mm')
}
}
},
yaxis: {
tooltip: {
enabled: true
}
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs#1.11.7/dayjs.min.js"></script>
<div id="chart"></div>
Thanks to everyone who tried to help I found out what was the problem. The close price was misconfigured by the API provider so the close price was higher by a few cents than the low price which caused the error
I am trying to force highcharts to show last label on x-axis when "step" is enabled. Code below works but it hides last label when I change device width (let's say open chrome console). Problem arises on mobile devices when I scroll down after the chart, last label disappears.
chart:
{
renderTo: "container",
type: "line",
events:{
load:function(){
var ticks = $.map(this.axes[0].ticks, function(t){return t;});
ticks[ticks.length-2].render(0);
}
}
}
First of all the last label 2020 is appearing because of your logic in load event. Ideally that label shouldn't be appearing because your step value is 3. Anyways, you need to add the same logic of load in redraw event to get the last label on resize.
const df = [
{ Period: 2009, value: 1056043 },
{ Period: 2010, value: 1278495 },
{ Period: 2011, value: 1482508 },
{ Period: 2012, value: 1545703 },
{ Period: 2013, value: 1579593 },
{ Period: 2014, value: 1620531.9 },
{ Period: 2015, value: 1502572.2 },
{ Period: 2016, value: 1451010.7 },
{ Period: 2017, value: 1546273 },
{ Period: 2018, value: 1663982.3 },
{ Period: 2019, value: 1643160.9 },
{ Period: 2020, value: 1431638.4 }
];
var chart = new Highcharts.Chart({
chart: {
renderTo: "container",
height: 300,
type: "areaspline",
events: {
load: function () {
var ticks = $.map(this.axes[0].ticks, function (t) {
return t;
});
ticks[ticks.length - 2].render(0);
},
redraw: function () {
var ticks = $.map(this.axes[0].ticks, function (t) {
return t;
});
ticks[ticks.length - 2].render(0);
}
}
},
title: {
text: "Emissions of CO2 - from Fossil Fuels - Total (CDIAC)"
},
xAxis: {
categories: df.map((o) => o.Period),
labels: {
step: 3,
style: {
fontFamily: "Arial, Helvetica, sans-serif;",
fontSize: "0.8rem",
fontWeight: "600",
background: "#000000",
whiteSpace: "nowrap",
textOverflow: "none"
}
},
showLastLabel: true,
endOnTick: true,
overflow: "allow"
},
yAxis: {
min: 0
},
series: [
{
data: df.map((o) => o.value),
name: "Germany"
}
]
});
https://jsfiddle.net/7zL0v5oq/
I would like to have a plotline at today's date. The list can get quite long and in that case it helps with having an oversight. I fear it doesn't work because it is a scatter chart but I don't know what the problem is. I've searched all over the place but everything leads to plotlines, which clearly doesn't work. I would also be thankful if anyone knew, whether there was an easy way to filter my data the way I have it (standard highcharts filtering is deactivated but doesn't really help because of the static y values, so I get a huge, white space in the middle unless I filter at the edges. Thank you in advance for your help.
data = [{
"id": 1,
"release": "Software1",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2014-04-01",
"sale_ended_on": "2013-04-01",
"security_vul_support_ended_on": "2015-04-01",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2018-03-31",
"updated_dates_on": "2012-10-03",
"created_at": "2018-05-04T18:53:21.301+02:00",
"updated_at": "2018-05-16T08:36:24.940+02:00"
},
{
"id": 2,
"release": "Software2",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2019-07-24",
"sale_ended_on": "2017-07-31",
"security_vul_support_ended_on": "2020-07-24",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2022-07-31",
"updated_dates_on": "2015-08-14",
"created_at": "2018-05-05T04:00:44.170+02:00",
"updated_at": "2018-05-16T08:36:29.325+02:00"
},
{
"id": 3,
"release": "Software3",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2018-03-01",
"sale_ended_on": "2017-03-01",
"security_vul_support_ended_on": "2018-12-01",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2022-02-28",
"updated_dates_on": "2016-09-02",
"created_at": "2018-05-05T04:00:44.401+02:00",
"updated_at": "2018-05-16T08:36:31.643+02:00"
}
];
const colors = ["#516", "#1781e3", "#25b252", "#20c997", "#ffc107", "#ff8b2e", "#dd1122"];
//Change to store y value paired to release/pid
var change = {};
//Which y values need to be displayed
var ticks = [0];
//Description of events
var sale = "Sale";
var support = "Support";
var svc = " SVC attach";
var sw = "Software maintenance";
var routine = "Routine failure analysis";
var service = "Service contract renewal";
var security = "Security vulnerability support";
//Data array for series
var high = [];
data.sort(function(a, b) {
return Date.parse(a.support_ended_on) < Date.parse(b.support_ended_on) ? 1 : -1
})
for (var i = 0; i < data.length; i++) {
var arr = [{
x: Date.parse(data[i].sale_ended_on),
y: (i + 1) * 20,
color: colors[0],
myValue: sale
},
{
x: Date.parse(data[i].sw_maintenance_releases_ended_on),
y: (i + 1) * 20,
color: colors[1],
myValue: sw
},
{
x: Date.parse(data[i].security_vul_support_ended_on),
y: (i + 1) * 20,
color: colors[2],
myValue: security
},
{
x: Date.parse(data[i].svc_attach_ended_on),
y: (i + 1) * 20,
color: colors[3],
myValue: svc
},
{
x: Date.parse(data[i].routine_failure_analysis_ended_on),
y: (i + 1) * 20,
color: colors[4],
myValue: routine
},
{
x: Date.parse(data[i].service_contract_renewal_ended_on),
y: (i + 1) * 20,
color: colors[5],
myValue: service
},
{
x: Date.parse(data[i].support_ended_on),
y: (i + 1) * 20,
color: colors[6],
myValue: support
}
];
var key, value;
line = [{
x: Date.parse(data[i].sale_ended_on),
y: (i + 1) * 20
}, {
x: Date.parse(data[i].support_ended_on),
y: (i + 1) * 20
}]
//Adding to change list, so we can add release/pid as label to y axis
key = (i + 1) * 20;
ticks.push(key);
if (data[i].pid) {
value = data[i].pid;
} else {
value = data[i].release;
}
change[key] = value;
//Expanding high (which is used for the highcharts series) with arr (all points for one pid)
if (data[i].pid) {
high.push({
label: data[i].pid,
name: data[i].pid,
type: 'scatter',
data: arr
}, {
type: 'line',
data: line,
linkedTo: ":previous"
});
} else {
high.push({
label: data[i].release,
name: data[i].release,
type: 'scatter',
data: arr,
showInLegend: false
}, {
type: 'line',
data: line,
linkedTo: ":previous"
});
}
}
Highcharts.chart("container", {
chart: {
height: data.length * 75
},
credits: {
enabled: false
},
yAxis: {
title: {
text: null
},
tickPositions: ticks,
visible: true,
labels: {
formatter: function() {
var value = change[this.value];
return value !== 'undefined' ? value : this.value;
}
}
},
xAxis: {
plotlines: [{
color: "#dd1122",
width: 2,
value: +new Date()
}],
type: 'datetime',
},
plotOptions: {
scatter: {
marker: {
symbol: 'circle',
radius: 7,
lineWidth: 2
}
},
line: {
enableMouseTracking: false,
marker: {
enabled: false
},
color: '#bbb',
lineWidth: 3
}
},
tooltip: {
formatter: function() {
var str = '<b>' + this.series.name + '</b><br/>'
if (this.point.myValue) {
str += this.point.myValue;
} else {
str += "Corrupted data!";
}
if (this.point.x < Date.parse(new Date))
return str += " ended on:<br/>" + Highcharts.dateFormat('%e %b %Y', new Date(this.x));
else
return str += " will end on:<br/>" + Highcharts.dateFormat('%e %b %Y', new Date(this.x));
},
shared: false
},
series: high
})
You have a typo, use plotLines instead of plotlines:
xAxis: {
plotLines: [{
...
}],
...
}
Live demo: https://jsfiddle.net/BlackLabel/p3u8ejtb/
API Reference: https://api.highcharts.com/highcharts/xAxis.plotLines