From f62676652307565844ca0ce1f6df1522d6a2b712 Mon Sep 17 00:00:00 2001 From: Melchior Reimers Date: Tue, 27 Jan 2026 13:36:28 +0100 Subject: [PATCH] updated dashboard --- .../__pycache__/worker.cpython-313.pyc | Bin 36468 -> 39097 bytes src/analytics/worker.py | 60 ++++++++++++++++-- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/analytics/__pycache__/worker.cpython-313.pyc b/src/analytics/__pycache__/worker.cpython-313.pyc index 9fc3e69b9e3ae2b9c15dc72892b976ccb3ba609f..563a8bad7aed17b9bb20e4e963dd82472cd436bc 100644 GIT binary patch delta 3174 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 RF~g>HKyf2!$M0X<_76KkQM~{F diff --git a/src/analytics/worker.py b/src/analytics/worker.py index d1688f5..d825d99 100644 --- a/src/analytics/worker.py +++ b/src/analytics/worker.py @@ -561,12 +561,38 @@ class AnalyticsWorker: """Verarbeitet alle Analytics für einen bestimmten Tag""" logger.info(f"Processing analytics for {date}") - # Custom Analytics (wichtigste Berechnung für Performance) - logger.info(f"Calculating custom analytics for {date}...") - custom_data = self.calculate_custom_analytics_daily(date) - if custom_data: - self.save_analytics_data('analytics_custom', custom_data) - logger.info(f"Saved {len(custom_data)} custom analytics rows for {date}") + # Prüfe ob es Trades für diesen Tag gibt + date_str = date.strftime('%Y-%m-%d') + check_query = f"select count(*) from trades where date_trunc('day', timestamp) = '{date_str}'" + check_data = self.query_questdb(check_query) + trade_count = 0 + if check_data and check_data.get('dataset') and check_data['dataset'][0][0]: + trade_count = check_data['dataset'][0][0] + + if trade_count == 0: + logger.info(f"No trades found for {date}, creating empty analytics entry") + # Erstelle einen leeren Eintrag, damit der Tag als "verarbeitet" gilt + empty_entry = [{ + 'date': date, + 'y_axis': 'volume', + 'group_by': 'exchange', + 'exchange_filter': 'all', + 'x_value': datetime.datetime.combine(date, datetime.time.min).replace(tzinfo=datetime.timezone.utc), + 'group_value': '', + 'y_value': 0 + }] + self.save_analytics_data('analytics_custom', empty_entry) + logger.info(f"Saved empty analytics entry for {date}") + else: + # Custom Analytics (wichtigste Berechnung für Performance) + logger.info(f"Calculating custom analytics for {date} ({trade_count} trades)...") + custom_data = self.calculate_custom_analytics_daily(date) + if custom_data: + self.save_analytics_data('analytics_custom', custom_data) + logger.info(f"Saved {len(custom_data)} custom analytics rows for {date}") + else: + # Auch wenn keine Daten zurückkommen, erstelle leeren Eintrag + logger.warning(f"No custom analytics data returned for {date} despite {trade_count} trades") logger.info(f"Completed processing for {date}") @@ -621,9 +647,29 @@ class AnalyticsWorker: all_dates.append(current) current += datetime.timedelta(days=1) + # Debug: Prüfe das letzte Trade-Datum + query_last = "select max(date_trunc('day', timestamp)) as last_date from trades" + data_last = self.query_questdb(query_last) + last_trade_date = None + if data_last and data_last.get('dataset') and data_last['dataset'][0][0]: + last_date_value = data_last['dataset'][0][0] + if isinstance(last_date_value, str): + last_trade_date = datetime.datetime.fromisoformat(last_date_value.replace('Z', '+00:00')).date() + else: + last_trade_date = datetime.datetime.fromtimestamp(last_date_value / 1000000, tz=datetime.timezone.utc).date() + # Finde fehlende Tage missing_dates = [d for d in all_dates if d not in existing_dates] - logger.info(f"Found {len(missing_dates)} missing dates to calculate (from {len(all_dates)} total dates, first: {first_date}, last: {today})") + + logger.info(f"Date range: first trade={first_date}, last trade={last_trade_date}, today={today}") + logger.info(f"Existing dates in analytics_custom: {len(existing_dates)} dates") + if existing_dates: + existing_sorted = sorted(existing_dates) + logger.info(f" First existing: {existing_sorted[0]}, Last existing: {existing_sorted[-1]}") + logger.info(f"Found {len(missing_dates)} missing dates to calculate (from {len(all_dates)} total dates)") + if missing_dates: + logger.info(f" First missing: {missing_dates[0]}, Last missing: {missing_dates[-1]}") + return sorted(missing_dates) def process_missing_dates(self):