This commit is contained in:
@@ -169,11 +169,12 @@ async def get_custom_analytics(
|
||||
):
|
||||
"""
|
||||
Flexibler Analytics-Endpunkt für custom Graphen.
|
||||
Nutzt vorberechnete Daten aus analytics_custom für bessere Performance.
|
||||
|
||||
Parameters:
|
||||
- date_from: Startdatum (YYYY-MM-DD)
|
||||
- date_to: Enddatum (YYYY-MM-DD)
|
||||
- x_axis: X-Achse (date, exchange, isin)
|
||||
- x_axis: X-Achse (date, exchange, isin) - aktuell nur "date" unterstützt
|
||||
- y_axis: Y-Achse (volume, trade_count, avg_price)
|
||||
- group_by: Gruppierung (exchange, isin, date)
|
||||
- exchanges: Komma-separierte Liste von Exchanges (optional)
|
||||
@@ -190,46 +191,123 @@ async def get_custom_analytics(
|
||||
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}")
|
||||
|
||||
# Baue Query auf
|
||||
y_axis_map = {
|
||||
"volume": "sum(price * quantity)",
|
||||
"trade_count": "count(*)",
|
||||
"avg_price": "avg(price)"
|
||||
}
|
||||
# Für Custom Analytics: x_axis muss "date" sein (wird täglich vorberechnet)
|
||||
if x_axis != "date":
|
||||
# Fallback auf direkte Query für nicht-date x_axis
|
||||
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)
|
||||
|
||||
x_axis_map = {
|
||||
"date": "date_trunc('day', timestamp)",
|
||||
"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]
|
||||
# Nutze vorberechnete Daten aus analytics_custom
|
||||
exchange_filter = "all"
|
||||
if exchanges:
|
||||
# Wenn mehrere Exchanges angegeben, müssen wir kombinieren
|
||||
# Für jetzt: nutze nur wenn ein Exchange angegeben ist
|
||||
exchange_list = [e.strip() for e in exchanges.split(",")]
|
||||
if len(exchange_list) == 1:
|
||||
exchange_filter = exchange_list[0]
|
||||
# Bei mehreren Exchanges: Fallback auf direkte Query
|
||||
else:
|
||||
query = f"""
|
||||
select
|
||||
timestamp as x_value,
|
||||
{group_by} as group_value,
|
||||
{'sum(price * quantity)' if y_axis == 'volume' else 'count(*)' if y_axis == 'trade_count' else 'avg(price)'} as y_value
|
||||
from trades
|
||||
where timestamp >= '{date_from}'
|
||||
and timestamp <= '{date_to}'
|
||||
and exchange in ({','.join([f"'{e}'" for e in exchange_list])})
|
||||
group by timestamp, {group_by}
|
||||
order by timestamp asc, {group_by} asc
|
||||
"""
|
||||
data = query_questdb(query, timeout=15)
|
||||
return format_questdb_response(data)
|
||||
|
||||
# Query für vorberechnete Daten
|
||||
query = f"""
|
||||
select
|
||||
{x_label} as x_value,
|
||||
{group_by_field} as group_value,
|
||||
{y_metric} as y_value
|
||||
from trades
|
||||
timestamp as x_value,
|
||||
group_value,
|
||||
y_value
|
||||
from analytics_custom
|
||||
where timestamp >= '{date_from}'
|
||||
and timestamp <= '{date_to}'
|
||||
and y_axis = '{y_axis}'
|
||||
and group_by = '{group_by}'
|
||||
and exchange_filter = '{exchange_filter}'
|
||||
order by timestamp asc, group_value asc
|
||||
"""
|
||||
|
||||
if exchanges:
|
||||
exchange_list = ",".join([f"'{e.strip()}'" for e in exchanges.split(",")])
|
||||
query += f" and exchange in ({exchange_list})"
|
||||
data = query_questdb(query, timeout=5)
|
||||
if not data or not data.get('dataset'):
|
||||
# Fallback: direkte Query wenn keine vorberechneten Daten vorhanden
|
||||
logger.warning(f"No pre-calculated data found, falling back to direct query")
|
||||
y_axis_map = {
|
||||
"volume": "sum(price * quantity)",
|
||||
"trade_count": "count(*)",
|
||||
"avg_price": "avg(price)"
|
||||
}
|
||||
group_by_map = {
|
||||
"exchange": "exchange",
|
||||
"isin": "isin",
|
||||
"date": "date_trunc('day', timestamp)"
|
||||
}
|
||||
|
||||
y_metric = y_axis_map[y_axis]
|
||||
group_by_field = group_by_map[group_by]
|
||||
|
||||
query = f"""
|
||||
select
|
||||
date_trunc('day', timestamp) 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 date_trunc('day', timestamp), {group_by_field} order by x_value asc, group_value asc"
|
||||
|
||||
data = query_questdb(query, timeout=15)
|
||||
|
||||
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)
|
||||
|
||||
@app.get("/api/statistics/moving-average")
|
||||
|
||||
Reference in New Issue
Block a user