This commit is contained in:
@@ -547,10 +547,11 @@
|
|||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
try {
|
try {
|
||||||
|
// Verwende limit für trades um Performance zu verbessern
|
||||||
const [t, m, s] = await Promise.all([
|
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}/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 || [] };
|
store = { ...store, trades: t.dataset || [], metadata: m.dataset || [], summary: s.dataset || [] };
|
||||||
updateDashboard();
|
updateDashboard();
|
||||||
|
|||||||
@@ -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")
|
DB_HOST = os.getenv("DB_HOST", "questdb")
|
||||||
|
|
||||||
@app.get("/api/trades")
|
@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())"
|
query = f"select * from trades where timestamp > dateadd('d', -{days}, now())"
|
||||||
if isin:
|
if isin:
|
||||||
query += f" and isin = '{isin}'"
|
query += f" and isin = '{isin}'"
|
||||||
query += " order by timestamp asc"
|
query += f" order by timestamp desc limit {limit}"
|
||||||
|
|
||||||
try:
|
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)
|
||||||
@@ -54,19 +58,56 @@ async def get_metadata():
|
|||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
@app.get("/api/summary")
|
@app.get("/api/summary")
|
||||||
async def get_summary():
|
async def get_summary(days: int = 7):
|
||||||
# Coalesce null values to 'Unknown' and group properly
|
"""
|
||||||
query = """
|
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
|
select
|
||||||
coalesce(m.continent, 'Unknown') as continent,
|
coalesce(m.continent, 'Unknown') as continent,
|
||||||
count(*) as trade_count,
|
count(*) as trade_count,
|
||||||
sum(t.price * t.quantity) as total_volume
|
sum(t.price * t.quantity) as total_volume
|
||||||
from trades t
|
from trades t
|
||||||
left join metadata m on t.isin = m.isin
|
left join metadata m on t.isin = m.isin
|
||||||
|
where t.timestamp > dateadd('d', -{days}, now())
|
||||||
group by continent
|
group by continent
|
||||||
"""
|
"""
|
||||||
try:
|
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:
|
if response.status_code == 200:
|
||||||
return response.json()
|
return response.json()
|
||||||
throw_http_error(response)
|
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.
|
Gibt Moving Average Daten für Tradezahlen und Volumen je Exchange zurück.
|
||||||
Unterstützte Zeiträume: 7, 30, 42, 69, 180, 365 Tage
|
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]:
|
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")
|
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"
|
query += " order by date asc, exchange asc"
|
||||||
|
|
||||||
try:
|
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:
|
if response.status_code == 200:
|
||||||
return response.json()
|
return response.json()
|
||||||
throw_http_error(response)
|
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.
|
Gibt Änderungen in Volumen und Anzahl je Exchange zurück.
|
||||||
Unterstützte Zeiträume: 7, 30, 42, 69, 180, 365 Tage
|
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]:
|
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")
|
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:
|
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:
|
if response.status_code == 200:
|
||||||
return response.json()
|
return response.json()
|
||||||
throw_http_error(response)
|
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.
|
Gibt Trendanalyse für häufig gehandelte Aktien zurück.
|
||||||
Unterstützte Zeiträume: 7, 30, 42, 69, 180, 365 Tage
|
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]:
|
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")
|
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:
|
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:
|
if response.status_code == 200:
|
||||||
return response.json()
|
return response.json()
|
||||||
throw_http_error(response)
|
throw_http_error(response)
|
||||||
|
|||||||
Reference in New Issue
Block a user