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)