function renderChart(ticker, exchange, divId, useLogScale, title, ylevel) {
fetch(`https://api.friedrich.report/tv?ticker=${ticker}&exchange=${exchange}`)
.then(response => response.json())
.then(data => {
const timestamps = Object.keys(data.close);
const closePrices = Object.values(data.close);
const xAxisCategories = timestamps.map(ts => new Date(parseInt(ts)).toISOString());
// Calculate 31-day SMA
const sma31 = [];
for (let i = 0; i < closePrices.length; i++) {
if (i < 30) {
sma31.push(null); // Not enough data to calculate SMA
} else {
const sum = closePrices.slice(i - 30, i + 1).reduce((a, b) => a + b, 0);
sma31.push(sum / 31);
}
}
var options = {
chart: {
fontFamily: 'Outfit',
background: '#ffffff', // Set the background color to white
zoom: {
enabled: true,
type: 'x',
autoScaleYaxis: true,
events: {
zoomed: function(chartContext, { xaxis, yaxis }) {
const zoomMessage = document.createElement('div');
zoomMessage.innerText = 'Press ESC to leave zoom';
zoomMessage.style.position = 'absolute';
zoomMessage.style.top = '10px';
zoomMessage.style.left = '10px';
zoomMessage.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
zoomMessage.style.color = 'white';
zoomMessage.style.padding = '5px';
zoomMessage.style.borderRadius = '5px';
zoomMessage.style.zIndex = 1000;
document.querySelector(`#${divId}`).appendChild(zoomMessage);
setTimeout(() => {
document.querySelector(`#${divId}`).removeChild(zoomMessage);
}, 2000);
}
}
},
toolbar: {
show: true,
tools: {
download: true,
selection: true,
zoom: {
icon: '',
title: 'Zoom In',
click: function(chart, options, e) {
if (chart.zoomed) {
// Simulate ESC key press
var escEvent = new KeyboardEvent('keydown', { key: 'Escape' });
document.dispatchEvent(escEvent);
chart.zoomed = false;
} else {
chart.zoomed = true;
}
}
},
zoomin: true,
zoomout: true,
pan: true, // Enable pan tool
reset: true,
customIcons: [{
icon: '',
index: -1,
title: 'Fullscreen',
class: 'custom-icon',
click: function(chart, options, e) {
const chartElement = chart.el;
if (chartElement.requestFullscreen) {
chartElement.requestFullscreen({ navigationUI: "hide" });
} else if (chartElement.mozRequestFullScreen) { // Firefox
chartElement.mozRequestFullScreen({ navigationUI: "hide" });
} else if (chartElement.webkitRequestFullscreen) { // Chrome, Safari and Opera
chartElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (chartElement.msRequestFullscreen) { // IE/Edge
chartElement.msRequestFullscreen();
}
// Add exit fullscreen button
const exitFullscreenButton = document.createElement('button');
exitFullscreenButton.innerText = 'Exit Fullscreen';
exitFullscreenButton.style.position = 'absolute';
exitFullscreenButton.style.top = '10px';
exitFullscreenButton.style.right = '10px';
exitFullscreenButton.style.zIndex = 1001;
exitFullscreenButton.onclick = function() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) { // Firefox
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) { // Chrome, Safari and Opera
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) { // IE/Edge
document.msExitFullscreen();
}
};
document.querySelector(`#${divId}`).appendChild(exitFullscreenButton);
}
}]
},
autoSelected: 'pan' // Auto-select pan tool
},
width: "100%",
type: "line",
stacked: false,
pan: {
enabled: true, // Enable panning
mode: 'x', // Allow panning only on the x-axis
}
},
title: {
text: `${title}`,
align: 'center',
margin: 20,
style: {
fontSize: '16px',
fontWeight: 'bold',
color: '#0000af'
}
},
dataLabels: {
enabled: false
},
colors: ["#0000af", "#FFA500", "#FF4560"],
series: [{
name: "Close Prices",
data: closePrices.map((price, index) => ({ x: new Date(parseInt(timestamps[index])), y: price }))
}, {
name: "31-day SMA",
data: sma31.map((price, index) => ({ x: new Date(parseInt(timestamps[index])), y: price }))
}],
stroke: {
curve: 'smooth',
width: [2, 2]
},
markers: {
size: 0 // Disable markers for better performance
},
fill: {
type: 'gradient',
gradient: {
type: "vertical"
}
},
xaxis: {
type: 'datetime'
},
yaxis: [{
opposite: true,
axisTicks: {
show: true
},
axisBorder: {
show: false,
color: "#0000af"
},
labels: {
style: {
colors: "#0000af"
},
formatter: function (value) {
return value.toFixed(2);
}
},
title: {
text: "Kurs",
rotate: -90,
offsetX: 0,
offsetY: 0,
style: {
color: "#0000af"
}
}
}],
tooltip: {
shared: true,
intersect: false,
x: {
show: true,
format: 'dd MMM yyyy'
}
},
annotations: {
yaxis: [{
y: ylevel,
borderColor: '#FF4560',
label: {
borderColor: '#FF4560',
position: 'left',
offsetX: 50, // Adjust this value to position the label in the left 25% quarter
style: {
color: '#fff',
background: '#FF4560'
},
text: 'Kaufzone'
}
}],
xaxis: [{
x: new Date(parseInt(timestamps[Math.floor(timestamps.length / 2)])),
borderColor: '#775DD0',
label: {
borderColor: '#775DD0',
style: {
color: '#fff',
background: '#775DD0'
},
text: 'Event'
}
}]
},
legend: {
show: true,
horizontalAlign: "left",
offsetX: 40
}
};
var chart = new ApexCharts(document.querySelector(`#${divId}`), options);
chart.zoomed = false;
chart.render();
})
.catch(error => console.error('Error fetching data:', error));
}