Add fleet stats table with funds, fees, loss streak, and totals.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-02 12:25:30 +08:00
parent 5982cb7414
commit 8745d8e6d1
5 changed files with 298 additions and 2 deletions
+54
View File
@@ -278,6 +278,60 @@ async def node_status(
return await _collect_one_status(node)
async def _collect_one_stats(node: dict[str, Any]) -> dict[str, Any]:
base = {
"id": node["id"],
"name": node["name"],
"ok": False,
"error": None,
"latest_funds": None,
"groups": None,
"fees_perp": None,
"fees_option": None,
"total_fees": None,
"max_single_loss": None,
"loss_streak": None,
"total_pnl": None,
}
if not node.get("token_sealed"):
base["error"] = "未生成 Token"
return base
try:
code, data = await call_node(node, "GET", "/api/fleet/stats", timeout=15.0)
except Exception as ex:
base["error"] = str(ex)
return base
if code >= 400 or not isinstance(data, dict):
base["error"] = _http_detail(data) if data else f"HTTP {code}"
return base
base.update(
{
"ok": True,
"latest_funds": data.get("latest_funds"),
"groups": data.get("groups"),
"fees_perp": data.get("fees_perp"),
"fees_option": data.get("fees_option"),
"total_fees": data.get("total_fees"),
"max_single_loss": data.get("max_single_loss"),
"loss_streak": data.get("loss_streak"),
"total_pnl": data.get("total_pnl"),
"mode": data.get("mode"),
}
)
return base
@router.get("/stats/all")
async def stats_all(_user: Annotated[str, Depends(require_control_user)]) -> dict:
"""并行拉取各策略机统计,供监控区「数据统计」表。"""
db = get_control_db()
nodes = db.list_nodes()
if not nodes:
return {"nodes": []}
items = list(await asyncio.gather(*[_collect_one_stats(n) for n in nodes]))
return {"nodes": items}
@router.get("/{node_id}/stats")
async def node_stats(
node_id: int,