feat: google cloud billing style analytics and robust reporting API
All checks were successful
Deployment / deploy-docker (push) Successful in 15s
All checks were successful
Deployment / deploy-docker (push) Successful in 15s
This commit is contained in:
@@ -73,22 +73,63 @@ async def get_summary():
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@app.get("/api/comparison")
|
||||
async def get_comparison(days: int = 7):
|
||||
# Aggregated volume per exchange per day
|
||||
# QuestDB date_trunc('day', timestamp) is good.
|
||||
# We ensure we get exchange, day, and metrics.
|
||||
query = f"""
|
||||
select
|
||||
exchange,
|
||||
date_trunc('day', timestamp) as day,
|
||||
sum(price * quantity) as daily_volume,
|
||||
count(*) as trade_count
|
||||
from trades
|
||||
where timestamp > dateadd('d', -{days}, now())
|
||||
group by exchange, day
|
||||
order by day asc
|
||||
"""
|
||||
@app.get("/api/analytics")
|
||||
async def get_analytics(
|
||||
metric: str = "volume",
|
||||
group_by: str = "day",
|
||||
sub_group_by: str = None,
|
||||
date_from: str = None,
|
||||
date_to: str = None,
|
||||
isins: str = None,
|
||||
continents: str = None
|
||||
):
|
||||
metrics_map = {
|
||||
"volume": "sum(t.price * t.quantity)",
|
||||
"count": "count(*)",
|
||||
"avg_price": "avg(t.price)"
|
||||
}
|
||||
|
||||
groups_map = {
|
||||
"day": "date_trunc('day', t.timestamp)",
|
||||
"month": "date_trunc('month', t.timestamp)",
|
||||
"exchange": "t.exchange",
|
||||
"isin": "t.isin",
|
||||
"name": "coalesce(m.name, t.isin)",
|
||||
"continent": "coalesce(m.continent, 'Unknown')",
|
||||
"sector": "coalesce(m.sector, 'Unknown')"
|
||||
}
|
||||
|
||||
selected_metric = metrics_map.get(metric, metrics_map["volume"])
|
||||
selected_group = groups_map.get(group_by, groups_map["day"])
|
||||
|
||||
# We always join metadata to allow filtering by continent/sector even if not grouping by them
|
||||
query = f"select {selected_group} as label"
|
||||
|
||||
if sub_group_by and sub_group_by in groups_map:
|
||||
query += f", {groups_map[sub_group_by]} as sub_label"
|
||||
|
||||
query += f", {selected_metric} as value from trades t"
|
||||
query += " left join metadata m on t.isin = m.isin where 1=1"
|
||||
|
||||
if date_from:
|
||||
query += f" and t.timestamp >= '{date_from}'"
|
||||
if date_to:
|
||||
query += f" and t.timestamp <= '{date_to}'"
|
||||
|
||||
if isins:
|
||||
isins_list = ",".join([f"'{i.strip()}'" for i in isins.split(",")])
|
||||
query += f" and t.isin in ({isins_list})"
|
||||
|
||||
if continents:
|
||||
cont_list = ",".join([f"'{c.strip()}'" for c in continents.split(",")])
|
||||
query += f" and m.continent in ({cont_list})"
|
||||
|
||||
query += " group by label"
|
||||
if sub_group_by and sub_group_by in groups_map:
|
||||
query += ", sub_label"
|
||||
|
||||
query += " order by label asc"
|
||||
|
||||
try:
|
||||
response = requests.get(f"http://{DB_HOST}:9000/exec", params={'query': query}, auth=DB_AUTH)
|
||||
if response.status_code == 200:
|
||||
|
||||
Reference in New Issue
Block a user