- Backend: get_status() now resolves scoring_run_id by querying
trade_entry_prices within the cycle time window, fixing the mismatch
between cycle run_id and the id actually written to trades
- Dashboard: Trades du cycle filters by scoring_run_id (no stale fallback)
- Dashboard: Pattern du cycle shows only patterns added in last cycle
(created_at >= started_at), renamed from Top Patterns
- Dashboard: Dernier Cycle now shows 4 stats (patterns/scorés/loggés/fermés)
+ IA commentary snippet
- Dashboard: P&L simulated mode bottom half shows open/closed/capital/profit
- Dashboard: Régime Macro shows top 4 scenario score bars
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auto_cycle.py: replace _log with logger (NameError at lines 484/489)
- auto_cycle.py: normalize underlying via _normalize_ticker before _resolve_ticker
so WHEAT→ZW=F→WEAT and EUR/USD→EURUSD=X→FXE reach the IV watchlist correctly
- iv_engine.py: _resolve_ticker now strips slash-format forex (EUR/USD→EURUSD=X)
before _PROXY lookup, fixing yfinance 500/404 spam from get_atm_iv
- database.py: _fetch in log_trade_entries uses _normalize_ticker (not _normalize_yf_ticker)
so commodity aliases like WHEAT→ZW=F are applied at price-fetch time
- ai_analyzer.py: max_workers=1 for batch scorer — parallel workers both slept and
retried simultaneously after 429, causing repeated bursts; sequential fixes the pattern
- journal.py + JournalDeBord.tsx: add price_warning field (no_price_data/no_entry_price/
no_live_price) with visible ⚠ badge and amber color on affected ticker/price cells
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- DB: add system_logs table (level/source/cycle_id/ticker/message) and
iv_watchlist table (ticker/added_by/is_active); seed builtin 18 tickers
- DBLogHandler attached at startup — all WARNING+ logs auto-persist to DB
- log_system_event() helper for structured manual events
- New router /api/logs: GET with filters (level, source, cycle_id, ticker,
date range), GET /sources, GET /cycles for dropdowns, DELETE /clear
- iv_watchlist now read from DB instead of hardcoded constant; options_vol
watchlist/refresh/bootstrap endpoints all use get_watchlist_tickers()
- New endpoints: POST/DELETE /options-vol/watchlist-tickers/{ticker} to
add/remove tickers; adding triggers background 1-year bootstrap
- auto_cycle: after log_trade_entries(), auto-detect new underlying proxies
not yet in watchlist, add them and bootstrap their IV history
Frontend:
- New page SystemLogs (/logs): log table with level/source/cycle/ticker/date
filters, color-coded rows, expandable JSON details, auto-refresh 30s
- Options Lab: WatchlistManager section — add ticker input, chip list with
builtin/auto/manual color coding, remove button for non-builtins
- Sidebar: Logs Système nav link (ScrollText icon)
- useApi: useSystemLogs, useLogSources, useLogCycles, useClearLogs,
useWatchlistTickers, useAddWatchlistTicker, useRemoveWatchlistTicker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- JournalDeBord: trade rows now expand inline (full-width) instead of
PostmortemPanel appearing below the whole table. Click anywhere on a
row to toggle. Period selector extended to 15/30/60/90j.
- Config: added Rétention Journal (30/60/90/180j) and Seuil Maturité
(20/30/35/50%) controls, wired to the Appliquer button.
- Backend: journal_retention_days and maturity_threshold_pct read from
config table; seeded at startup with defaults 90d / 35%. get_status()
now returns both values so Config page can initialise correctly.
- cycle.py: CycleConfigRequest accepts and validates both new params.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The auto-cycle was saving new IV snapshots to SQLite but not clearing
the in-memory cache in options_vol.py (TTL 1h), so the Options Lab
page kept showing stale IV Rank data until the cache naturally expired.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sprint 2.1 — Pattern Reliability Score
- database.py: get_pattern_reliability() — win_rate × log(n+1) sur trades matures (≥35% horizon)
- database.py: get_all_pattern_reliability_map() pour injection rapide dans les prompts
- ai_analyzer.py: inject reliability_map dans suggest_patterns (patterns fiables mis en avant)
- auto_cycle.py: charge reliability_map avant suggestion et le passe au suggéreur
- routers/analytics.py: GET /api/analytics/reliability
- PatternEditor.tsx: ReliabilityBadge sur chaque card + usePatternReliability hook
- useApi.ts: usePatternReliability, useCalibration hooks
Sprint 2.2 — Contre-thèses & Invalidation Triggers
- database.py: migration ALTER TABLE — counter_thesis, invalidation_trigger, invalidation_probability
- database.py: save_custom_pattern() persiste les 3 nouveaux champs
- ai_analyzer.py: counter_thesis + invalidation_trigger + invalidation_probability dans le JSON schema
- auto_cycle.py: détection automatique des triggers d'invalidation contre les news (keyword match)
- routers/analytics.py: GET /api/analytics/invalidation-alerts
- PatternEditor.tsx: affichage contre-thèse dans les cards + champs dans le formulaire
- PatternEditor.tsx: affichage dans AiSuggestModal (suggestions IA)
- routers/patterns.py: PatternRequest inclut les 3 nouveaux champs
Sprint 2.3 — Calibration probabiliste & Demi-vie KB
- database.py: migration — predicted_probability sur pattern_score_history
- database.py: save_pattern_scores() stocke probability du pattern à chaque scoring run
- database.py: get_calibration_data() — Brier score + buckets de calibration par décile
- database.py: expires_at + confidence_decay_days sur knowledge_base
- database.py: decay_kb_confidence() — decay automatique + archivage à 0
- auto_cycle.py: decay_kb_confidence() appelé au début de chaque cycle (non-bloquant)
- routers/analytics.py: GET /api/analytics/calibration + POST /api/analytics/kb/decay
- frontend/src/pages/Analytics.tsx: nouvelle page — tableau fiabilité + calibration Brier
- App.tsx + Sidebar.tsx: route /analytics + entrée menu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auto_cycle.py: next_run_at now set to future timestamp (now + interval)
instead of current time — was always showing wrong value
- Config.tsx: NextRunCountdown component shows live countdown (updates
every second) + absolute local time, only visible when auto-cycle enabled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix NameError: len(meaningful) → len(meaningful_mature) (ligne 624)
- _auto_synthesize_knowledge() appelé même si pas assez de trades matures,
pour que le Super Contexte se mette à jour à chaque cycle (gate 6h suffit)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ai_analyzer: add explicit calibration rules to SYSTEM_SCORER and batch
prompt so GPT-4o produces a spread of scores rather than defaulting
to 50 for all patterns (0-news patterns capped at 35, contra patterns
at 40, high-signal patterns can reach 70-85)
- auto_cycle: add _auto_synthesize_knowledge() called after each auto
portfolio snapshot; skips if last synthesis < 6h old to avoid
redundant GPT-4o calls — Super Contexte now updates automatically
every cycle without manual intervention
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>