feat: pattern calibration — progressive AI→observed expected_move blending

DB (database.py):
- 3 new columns on custom_patterns: calibrated_expected_move, calibration_weight, observed_avg_win_pct
- update_bayesian_posteriors() now also computes credibility blend w=n/(n+5):
  calibrated = (1-w)*ai_estimate + w*observed_avg_win_pct (only when wins exist)
- log_trade_entries() prefers calibrated_expected_move when w>10%
- get_calibration_summary() returns per-pattern state (source: pure_ai/early/mixed/data_driven)

Backend (patterns.py, auto_cycle.py):
- GET /api/patterns/calibration endpoint
- calibration_report block in cycle report: counts by source, avg weight, per-pattern detail

Frontend (PatternExplorer.tsx, RapportIA.tsx, useApi.ts):
- MaturityBadge on each PatternCard: blend bar (AI→observed), win rate, AI estimate vs calibrated
- usePatternCalibration hook
- Cycle report: calibration section with global bar + per-pattern table (weight%, n_trades, WR, AI→calibrated)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-23 12:38:16 +02:00
parent a630cdc708
commit 91f12e177f
6 changed files with 327 additions and 17 deletions

View File

@@ -5,7 +5,7 @@ from pydantic import BaseModel
from typing import Optional, List, Dict, Any
from services.database import (
save_custom_pattern, get_custom_patterns, delete_custom_pattern, toggle_pattern_active,
get_config,
get_config, get_calibration_summary,
)
from services.geo_analyzer import PATTERN_TAXONOMY
@@ -141,6 +141,14 @@ def get_by_instrument(ticker: str = Query(..., description="Ticker / underlying
return result
# ── Calibration summary ───────────────────────────────────────────────────────
@router.get("/calibration")
def get_calibration():
"""Per-pattern calibration state: AI estimate vs observed blend."""
return get_calibration_summary()
# ── Find Similar ──────────────────────────────────────────────────────────────
class FindSimilarRequest(BaseModel):