fixed dashboard - updated analytics to include sectors instead of isin
Some checks failed
Deployment / deploy-docker (push) Has been cancelled
Some checks failed
Deployment / deploy-docker (push) Has been cancelled
This commit is contained in:
@@ -47,9 +47,9 @@ const ANALYTICS_CONFIG = {
|
|||||||
label: 'Exchange',
|
label: 'Exchange',
|
||||||
description: 'Gruppierung nach Exchange'
|
description: 'Gruppierung nach Exchange'
|
||||||
},
|
},
|
||||||
'isin': {
|
'sector': {
|
||||||
label: 'ISIN',
|
label: 'Sektor',
|
||||||
description: 'Gruppierung nach ISIN'
|
description: 'Gruppierung nach Sektor'
|
||||||
},
|
},
|
||||||
'date': {
|
'date': {
|
||||||
label: 'Datum',
|
label: 'Datum',
|
||||||
|
|||||||
@@ -383,7 +383,7 @@
|
|||||||
if (typeof dateVal === 'string') {
|
if (typeof dateVal === 'string') {
|
||||||
return dateVal.split('T')[0]; // Extract date part
|
return dateVal.split('T')[0]; // Extract date part
|
||||||
} else if (typeof dateVal === 'number') {
|
} 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;
|
return dateVal;
|
||||||
}))].sort();
|
}))].sort();
|
||||||
@@ -424,7 +424,7 @@
|
|||||||
if (typeof rowDate === 'string') {
|
if (typeof rowDate === 'string') {
|
||||||
rowDateStr = rowDate.split('T')[0];
|
rowDateStr = rowDate.split('T')[0];
|
||||||
} else if (typeof rowDate === 'number') {
|
} 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);
|
return rowDateStr === date && config.exchanges.includes(exchange);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ async def get_custom_analytics(
|
|||||||
# Validiere Parameter
|
# Validiere Parameter
|
||||||
valid_x_axis = ["date", "exchange", "isin"]
|
valid_x_axis = ["date", "exchange", "isin"]
|
||||||
valid_y_axis = ["volume", "trade_count", "avg_price"]
|
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:
|
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}")
|
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:
|
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}")
|
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)
|
# Für Custom Analytics: x_axis muss "date" sein (wird täglich vorberechnet)
|
||||||
if x_axis != "date":
|
if x_axis != "date":
|
||||||
# Für nicht-date x_axis: gib Fehler zurück, da dies nicht vorberechnet wird
|
# Für nicht-date x_axis: gib Fehler zurück, da dies nicht vorberechnet wird
|
||||||
raise HTTPException(
|
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."
|
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
|
# Nutze vorberechnete Daten aus analytics_custom
|
||||||
exchange_filter = "all"
|
exchange_filter = "all"
|
||||||
|
|||||||
Reference in New Issue
Block a user