Files
crypto_monitor/lib/hub/hub_monitor_totals_lib.py
T
2026-07-04 23:10:32 +08:00

94 lines
3.0 KiB
Python

"""监控区看板:三所当日统计聚合。"""
from __future__ import annotations
from typing import Any
def _coerce_float(value: Any) -> float | None:
if value is None or value == "":
return None
try:
return float(value)
except (TypeError, ValueError):
return None
def position_unrealized_pnl(pos: dict[str, Any]) -> float:
for key in ("unrealized_pnl", "unrealizedPnl", "upnl"):
v = _coerce_float(pos.get(key))
if v is not None:
return v
return 0.0
def _open_positions(agent: dict[str, Any] | None) -> list[dict[str, Any]]:
if not isinstance(agent, dict):
return []
positions = agent.get("positions")
if not isinstance(positions, list):
return []
out: list[dict[str, Any]] = []
for p in positions:
if not isinstance(p, dict):
continue
try:
c = abs(float(p.get("contracts") or 0))
except (TypeError, ValueError):
c = 0.0
if c > 1e-12:
out.append(p)
return out
def aggregate_monitor_board_totals(
rows: list[dict[str, Any]],
*,
trading_day: str,
reset_hour: int = 8,
) -> dict[str, Any]:
"""汇总监控 board 各行 → 左上统计卡数据。"""
open_count = 0
closed_count = 0
win_count = 0
loss_count = 0
win_pnl_u = 0.0
loss_pnl_u = 0.0
open_position_count = 0
float_pnl_u = 0.0
for row in rows or []:
if not isinstance(row, dict):
continue
day_stats = row.get("day_stats") if isinstance(row.get("day_stats"), dict) else {}
if day_stats.get("ok"):
open_count += int(day_stats.get("opens_today") or 0)
st = day_stats.get("trade_stats") if isinstance(day_stats.get("trade_stats"), dict) else {}
closed_count += int(st.get("closed_count") or 0)
win_count += int(st.get("win_count") or 0)
loss_count += int(st.get("loss_count") or 0)
win_pnl_u += float(st.get("win_pnl_u") or 0)
loss_pnl_u += float(st.get("loss_pnl_u") or 0)
ag = row.get("agent") if isinstance(row.get("agent"), dict) else {}
open_pos = _open_positions(ag)
open_position_count += len(open_pos)
agent_upnl = _coerce_float(ag.get("total_unrealized_pnl"))
if agent_upnl is not None:
float_pnl_u += agent_upnl
else:
float_pnl_u += sum(position_unrealized_pnl(p) for p in open_pos)
return {
"trading_day": trading_day,
"reset_hour": int(reset_hour),
"open_count": open_count,
"closed_count": closed_count,
"win_count": win_count,
"loss_count": loss_count,
"win_pnl_u": round(win_pnl_u, 4),
"loss_pnl_u": round(loss_pnl_u, 4),
"realized_pnl_u": round(win_pnl_u + loss_pnl_u, 4),
"open_position_count": open_position_count,
"float_pnl_u": round(float_pnl_u, 4),
}