from fastapi import APIRouter, Query from services.database import ( get_pattern_reliability, get_all_pattern_reliability_map, get_calibration_data, decay_kb_confidence, get_custom_patterns, ) router = APIRouter(prefix="/api/analytics", tags=["analytics"]) @router.get("/reliability") def reliability_all(): """Pattern reliability scores — all patterns with mature trade history.""" return {"reliability": get_pattern_reliability()} @router.get("/reliability/{pattern_id}") def reliability_one(pattern_id: str): result = get_pattern_reliability(pattern_id=pattern_id) if not result: return {"reliability": None} return {"reliability": result[0]} @router.get("/calibration") def calibration(days: int = Query(default=365, ge=30, le=1000)): """Predicted probability vs realized outcomes (Brier score + buckets).""" return get_calibration_data(days=days) @router.post("/kb/decay") def run_kb_decay(): """Manually trigger KB confidence decay (also runs at cycle start).""" updated = decay_kb_confidence() return {"updated": updated, "message": f"{updated} entrée(s) KB mise(s) à jour"} @router.get("/invalidation-alerts") def invalidation_alerts(): """List all active patterns that have an invalidation trigger defined.""" patterns = get_custom_patterns() alerts = [ { "pattern_id": p["id"], "pattern_name": p["name"], "invalidation_trigger": p.get("invalidation_trigger"), "invalidation_probability": p.get("invalidation_probability"), "counter_thesis": p.get("counter_thesis"), } for p in patterns if p.get("invalidation_trigger") ] return {"alerts": alerts, "count": len(alerts)}