diff --git a/app.py b/app.py index 611fca2..5091aa7 100644 --- a/app.py +++ b/app.py @@ -33,6 +33,70 @@ def curate_now(): def api_account(): return JSONResponse(account_snapshot()) +@app.get("/api/metrics") +def api_metrics(hours: int = 72): + db = SessionLocal() + try: + since = datetime.utcnow() - timedelta(hours=hours) + decs = db.query(BotDecision).filter(BotDecision.ts >= since).order_by(BotDecision.ts.asc()).all() + trades = db.query(TradeExecution).filter(TradeExecution.ts >= since).order_by(TradeExecution.ts.asc()).all() + + # hour buckets + buckets = {} + for d in decs: + k = d.ts.strftime("%m-%d %H:00") + buckets.setdefault(k, {"buy": 0, "sell": 0, "hold": 0, "executed": 0, "failed": 0}) + if d.action in ("buy", "sell", "hold"): + buckets[k][d.action] += 1 + if d.status == "executed": + buckets[k]["executed"] += 1 + if d.status == "failed": + buckets[k]["failed"] += 1 + + labels = list(buckets.keys()) + buy = [buckets[k]["buy"] for k in labels] + sell = [buckets[k]["sell"] for k in labels] + hold = [buckets[k]["hold"] for k in labels] + executed = [buckets[k]["executed"] for k in labels] + failed = [buckets[k]["failed"] for k in labels] + + # cumulative notional (proxy activity curve) + t_labels, t_values = [], [] + c = 0.0 + for t in trades: + c += float(t.notional or 0) + t_labels.append(t.ts.strftime("%m-%d %H:%M")) + t_values.append(round(c, 2)) + + # symbol leaderboard + lb = {} + for d in decs: + row = lb.setdefault(d.symbol, {"symbol": d.symbol, "decisions": 0, "executed": 0}) + row["decisions"] += 1 + if d.status == "executed": + row["executed"] += 1 + leaderboard = sorted(lb.values(), key=lambda x: x["executed"], reverse=True) + + return { + "ok": True, + "hours": hours, + "decisionSeries": { + "labels": labels, + "buy": buy, + "sell": sell, + "hold": hold, + "executed": executed, + "failed": failed, + }, + "activitySeries": { + "labels": t_labels, + "cumulativeNotional": t_values, + }, + "leaderboard": leaderboard, + } + finally: + db.close() + @app.get("/") def home(request: Request): db = SessionLocal() diff --git a/templates/index.html b/templates/index.html index dbf006c..ae37f5b 100644 --- a/templates/index.html +++ b/templates/index.html @@ -4,19 +4,31 @@ alpaca-llm-bot-v1 + -

alpaca-llm-bot-v1

+

alpaca-llm-bot-v1 · Mission Control

+
Autonomous trading telemetry · updates every 60s · non-blocking UI reads
+
Decisions (24h)
{{ stats.decisions }}
Trades (24h)
{{ stats.trades }}
@@ -25,16 +37,35 @@
Curated Insights
{{ stats.insights }}
-
-
-

Recent Decisions

+
+
+
Decision Flow (last 72h)
+
+
+
+
Cumulative Notional Activity
+
+
+
+ +
+
Symbol Leaderboard
+
+
+
+ +
+
+

Recent Decisions latest 120

+
- + {% for d in decisions %} - + + @@ -47,28 +78,76 @@
-

Curated Market Briefs

-
+

Curated Briefs latest 30

+
{% for i in insights %} -
+
{{ i.symbol }} · {{ i.ts }}
-
{{ i.summary }}
+
{{ i.summary }}
{% endfor %}
-

Recent Trades

-
-
TimeSymbolActionConfidenceStatusReason
TimeSymbolActionConfStatusReason
{{ d.ts }}{{ d.symbol }}{{ d.ts }}{{ d.symbol }} {{ d.action }} {{ '%.2f'|format(d.confidence or 0) }} {{ d.status }}
- - - {% for t in trades %} - - {% endfor %} - -
TimeSymbolSideNotionalOrder ID
{{ t.ts }}{{ t.symbol }}{{ t.side }}${{ '%.2f'|format(t.notional or 0) }}{{ t.alpaca_order_id }}
-
+