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

@@ -363,6 +363,27 @@ export const useTogglePattern = () => {
})
}
export interface PatternCalibration {
pattern_id: string
pattern_name: string
asset_class: string
ai_estimate: number | null
observed_avg_win_pct: number | null
calibrated_expected_move: number | null
calibration_weight: number
calibration_weight_pct: number
n_mature_trades: number
bayes_win_rate: number
source: 'pure_ai' | 'early' | 'mixed' | 'data_driven'
}
export const usePatternCalibration = () =>
useQuery({
queryKey: ['pattern-calibration'],
queryFn: () => api.get('/patterns/calibration').then(r => r.data as PatternCalibration[]),
staleTime: 60_000,
})
export interface SimilarityResult {
recommendation: 'merge_as_instance' | 'counter_scenario' | 'new_pattern'
match_id: string | null