feat: cockpit

This commit is contained in:
OpenSquared
2026-07-23 22:04:02 +02:00
parent cfc33d1ee3
commit 548bad2dcd
5 changed files with 165 additions and 247 deletions

View File

@@ -1,3 +1,4 @@
import math
from fastapi import APIRouter, Query
from services.database import (
get_portfolio_exposure,
@@ -11,6 +12,17 @@ from services.database import (
router = APIRouter(prefix="/api/risk", tags=["risk"])
def _sanitize(obj):
"""Replace NaN/Inf with None recursively for JSON compliance."""
if isinstance(obj, dict):
return {k: _sanitize(v) for k, v in obj.items()}
if isinstance(obj, list):
return [_sanitize(v) for v in obj]
if isinstance(obj, float) and (math.isnan(obj) or math.isinf(obj)):
return None
return obj
@router.get("/exposure")
def portfolio_exposure():
"""Exposure by asset class + risk factor for open positions."""
@@ -49,3 +61,10 @@ def kelly_sizing(
def risk_dashboard():
"""Full portfolio risk snapshot: concentration, diversification, expected drawdown, recommendation."""
return get_risk_dashboard()
@router.get("/radar")
def risk_radar():
"""5-axis risk radar (Concentration/Volatility/Correlation/Exposure/Drawdown) for the real portfolio."""
from services.portfolio_risk import compute_real_portfolio_risk_radar
return _sanitize(compute_real_portfolio_risk_radar())