diff --git a/dashboard/server.py b/dashboard/server.py index 50570fe..dd2a0a7 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -528,6 +528,19 @@ def _refresh_vbt_cache(): _vbt_cache_time = now +def _sanitize_nan(obj): + """Recursively replace NaN/Inf/-Inf with 0 for JSON compliance.""" + import math + if isinstance(obj, dict): + return {k: _sanitize_nan(v) for k, v in obj.items()} + if isinstance(obj, list): + return [_sanitize_nan(v) for v in obj] + if isinstance(obj, float): + if math.isnan(obj) or math.isinf(obj): + return 0.0 + return obj + + def _normalize_vbt_fields(data: dict) -> dict: """Normalise old/new backtest file field names to a consistent schema.""" out = dict(data) @@ -570,7 +583,7 @@ def _normalize_vbt_fields(data: dict) -> dict: if out.get("total_trades") is None: out["total_trades"] = 0 - if not out.get("win_rate") and "trades" in out: + if out.get("win_rate") is None and "trades" in out: trades = out.get("trades", []) if trades: wins = sum(1 for t in trades if (t.get("pnl_net", t.get("pnl_gross", t.get("pnl", 0))) or 0) > 0) @@ -604,6 +617,7 @@ def _normalize_vbt_fields(data: dict) -> dict: fee = float(t.get("fee", 0)) t["pnl_gross"] = round(pnl_net + fee, 4) + out = _sanitize_nan(out) return out