from __future__ import annotations from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from app.core.auth import token_manager from app.core.database import get_db from app.models.stock import Holding, Strategy, Trade, Stock from app.engine.scheduler import scheduler from app.services.account import account_service from app.services.realtime import realtime_service router = APIRouter(prefix="/api/dashboard", tags=["dashboard"]) @router.get("/") async def dashboard(db: Session = Depends(get_db)) -> dict: recent_trades = db.query(Trade).order_by(Trade.created_at.desc()).limit(20).all() active_strategies = db.query(Strategy).filter(Strategy.is_active == True).all() active_stocks = db.query(Stock).filter(Stock.is_active == True).all() holdings = [] total_profit = 0.0 total_invested = 0.0 total_evaluated = 0.0 if token_manager.is_authenticated: try: balance = await account_service.get_balance() for s in balance.get("stocks", []): holdings.append({ "stock_code": s["stock_code"], "stock_name": s["stock_name"], "qty": s["qty"], "avg_price": s["avg_price"], "current_price": s["current_price"], "profit": s["profit"], "profit_rate": s["profit_rate"], }) total_invested += s.get("buy_amount", s["avg_price"] * s["qty"]) total_evaluated += s.get("eval_amount", s["current_price"] * s["qty"]) total_profit += s["profit"] except Exception: pass if not holdings: local = db.query(Holding).all() for h in local: holdings.append({ "stock_code": h.stock_code, "stock_name": h.stock_name, "qty": h.qty, "avg_price": h.avg_price, "current_price": h.current_price, "profit": h.profit, "profit_rate": h.profit_rate, }) total_invested += h.avg_price * h.qty total_evaluated += h.current_price * h.qty total_profit += h.profit jobs = [] if scheduler.running: for job in scheduler.get_jobs(): jobs.append({ "id": job.id, "name": job.name, "next_run": str(job.next_run_time) if job.next_run_time else None, }) return { "authenticated": token_manager.is_authenticated, "summary": { "total_holdings": len(holdings), "total_profit": total_profit, "total_invested": total_invested, "total_evaluated": total_evaluated, "profit_rate": (total_profit / total_invested * 100) if total_invested > 0 else 0, "active_strategies": len(active_strategies), "active_stocks": len(active_stocks), }, "holdings": holdings, "recent_trades": [ { "id": t.id, "stock_code": t.stock_code, "side": t.side, "qty": t.qty, "price": t.price, "status": t.status, "created_at": t.created_at.isoformat() if t.created_at else None, } for t in recent_trades ], "scheduler_jobs": jobs, } @router.get("/status") def get_status() -> dict: return { "authenticated": token_manager.is_authenticated, "realtime_connected": realtime_service.is_connected, }