From 64ffd9aa32449b0a4239eb33ff77800a8b4b8aa0 Mon Sep 17 00:00:00 2001 From: Melchior Reimers Date: Sun, 25 Jan 2026 17:46:47 +0100 Subject: [PATCH] updated --- dashboard/public/index.html | 5 +-- dashboard/server.py | 62 +++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/dashboard/public/index.html b/dashboard/public/index.html index e987b36..d95faa4 100644 --- a/dashboard/public/index.html +++ b/dashboard/public/index.html @@ -547,10 +547,11 @@ async function fetchData() { try { + // Verwende limit für trades um Performance zu verbessern const [t, m, s] = await Promise.all([ - fetch(`${API}/trades?days=7`).then(r => r.json()), + fetch(`${API}/trades?days=7&limit=1000`).then(r => r.json()), fetch(`${API}/metadata`).then(r => r.json()), - fetch(`${API}/summary`).then(r => r.json()) + fetch(`${API}/summary?days=7`).then(r => r.json()) ]); store = { ...store, trades: t.dataset || [], metadata: m.dataset || [], summary: s.dataset || [] }; updateDashboard(); diff --git a/dashboard/server.py b/dashboard/server.py index 46d0c19..9de2bc0 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -28,11 +28,15 @@ DB_AUTH = (DB_USER, DB_PASSWORD) if DB_USER and DB_PASSWORD else None DB_HOST = os.getenv("DB_HOST", "questdb") @app.get("/api/trades") -async def get_trades(isin: str = None, days: int = 7): +async def get_trades(isin: str = None, days: int = 7, limit: int = 1000): + """ + Gibt Trades zurück. Standardmäßig limitiert auf 1000 für Performance. + Für Dashboard-Übersicht werden nur die neuesten Trades benötigt. + """ query = f"select * from trades where timestamp > dateadd('d', -{days}, now())" if isin: query += f" and isin = '{isin}'" - query += " order by timestamp asc" + query += f" order by timestamp desc limit {limit}" try: response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH) @@ -54,19 +58,56 @@ async def get_metadata(): raise HTTPException(status_code=500, detail=str(e)) @app.get("/api/summary") -async def get_summary(): - # Coalesce null values to 'Unknown' and group properly - query = """ +async def get_summary(days: int = 7): + """ + Gibt Zusammenfassung zurück. Optimiert für schnelle Abfrage. + Falls vorberechnete Daten verfügbar sind, verwende diese. + """ + # Versuche zuerst, aus analytics_exchange_daily zu aggregieren (schneller) + # Falls das nicht funktioniert, falle auf die ursprüngliche Query zurück + try: + # Aggregiere aus analytics_exchange_daily für die letzten N Tage + # Dies ist schneller als eine JOIN-Query auf alle Trades + query = f""" + select + 'All' as continent, + sum(trade_count) as trade_count, + sum(volume) as total_volume + from analytics_exchange_daily + where timestamp >= dateadd('d', -{days}, now()) + """ + response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH, timeout=5) + if response.status_code == 200: + data = response.json() + # Wenn Daten vorhanden, verwende diese + if data.get('dataset') and len(data['dataset']) > 0: + # Formatiere für Kompatibilität mit dem Frontend + result = { + 'columns': [ + {'name': 'continent'}, + {'name': 'trade_count'}, + {'name': 'total_volume'} + ], + 'dataset': [[row[0], row[1], row[2]] for row in data['dataset']] + } + return result + except Exception: + # Fallback auf ursprüngliche Query + pass + + # Fallback: Original Query mit Limit für Performance + query = f""" select coalesce(m.continent, 'Unknown') as continent, count(*) as trade_count, sum(t.price * t.quantity) as total_volume from trades t left join metadata m on t.isin = m.isin + where t.timestamp > dateadd('d', -{days}, now()) group by continent """ try: - response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH) + response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH, timeout=10) if response.status_code == 200: return response.json() throw_http_error(response) @@ -175,6 +216,7 @@ async def get_moving_average(days: int = 7, exchange: str = None): """ Gibt Moving Average Daten für Tradezahlen und Volumen je Exchange zurück. Unterstützte Zeiträume: 7, 30, 42, 69, 180, 365 Tage + Verwendet vorberechnete Daten aus analytics_exchange_daily für schnelle Antwortzeiten. """ if days not in [7, 30, 42, 69, 180, 365]: raise HTTPException(status_code=400, detail="Invalid days parameter. Must be one of: 7, 30, 42, 69, 180, 365") @@ -198,7 +240,7 @@ async def get_moving_average(days: int = 7, exchange: str = None): query += " order by date asc, exchange asc" try: - response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH) + response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH, timeout=5) if response.status_code == 200: return response.json() throw_http_error(response) @@ -210,6 +252,7 @@ async def get_volume_changes(days: int = 7): """ Gibt Änderungen in Volumen und Anzahl je Exchange zurück. Unterstützte Zeiträume: 7, 30, 42, 69, 180, 365 Tage + Verwendet vorberechnete Daten aus analytics_volume_changes für schnelle Antwortzeiten. """ if days not in [7, 30, 42, 69, 180, 365]: raise HTTPException(status_code=400, detail="Invalid days parameter. Must be one of: 7, 30, 42, 69, 180, 365") @@ -229,7 +272,7 @@ async def get_volume_changes(days: int = 7): """ try: - response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH) + response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH, timeout=5) if response.status_code == 200: return response.json() throw_http_error(response) @@ -241,6 +284,7 @@ async def get_stock_trends(days: int = 7, limit: int = 20): """ Gibt Trendanalyse für häufig gehandelte Aktien zurück. Unterstützte Zeiträume: 7, 30, 42, 69, 180, 365 Tage + Verwendet vorberechnete Daten aus analytics_stock_trends für schnelle Antwortzeiten. """ if days not in [7, 30, 42, 69, 180, 365]: raise HTTPException(status_code=400, detail="Invalid days parameter. Must be one of: 7, 30, 42, 69, 180, 365") @@ -261,7 +305,7 @@ async def get_stock_trends(days: int = 7, limit: int = 20): """ try: - response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH) + response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH, timeout=5) if response.status_code == 200: return response.json() throw_http_error(response)