fix: JSON serialization crash on NaN floats in cycle context snapshot
- portfolio_context.py: add _safe_float() helper (converts NaN/Inf → None);
use .squeeze().dropna() on yfinance closes before computing moves;
guard division by checking closes.iloc[-2] != 0
- cycle.py: add _sanitize_floats() recursive sanitizer applied to the full
snapshot before FastAPI serializes it — catches any remaining NaN from
iv_rank, technical indicators, or other sources
Fixes 500 on GET /api/cycle/contexts/{run_id} when yfinance returns NaN
weekend data for portfolio positions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -91,13 +91,25 @@ def list_context_snapshots(limit: int = 30):
|
||||
return {"snapshots": list_cycle_context_snapshots(limit=limit)}
|
||||
|
||||
|
||||
def _sanitize_floats(obj):
|
||||
"""Recursively replace NaN/Inf floats with None for JSON-safe serialization."""
|
||||
import math
|
||||
if isinstance(obj, float):
|
||||
return None if (math.isnan(obj) or math.isinf(obj)) else obj
|
||||
if isinstance(obj, dict):
|
||||
return {k: _sanitize_floats(v) for k, v in obj.items()}
|
||||
if isinstance(obj, list):
|
||||
return [_sanitize_floats(v) for v in obj]
|
||||
return obj
|
||||
|
||||
|
||||
@router.get("/contexts/{run_id}")
|
||||
def get_context_snapshot(run_id: str):
|
||||
"""Return the full context snapshot for a given cycle run_id."""
|
||||
snap = get_cycle_context_snapshot(run_id)
|
||||
if not snap:
|
||||
raise HTTPException(404, "Snapshot non trouvé pour ce cycle")
|
||||
return snap
|
||||
return _sanitize_floats(snap)
|
||||
|
||||
|
||||
@router.get("/ai-calls/{run_id}")
|
||||
|
||||
Reference in New Issue
Block a user