Projet terminé V1.0
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* charts.js — Graphiques Chart.js pour l'analyse technique.
|
||||
* - Graphique principal : cours de clôture + MM20/MM50/MM200 (toggle)
|
||||
* - Graphique volume : histogramme + moyenne 20j
|
||||
* - Graphique volatilité : courbe 20j
|
||||
*
|
||||
* Utilise un axe X catégoriel (dates en labels) pour éviter toute
|
||||
* dépendance à un adapter temporel.
|
||||
*/
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const dataCoursEl = document.getElementById("data-cours");
|
||||
const dataVolEl = document.getElementById("data-volumes");
|
||||
const dataVolatEl = document.getElementById("data-volatilite");
|
||||
|
||||
if (!dataCoursEl) return; // pas de données (page d'accueil)
|
||||
|
||||
let dataCours, dataVol, dataVolat;
|
||||
try {
|
||||
dataCours = JSON.parse(dataCoursEl.textContent);
|
||||
dataVol = JSON.parse(dataVolEl.textContent);
|
||||
dataVolat = JSON.parse(dataVolatEl.textContent);
|
||||
} catch (e) {
|
||||
console.error("Erreur parsing JSON graphiques:", e);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[charts] données chargées:",
|
||||
"cours=" + dataCours.dates.length + "pts",
|
||||
"vol=" + dataVol.volumes.length + "pts");
|
||||
|
||||
// --- Configuration globale Chart.js ---
|
||||
if (typeof Chart === "undefined") {
|
||||
console.error("[charts] Chart.js non chargé");
|
||||
return;
|
||||
}
|
||||
Chart.defaults.color = "#9ca3af";
|
||||
Chart.defaults.borderColor = "#1f2937";
|
||||
Chart.defaults.font.family = "system-ui, sans-serif";
|
||||
|
||||
const labels = dataCours.dates;
|
||||
|
||||
// ===================== GRAPHIQUE PRINCIPAL =====================
|
||||
const datasetsCours = [
|
||||
{
|
||||
label: "Cours",
|
||||
data: dataCours.close,
|
||||
borderColor: "#60a5fa",
|
||||
backgroundColor: "rgba(96, 165, 250, 0.1)",
|
||||
borderWidth: 1.5,
|
||||
pointRadius: 0,
|
||||
fill: true,
|
||||
tension: 0.1,
|
||||
},
|
||||
];
|
||||
|
||||
if (dataCours.MM20) {
|
||||
datasetsCours.push({
|
||||
label: "MM20", data: dataCours.MM20, borderColor: "#3b82f6",
|
||||
borderWidth: 1.2, pointRadius: 0, fill: false, tension: 0.1, hidden: false, id: "mm20",
|
||||
});
|
||||
}
|
||||
if (dataCours.MM50) {
|
||||
datasetsCours.push({
|
||||
label: "MM50", data: dataCours.MM50, borderColor: "#10b981",
|
||||
borderWidth: 1.2, pointRadius: 0, fill: false, tension: 0.1, hidden: false, id: "mm50",
|
||||
});
|
||||
}
|
||||
if (dataCours.MM200) {
|
||||
datasetsCours.push({
|
||||
label: "MM200", data: dataCours.MM200, borderColor: "#f59e0b",
|
||||
borderWidth: 1.2, pointRadius: 0, fill: false, tension: 0.1, hidden: false, id: "mm200",
|
||||
});
|
||||
}
|
||||
|
||||
const ctxCours = document.getElementById("chartCours");
|
||||
if (ctxCours) {
|
||||
const chartCours = new Chart(ctxCours, {
|
||||
type: "line",
|
||||
data: { labels: labels, datasets: datasetsCours },
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { intersect: false, mode: "index" },
|
||||
scales: {
|
||||
x: {
|
||||
grid: { color: "#1f2937" },
|
||||
ticks: { maxTicksLimit: 10, autoSkip: true },
|
||||
},
|
||||
y: {
|
||||
position: "right",
|
||||
grid: { color: "#1f2937" },
|
||||
ticks: { callback: v => v.toFixed(2) },
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
backgroundColor: "#111827", borderColor: "#374151", borderWidth: 1,
|
||||
callbacks: { label: ctx => `${ctx.dataset.label}: ${ctx.parsed.y !== null ? ctx.parsed.y.toFixed(2) : 'N/A'}` },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
document.getElementById("toggle-mm20")?.addEventListener("change", e => {
|
||||
const ds = chartCours.data.datasets.find(d => d.id === "mm20");
|
||||
if (ds) ds.hidden = !e.target.checked;
|
||||
chartCours.update();
|
||||
});
|
||||
document.getElementById("toggle-mm50")?.addEventListener("change", e => {
|
||||
const ds = chartCours.data.datasets.find(d => d.id === "mm50");
|
||||
if (ds) ds.hidden = !e.target.checked;
|
||||
chartCours.update();
|
||||
});
|
||||
document.getElementById("toggle-mm200")?.addEventListener("change", e => {
|
||||
const ds = chartCours.data.datasets.find(d => d.id === "mm200");
|
||||
if (ds) ds.hidden = !e.target.checked;
|
||||
chartCours.update();
|
||||
});
|
||||
}
|
||||
|
||||
// ===================== GRAPHIQUE VOLUME =====================
|
||||
const ctxVol = document.getElementById("chartVolume");
|
||||
if (ctxVol) {
|
||||
const volColors = dataVol.volumes.map((v, i) => {
|
||||
const vm = dataVol.moyenne_20j[i];
|
||||
return vm && v > vm * 2 ? "#f59e0b" : "#3b82f6";
|
||||
});
|
||||
|
||||
new Chart(ctxVol, {
|
||||
type: "bar",
|
||||
data: {
|
||||
labels: dataVol.dates,
|
||||
datasets: [
|
||||
{ label: "Volume", data: dataVol.volumes, backgroundColor: volColors, borderWidth: 0, order: 2 },
|
||||
{
|
||||
label: "Moyenne 20j", type: "line", data: dataVol.moyenne_20j,
|
||||
borderColor: "#10b981", borderWidth: 1.5, pointRadius: 0, fill: false, tension: 0.1, order: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { intersect: false, mode: "index" },
|
||||
scales: {
|
||||
x: { display: false },
|
||||
y: {
|
||||
position: "right", grid: { color: "#1f2937" },
|
||||
ticks: { callback: v => v >= 1e6 ? (v / 1e6).toFixed(1) + "M" : v >= 1e3 ? (v / 1e3).toFixed(0) + "K" : v },
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
backgroundColor: "#111827", borderColor: "#374151", borderWidth: 1,
|
||||
callbacks: { label: ctx => ctx.dataset.label + ": " + (ctx.parsed.y !== null ? ctx.parsed.y.toLocaleString("fr-FR") : "N/A") },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ===================== GRAPHIQUE VOLATILITÉ =====================
|
||||
const ctxVolat = document.getElementById("chartVolatilite");
|
||||
if (ctxVolat) {
|
||||
new Chart(ctxVolat, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: dataVolat.dates,
|
||||
datasets: [
|
||||
{
|
||||
label: "Volatilité 20j", data: dataVolat.volatilite_20j,
|
||||
borderColor: "#f59e0b", backgroundColor: "rgba(245, 158, 11, 0.1)",
|
||||
borderWidth: 1.5, pointRadius: 0, fill: true, tension: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { intersect: false, mode: "index" },
|
||||
scales: {
|
||||
x: { grid: { color: "#1f2937" }, ticks: { maxTicksLimit: 10, autoSkip: true } },
|
||||
y: { position: "right", grid: { color: "#1f2937" }, ticks: { callback: v => v.toFixed(1) + "%" } },
|
||||
},
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
backgroundColor: "#111827", borderColor: "#374151", borderWidth: 1,
|
||||
callbacks: { label: ctx => "Volatilité: " + (ctx.parsed.y !== null ? ctx.parsed.y.toFixed(2) : "N/A") + "%" },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log("[charts] graphiques initialisés");
|
||||
});
|
||||
Reference in New Issue
Block a user