47 lines
1.7 KiB
Python
47 lines
1.7 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
|
|
from bot import start_scheduler, run_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.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()
|
|
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,
|
|
}
|
|
return templates.TemplateResponse("index.html", {"request": request, "decisions": decisions, "trades": trades, "stats": stats})
|
|
finally:
|
|
db.close()
|