Files
alpaca-llm-bot-v1/app.py

54 lines
2.1 KiB
Python

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy import func
from datetime import datetime, timedelta
from db import init_db, SessionLocal, BotDecision, TradeExecution, CuratedInsight
from bot import start_scheduler, run_cycle, curate_cycle
from services import account_snapshot
app = FastAPI(title="alpaca-llm-bot-v1")
templates = Jinja2Templates(directory="templates")
@app.on_event("startup")
def startup():
init_db()
start_scheduler()
@app.get("/health")
def health():
return {"ok": True}
@app.post("/run-now")
def run_now():
run_cycle()
return {"ok": True, "ran": True}
@app.post("/curate-now")
def curate_now():
curate_cycle()
return {"ok": True, "curated": True}
@app.get("/api/account")
def api_account():
return JSONResponse(account_snapshot())
@app.get("/")
def home(request: Request):
db = SessionLocal()
try:
since = datetime.utcnow() - timedelta(hours=24)
decisions = db.query(BotDecision).order_by(BotDecision.ts.desc()).limit(120).all()
trades = db.query(TradeExecution).order_by(TradeExecution.ts.desc()).limit(120).all()
insights = db.query(CuratedInsight).order_by(CuratedInsight.ts.desc()).limit(30).all()
stats = {
"decisions": db.query(func.count(BotDecision.id)).filter(BotDecision.ts >= since).scalar() or 0,
"trades": db.query(func.count(TradeExecution.id)).filter(TradeExecution.ts >= since).scalar() or 0,
"executed": db.query(func.count(BotDecision.id)).filter(BotDecision.ts >= since, BotDecision.status == "executed").scalar() or 0,
"failed": db.query(func.count(BotDecision.id)).filter(BotDecision.ts >= since, BotDecision.status == "failed").scalar() or 0,
"insights": db.query(func.count(CuratedInsight.id)).filter(CuratedInsight.ts >= since).scalar() or 0,
}
return templates.TemplateResponse("index.html", {"request": request, "decisions": decisions, "trades": trades, "insights": insights, "stats": stats})
finally:
db.close()