71 lines
2.5 KiB
Python
71 lines
2.5 KiB
Python
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, PriceHistory, Strategy, Trade, Stock
|
|
from app.engine.scheduler import scheduler
|
|
|
|
router = APIRouter(prefix="/api/dashboard", tags=["dashboard"])
|
|
|
|
|
|
@router.get("/")
|
|
def dashboard(db: Session = Depends(get_db)) -> dict:
|
|
holdings = db.query(Holding).all()
|
|
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()
|
|
|
|
total_profit = sum(h.profit for h in holdings)
|
|
total_invested = sum(h.avg_price * h.qty for h in holdings if h.avg_price > 0)
|
|
total_evaluated = sum(h.current_price * h.qty for h in holdings if h.current_price > 0)
|
|
|
|
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": [
|
|
{
|
|
"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,
|
|
}
|
|
for h in 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,
|
|
}
|