From f608f7ca40b12b6be0ccdef57e7347538868bb31 Mon Sep 17 00:00:00 2001 From: Melchior Reimers Date: Tue, 3 Feb 2026 13:58:47 +0100 Subject: [PATCH] fixed dashboard - updated analytics to include sectors instead of isin --- dashboard/public/analytics-config.js | 6 +-- dashboard/public/index.html | 4 +- dashboard/server.py | 71 +++++++++++++--------------- 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/dashboard/public/analytics-config.js b/dashboard/public/analytics-config.js index e40e2a7..80e6af1 100644 --- a/dashboard/public/analytics-config.js +++ b/dashboard/public/analytics-config.js @@ -47,9 +47,9 @@ const ANALYTICS_CONFIG = { label: 'Exchange', description: 'Gruppierung nach Exchange' }, - 'isin': { - label: 'ISIN', - description: 'Gruppierung nach ISIN' + 'sector': { + label: 'Sektor', + description: 'Gruppierung nach Sektor' }, 'date': { label: 'Datum', diff --git a/dashboard/public/index.html b/dashboard/public/index.html index 50157de..9d9ab71 100644 --- a/dashboard/public/index.html +++ b/dashboard/public/index.html @@ -383,7 +383,7 @@ 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 new Date(dateVal / 1000000).toISOString().split('T')[0]; } return dateVal; }))].sort(); @@ -424,7 +424,7 @@ if (typeof rowDate === 'string') { rowDateStr = rowDate.split('T')[0]; } else if (typeof rowDate === 'number') { - rowDateStr = new Date(rowDate / 1000).toISOString().split('T')[0]; + rowDateStr = new Date(rowDate / 1000000).toISOString().split('T')[0]; } return rowDateStr === date && config.exchanges.includes(exchange); }); diff --git a/dashboard/server.py b/dashboard/server.py index 41039e3..7a4f2d9 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -203,7 +203,7 @@ async def get_custom_analytics( # Validiere Parameter valid_x_axis = ["date", "exchange", "isin"] valid_y_axis = ["volume", "trade_count", "avg_price"] - valid_group_by = ["exchange", "isin", "date"] + valid_group_by = ["exchange", "sector", "date"] if x_axis not in valid_x_axis: raise HTTPException(status_code=400, detail=f"Invalid x_axis. Must be one of: {valid_x_axis}") @@ -212,50 +212,43 @@ async def get_custom_analytics( if group_by not in valid_group_by: raise HTTPException(status_code=400, detail=f"Invalid group_by. Must be one of: {valid_group_by}") + # Für Sektor-Gruppierung: direkter JOIN mit metadata (nicht vorberechnet) + if group_by == "sector": + y_axis_map = { + "volume": "sum(t.price * t.quantity)", + "trade_count": "count(*)", + "avg_price": "avg(t.price)" + } + + y_metric = y_axis_map[y_axis] + + query = f""" + select + date_trunc('day', t.timestamp) as x_value, + coalesce(m.sector, 'Unbekannt') as group_value, + {y_metric} as y_value + from trades t + left join metadata m on t.isin = m.isin + where t.timestamp >= '{date_from}' + and t.timestamp <= '{date_to}' + """ + + if exchanges: + exchange_list = ",".join([f"'{e.strip()}'" for e in exchanges.split(",")]) + query += f" and t.exchange in ({exchange_list})" + + query += f" group by date_trunc('day', t.timestamp), coalesce(m.sector, 'Unbekannt') order by x_value asc, group_value asc" + + data = query_questdb(query, timeout=30) + return format_questdb_response(data) + # Für Custom Analytics: x_axis muss "date" sein (wird täglich vorberechnet) if x_axis != "date": # Für nicht-date x_axis: gib Fehler zurück, da dies nicht vorberechnet wird raise HTTPException( - status_code=400, + status_code=400, detail="x_axis must be 'date' for pre-calculated analytics. Other x_axis values are not supported for performance reasons." ) - y_axis_map = { - "volume": "sum(price * quantity)", - "trade_count": "count(*)", - "avg_price": "avg(price)" - } - x_axis_map = { - "exchange": "exchange", - "isin": "isin" - } - group_by_map = { - "exchange": "exchange", - "isin": "isin", - "date": "date_trunc('day', timestamp)" - } - - y_metric = y_axis_map[y_axis] - x_label = x_axis_map[x_axis] - group_by_field = group_by_map[group_by] - - query = f""" - select - {x_label} as x_value, - {group_by_field} as group_value, - {y_metric} as y_value - from trades - where timestamp >= '{date_from}' - and timestamp <= '{date_to}' - """ - - if exchanges: - exchange_list = ",".join([f"'{e.strip()}'" for e in exchanges.split(",")]) - query += f" and exchange in ({exchange_list})" - - query += f" group by {x_label}, {group_by_field} order by {x_label} asc, {group_by_field} asc" - - data = query_questdb(query, timeout=15) - return format_questdb_response(data) # Nutze vorberechnete Daten aus analytics_custom exchange_filter = "all"