Files
OpenFin/backend/routers/risk.py
2026-07-23 22:04:02 +02:00

71 lines
2.1 KiB
Python

import math
from fastapi import APIRouter, Query
from services.database import (
get_portfolio_exposure,
get_pnl_timeline,
get_risk_clusters,
get_pattern_correlations,
compute_kelly_sizing,
get_risk_dashboard,
)
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."""
return get_portfolio_exposure()
@router.get("/timeline")
def pnl_timeline(days: int = Query(default=90, ge=7, le=365)):
"""Daily aggregated P&L timeline for equity curve."""
return {"timeline": get_pnl_timeline(days=days)}
@router.get("/clusters")
def risk_clusters():
"""Risk factor clustering + saturation detection + prompt context."""
return get_risk_clusters()
@router.get("/correlations")
def pattern_correlations():
"""Pearson correlation matrix between patterns (mature trades only)."""
return get_pattern_correlations()
@router.get("/kelly/{pattern_id}")
def kelly_sizing(
pattern_id: str,
capital: float = Query(default=10000.0, ge=100, le=10_000_000),
fractional: float = Query(default=0.33, ge=0.1, le=1.0),
):
"""Fractional Kelly position sizing for a pattern."""
return compute_kelly_sizing(pattern_id=pattern_id, capital_available=capital, fractional=fractional)
@router.get("/dashboard")
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())