Add trading journal and portfolio tracking

This commit is contained in:
kai
2026-09-09 19:01:30 +02:00
parent 1db3b008ec
commit c683bc74c0
24 changed files with 1043 additions and 8 deletions
+28
View File
@@ -0,0 +1,28 @@
'use strict';
(() => {
const status = document.getElementById('trading-chart-status');
if (typeof Chart === 'undefined') {
status.textContent = 'Diagramme konnten nicht geladen werden. Alle Werte sind in den Tabellen verfügbar.';
return;
}
const {stats, sources, strategies, months} = JSON.parse(document.getElementById('trading-data').textContent);
const palette = ['#72e2b0','#79b6ff','#a6b7ca','#bda7d8','#d5bf8d','#78adb1','#8fa494','#b7bac6'];
Chart.defaults.color = '#a4b3c7';
Chart.defaults.borderColor = '#293548';
for (const field of ['by_source', 'by_strategy']) {
const rows = stats[field];
const names = field === 'by_source' ? sources : {...strategies, untagged: 'Ohne Tag'};
new Chart(document.getElementById(field), {
type: 'doughnut', data: {labels: rows.map(r => names[r.key]), datasets:[{data:rows.map(r => Number(r.amount)), backgroundColor:palette, borderWidth:0}]},
options:{responsive:true,maintainAspectRatio:false,animation:false,cutout:'65%',plugins:{legend:{position:'bottom'},tooltip:{callbacks:{label:context => {
const row = rows[context.dataIndex];
return `${names[row.key]}: ${row.amount.replace('.', ',')} ${stats.currency} (${row.percentage === null ? '' : row.percentage.replace('.', ',') + ' %'})`;
}}}}}
});
}
new Chart(document.getElementById('trading-monthly'), {
type:'bar', data:{labels:months,datasets:stats.monthly.map((row,i) => ({label:String(row.year),data:row.counts,backgroundColor:palette[i % palette.length]}))},
options:{responsive:true,maintainAspectRatio:false,animation:false,scales:{y:{beginAtZero:true,ticks:{precision:0},title:{display:true,text:'Anzahl Käufe'}}}}
});
status.textContent = 'Diagramme zeigen den offenen Einstand und die Anzahl echter Käufe in der gewählten Währung.';
})();