From 241e93d7b65b0e1daa85fa7dc2506b482c88abb6 Mon Sep 17 00:00:00 2001 From: Melchior Reimers Date: Tue, 27 Jan 2026 14:35:41 +0100 Subject: [PATCH] Fix: Analytics Worker berechnet jetzt alle Tabellen pro Tag --- dashboard/public/index.html | 75 ++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/dashboard/public/index.html b/dashboard/public/index.html index da83119..e9bb03f 100644 --- a/dashboard/public/index.html +++ b/dashboard/public/index.html @@ -267,8 +267,43 @@ const data = res.dataset || []; const columns = res.columns || []; + console.log('Moving Average API Response:', { + dataLength: data.length, + columns: columns.map(c => c.name), + firstRow: data[0] + }); + if (!data.length) { - console.log('No moving average data available'); + console.warn('No moving average data available - analytics_exchange_daily table may be empty'); + // Zeige leere Graphen mit "Keine Daten" Meldung + const exchangeGroups = { + 'EIX': { canvasId: 'maChartEIX' }, + 'LS': { canvasId: 'maChartLS' }, + 'GETTEX': { canvasId: 'maChartGETTEX' }, + 'XETRA': { canvasId: 'maChartXETRA' }, + 'FRA': { canvasId: 'maChartFRA' }, + 'STU': { canvasId: 'maChartSTU' }, + 'QUOTRIX': { canvasId: 'maChartQUOTRIX' } + }; + Object.values(exchangeGroups).forEach(config => { + const canvas = document.getElementById(config.canvasId); + if (canvas) { + const ctx = canvas.getContext('2d'); + if (charts[config.canvasId]) charts[config.canvasId].destroy(); + charts[config.canvasId] = new Chart(ctx, { + type: 'line', + data: { labels: [], datasets: [] }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { display: false }, + title: { display: true, text: 'Keine Daten verfügbar' } + } + } + }); + } + }); return; } @@ -277,6 +312,11 @@ const countIdx = columns.findIndex(c => c.name === 'trade_count'); const volumeIdx = columns.findIndex(c => c.name === 'volume'); + if (dateIdx === -1 || exchangeIdx === -1 || countIdx === -1 || volumeIdx === -1) { + console.error('Missing required columns:', { dateIdx, exchangeIdx, countIdx, volumeIdx, columns }); + return; + } + // Alle Exchanges mit Canvas-IDs definieren const exchangeGroups = { 'EIX': { exchanges: ['EIX'], canvasId: 'maChartEIX' }, @@ -289,7 +329,18 @@ }; // Alle Daten nach Datum sortieren - const dates = [...new Set(data.map(r => r[dateIdx]))].sort(); + const dates = [...new Set(data.map(r => { + const dateVal = r[dateIdx]; + // Handle timestamp format (could be string or number) + if (typeof dateVal === 'string') { + return dateVal.split('T')[0]; // Extract date part + } else if (typeof dateVal === 'number') { + return new Date(dateVal / 1000).toISOString().split('T')[0]; + } + return dateVal; + }))].sort(); + + console.log('Processed dates:', dates.slice(0, 5), '...', dates.slice(-5)); // Moving Average berechnen (7-Tage gleitender Durchschnitt) const maWindow = 7; @@ -320,16 +371,30 @@ dates.forEach(date => { const dayRows = data.filter(r => { const exchange = r[exchangeIdx]; - return r[dateIdx] === date && config.exchanges.includes(exchange); + const rowDate = r[dateIdx]; + let rowDateStr = rowDate; + if (typeof rowDate === 'string') { + rowDateStr = rowDate.split('T')[0]; + } else if (typeof rowDate === 'number') { + rowDateStr = new Date(rowDate / 1000).toISOString().split('T')[0]; + } + return rowDateStr === date && config.exchanges.includes(exchange); }); groupData[date] = { - tradeCount: dayRows.reduce((sum, r) => sum + (r[countIdx] || 0), 0), - volume: dayRows.reduce((sum, r) => sum + (r[volumeIdx] || 0), 0) + tradeCount: dayRows.reduce((sum, r) => sum + (parseFloat(r[countIdx]) || 0), 0), + volume: dayRows.reduce((sum, r) => sum + (parseFloat(r[volumeIdx]) || 0), 0) }; }); const tradeData = dates.map(d => groupData[d]?.tradeCount || 0); const volumeData = dates.map(d => groupData[d]?.volume || 0); + + console.log(`${groupName} data:`, { + dates: dates.length, + tradeData: tradeData.slice(0, 5), + volumeData: volumeData.slice(0, 5) + }); + const maTradeData = calculateMA(tradeData, maWindow); const maVolumeData = calculateMA(volumeData, maWindow);