Commit Graph

30 Commits

Author SHA1 Message Date
OpenSquared
d8c0334feb feat: 50-signal macro engine — vol surface, sectors, EM, carry, long bonds
data_fetcher.py
- MACRO_GAUGE_CONFIG: 15 → 29 tickers (+silver, vvix, skew, ovx, gvz,
  usdjpy, xlk, xlf, xlp, xlu, eem, emb, fxi, tlt)
- 5 new derived metrics: silver_gold_ratio, xlk_xlp_momentum, xlf_spx_ratio,
  eem_spx_ratio, vol_surface_regime (composite classification)
- ThreadPoolExecutor max_workers raised to 20
- score_macro_scenarios: +15 new variables; each of 8 scenarios enriched
  with vol-surface (SKEW, VVIX), sector rotation (XLK, XLF, XLP, XLU),
  EM/carry (EEM, EMB, USDJPY), long bonds (TLT), silver signals

ai_analyzer.py
- macro_ctx: 5 → 21 fields per pattern (vol surface, sectors, EM, carry,
  long bonds, silver/gold ratio — all with interpretation comments)
- macro_section in scoring prompt: describes surface de vol regime, sector
  rotation, global/carry signals with explicit GPT instructions for pilier 3e
- DEFAULT_ANALYSIS_TEMPLATE: pilier 3e expanded with SKEW/VVIX/OVX/GVZ guidance

SIGNALS_FUTURES.md: reference document listing 30+ signals not yet
available (FRED, CFTC COT, EIA, Baltic Dry, LME, credit spreads,
hedge fund positioning, central bank balance sheets) with implementation
priority and cost estimate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 08:34:48 +02:00
OpenSquared
18b3ae6f91 feat: IBKR ticket in Dashboard + Journal MtM (Strike, DTE, legs)
Adds full Interactive Brokers order ticket to both the Dashboard cockpit
and the Journal de Bord MtM expanded rows. Each ticket shows the
underlying, computed strike in dollars, estimated expiry date (nearest
Friday), per-leg BUY/SELL CALL/PUT breakdown, order type LIMIT, budget
and target.

Also adds Strike and DTE columns to the MtM table and persists
strike_guidance + expiry_days_at_entry in trade_entry_prices.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:54:29 +02:00
OpenSquared
05a475fb04 feat: system logs page + dynamic IV watchlist with auto-add from cycle
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>
2026-06-18 13:07:35 +02:00
OpenSquared
3b4e035819 fix: IV rank fallback to history when live options fetch fails + Entrée date from cycle logs
- iv_engine/options_vol: when get_atm_iv() returns None (yfinance chain unavailable),
  fall back to most recent iv_history row so IV Rank is always computable from
  bootstrapped data; live vs history source tagged as iv_source field
- Dashboard: build mtmMap from tradeMtmData.trades (trade_entry_prices, cycle auto-log)
  keyed by pattern_id; getAddedInfo() falls back to mtmMap so Entrée/Durée columns
  populate automatically after each AI cycle without manual portfolio add
- OptionsLab: show '~' prefix and 'IV estimée' label when IV comes from history fallback;
  fix near-invisible text-slate-700 on 'Sans historique' section header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 11:55:57 +02:00
OpenSquared
592918c230 fix: default cockpit view to grid instead of cards 2026-06-18 11:15:02 +02:00
OpenSquared
be9834d70b fix: add Entrée date and Durée/maturité columns to Dashboard grid view 2026-06-18 10:58:01 +02:00
OpenSquared
cf45d9fb52 feat: add grid/table view with expandable rows to Dashboard cockpit
Toggle between Cards (existing) and Grid (new) via icons next to Top N.
Grid view: compact table with score bar, EV, gain, max/cible, profil,
macro bias per row. Click any row to expand inline (full-width) showing
score justification, contra-signals, macro context, and add button.
Added 'Tous' option (topN=0) to show all scored patterns without limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 10:49:22 +02:00
OpenSquared
fb78be49e5 fix: add journal_retention_days and maturity_threshold_pct to useUpdateCycleConfig type 2026-06-18 10:15:05 +02:00
OpenSquared
abee090881 feat: expandable inline rows in Journal + journal/maturity params in Config
- 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>
2026-06-18 10:08:16 +02:00
OpenSquared
8446876eb0 fix: add pnl_pct and capital_invested migration for trade_entry_prices
Both columns were referenced in queries (reliability, Kelly, calibration,
backtest) but missing from the ALTER TABLE migration block, causing
sqlite3.OperationalError: no such column: pnl_pct on existing VPS DBs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 21:52:50 +02:00
OpenSquared
97ba36454b fix: bootstrap IV history with 1y realized vol to unblock IV Rank from 50
IV Rank was stuck at 50 for all tickers because the formula returns 50.0
when iv_max == iv_min (not enough historical snapshots). Added:
- bootstrap_iv_history(): downloads 1y of closes per ticker, computes
  30d rolling realized vol (annualized), saves each day to iv_history
- POST /api/options-vol/bootstrap-history endpoint (runs in background)
- OptionsLab: auto-detect when IV Rank needs bootstrapping and show
  an amber banner with one-click "Initialiser historique" button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 21:33:01 +02:00
OpenSquared
7e38fd6257 fix: invalidate IV watchlist cache after cycle fetches fresh IV data
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>
2026-06-17 21:21:25 +02:00
OpenSquared
533e0f374b fix: AnalyticsAdvanced — import api from useApi (no local axios/import.meta.env) 2026-06-17 17:51:08 +02:00
OpenSquared
246deaf631 feat: Phase 4 — Moteur Probabiliste & Apprentissage Automatique
Sprint 4.1 — Bayesian Updating
- database.py: update_bayesian_posteriors() — Beta(α,β) posteriors sur trades matures
- database.py: get_bayesian_posteriors() — posteriors + IC 95% + dérive prior GPT vs posterior
- Colonnes Bayésiennes ajoutées : bayesian_alpha, bayesian_beta, bayesian_win_rate, bayesian_sample_size
- auto_cycle.py: appel update_bayesian_posteriors() en Step 5.5 (après scoring)

Sprint 4.2 — Détection Automatique de Régimes (K-Means numpy pur)
- database.py: detect_and_save_regime_clusters() — K-Means sur 7 gauges macro (VIX, slope, DXY…)
- database.py: get_regime_cluster_history() — timeline des clusters
- database.py: get_regime_transition_matrix() — P(cluster j | cluster i) sur N transitions
- Table regime_clusters avec anomaly_flag (points > 3σ)
- auto_cycle.py: appel detect_and_save_regime_clusters() en Step 5.6

Sprint 4.3 — Embeddings Sémantiques (remplace Jaccard)
- database.py: get_or_create_pattern_embedding() — OpenAI text-embedding-3-small, stocké en DB
- database.py: max_cosine_similarity_vs_existing() — similarité cosinus vs patterns existants
- Table pattern_embeddings avec vecteur JSON + model_version
- auto_cycle.py: _is_duplicate_pattern() — cosinus seuil 0.75 avec fallback Jaccard automatique

Sprint 4.4 — Tableau de Bord Analytique Avancé
- AnalyticsAdvanced.tsx: nouvelle page /analytics-advanced
  • BayesianTable : prior GPT vs WR bayésien ± IC 95%, dérive, niveau de confiance
  • ClusterTimeline : timeline colorée des clusters + anomalies
  • TransitionMatrix : heatmap P(j|i) avec diagonale auto-transition
  • EmbeddingsSummary : liste des patterns vectorisés
  • Boutons "Bayesian update" et "Détecter régime" avec mutation React Query
- analytics.py router : 5 nouveaux endpoints (bayesian, regime-clusters, transitions, detect, embeddings)
- useApi.ts : 4 nouveaux hooks (useBayesianPosteriors, useRegimeClusters, useRegimeTransitions, usePatternEmbeddings)
- App.tsx + Sidebar.tsx : route /analytics-advanced + entrée menu

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 17:46:34 +02:00
OpenSquared
e44c8799b9 feat: Phase 3 — Portfolio Risk Engine (Exposition, Clusters, Kelly, Risk Dashboard)
Sprint 3.1 — Vue Portefeuille Consolidée
- database.py: get_portfolio_exposure() — exposition par classe d'actif + facteur de risque
- database.py: get_pnl_timeline() — courbe P&L cumulé pour equity curve
- Alertes concentration automatiques (>40% par classe, >50% par facteur)
- _RISK_FACTOR_MAP: classification géopolitique/inflation/récession/liquidité/dollar

Sprint 3.2 — Risk Cluster Engine
- database.py: get_risk_clusters() — saturation par facteur + risk_prompt_context
- database.py: get_pattern_correlations() — matrice Pearson sur trades matures
- auto_cycle.py: injection du contexte risque dans le prompt de scoring (Step 3.5)
- ai_analyzer.py: paramètre risk_context dans score_patterns_with_context()
- Pénalisation automatique des patterns sur facteurs saturés dans le scoring GPT

Sprint 3.3 — Position Sizing Kelly Fractionnel
- database.py: compute_kelly_sizing() — f* = (p×G - (1-p))/G, Kelly ×33% par défaut
- Ajustement cluster: sizing ÷2 si facteur saturé
- Ajustement fiabilité: sizing ÷2 si win_rate historique <40% (≥5 trades)
- JournalDeBord.tsx: colonne "Kelly" avec KellyCell (% + €, ajustements signalés)
- routers/risk.py: GET /api/risk/kelly/{pattern_id}

Sprint 3.4 — Tableau de Bord Risque Global
- database.py: get_risk_dashboard() — HHI, score diversification, drawdown attendu, recommandation
- database.py: _build_risk_recommendation() — alerte Risk Committee automatique
- RiskDashboard.tsx: nouvelle page — jauges concentration, courbe P&L, corrélations, recommandation
- Dashboard.tsx: banner d'alerte concentration sur le Cockpit avec lien vers /risk
- routers/risk.py: GET /api/risk/exposure|timeline|clusters|correlations|dashboard
- App.tsx + Sidebar.tsx: route /risk + entrée menu Risk Dashboard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 17:18:36 +02:00
OpenSquared
f09c5b8ee7 feat: Phase 2 — Pattern Reliability, Contre-thèses & Calibration probabiliste
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>
2026-06-17 16:50:53 +02:00
OpenSquared
9a6b6f70b1 feat: Phase 1 — IV Rank, Term Structure, Skew, Options Flow (Sprint 1.1/1.2/1.3)
Backend:
- iv_engine.py: ATM IV, term structure (30/60/90/180j), put/call skew,
  options flow (P/C OI ratio, unusual strikes, gamma bias), proxy map for futures→ETFs
- database.py: iv_history table + save_iv_snapshot, get_iv_rank_percentile, get_iv_history
- routers/options_vol.py: /api/options-vol/ endpoints (snapshot, batch, watchlist, history)
- auto_cycle.py: inject IV context string into scoring prompt (step 3.5)
- ai_analyzer.py: score_patterns_with_context accepts iv_context param
- main.py: register options_vol router

Frontend:
- pages/OptionsLab.tsx: full IV dashboard (watchlist by IVR, term structure, skew, flow, sparkline)
- pages/JournalDeBord.tsx: IvRankCell component + IV Rank column per trade
- hooks/useApi.ts: useIvSnapshot, useIvWatchlist, useIvBatch, useIvHistory, useIvForTrade

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:29:33 +02:00
OpenSquared
07c1a74704 fix: save_config → set_config (correct function name in database.py) 2026-06-17 15:00:31 +02:00
OpenSquared
d726cf430e fix: VPS fresh-DB bootstrap — sync OPENAI_API_KEY from env to DB at startup + show countdown before first cycle
- main.py startup: if DB has no openai_api_key but OPENAI_API_KEY env var is set, auto-save it so cycle trigger returns 200 instead of 400
- Config.tsx: move NextRunCountdown outside cs?.last_cycle block so it renders even when no cycle has run yet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:55:42 +02:00
OpenSquared
9fe9a15939 fix: TS2322 onClick handler — wrap handleSynthesize in arrow function
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:38:32 +02:00
OpenSquared
dc3bc667eb fix: 3 bugs — synthesis crash, stale running cycle, invalid tickers
- knowledge.py: trade_line crash when pnl_pct is None in dict
  (t.get('pnl_pct',0) returns None if key exists with None value — use 'or 0')
- database.py: cleanup_stale_running_cycles() marks any 'running' cycle
  as 'error' on startup (uvicorn reload mid-cycle left status stuck)
- main.py: call cleanup_stale_running_cycles() at startup with warning log
- database.py: _normalize_ticker() converts GPT-4o exchange:symbol format
  (NSE:RELIANCE → RELIANCE.NS, BSE:X → X.BO, etc.) so yfinance stops
  spamming 404 errors for every MTM request

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 12:15:32 +02:00
OpenSquared
27d6b598e8 feat: next run countdown in auto-cycle config
- 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>
2026-06-17 12:02:50 +02:00
OpenSquared
3818544832 fix: auto_cycle — NameError 'meaningful' + Super Contexte bloqué par gate rapport
- 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>
2026-06-17 09:15:12 +02:00
OpenSquared
7b50a9b339 fix: KeyError 'stats' in cycle log line — use .get() defensively
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 08:43:10 +02:00
OpenSquared
a3fb486477 feat: delete AI reports, Super Contexte versions, and KB entries
- database.py: add delete_ai_report(), delete_reasoning_state(), delete_kb_entry()
- reasoning.py: DELETE /api/reasoning/reports/{id}
- knowledge.py: DELETE /api/knowledge/history/{id} and /entries/{id}
- useApi.ts: useDeleteAiReport, useDeleteReasoningState, useDeleteKbEntry hooks
- RapportIA.tsx: trash icon on hover in archived reports sidebar
- SuperContexte.tsx: trash icon on hover for history versions and KB entries;
  both propagate onDelete through CategorySection down to KbEntry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 00:10:41 +02:00
OpenSquared
22687dfd03 feat: time-aware Super Contexte synthesis
- knowledge.py: classify trades by maturity before building synthesis
  prompt; only mature trades (≥35% elapsed) contribute to P&L stats
  and conclusions; immature trades listed for transparency only
- Add 6h staleness gate on POST /synthesize (force=true to override)
- System prompt now includes hard timing rule: GPT-4o must not revise
  existing conclusions because of newly-added immature trades
- useApi.ts: useSynthesizeKnowledge accepts force boolean param
- SuperContexte.tsx: shows amber notice with age when skipped + offers
  "Force quand même" button; success banner uses new response shape

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 23:57:46 +02:00
OpenSquared
9075762dd5 feat: time-aware trade maturity classification
- Add _trade_maturity() helper: classifies trades by % of horizon elapsed
  (trop_tot <10%, debut 10-35%, mature 35-75%, fin_horizon >75%)
- Fix horizon_days fallback chain in log_trade_entries (default 30→90)
- journal.py: enrich each MTM trade with maturity dict + horizon_days
- reasoning.py: portfolio report segments trades by maturity; GPT-4o
  draws lessons only from matures (≥35% elapsed), never from trop_tot
- auto_cycle.py: 90d window, maturity-aware prompt with timing rules
- JournalDeBord.tsx: maturity badge with emoji, label, progress bar
  and day counter (Xj / Yj Z%) replacing plain days_held column

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 23:49:33 +02:00
OpenSquared
4bbcd7a3a6 feat: score justification on trade cards
- Add ScorePillars: compact 4-pillar mini-bars always visible under score
  bar (📰/📅/📈/⚖️ with color-coded fill — instant visual of pillar distribution)
- Add ScoreJustification: replaces old per-click BucketBreakdown with full
  text reasoning shown at once — key_catalyst highlighted in yellow callout,
  each pillar shows score + GPT-4o comment + all sub-pillars with comments
- Rename expand button to "↳ Justification du score" for clarity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 22:05:51 +02:00
OpenSquared
929283045f fix: score differentiation + auto Super Contexte synthesis
- 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>
2026-06-16 20:43:48 +02:00
OpenSquared
d256b65d30 Initial commit — GeoOptions Intelligence Cockpit v2.0
Stack: FastAPI + React/TypeScript + SQLite + GPT-4o
Features: Radar géopolitique, Marchés, Régime Macro, Journal de Bord MTM,
Rapport IA, Super Contexte (base de raisonnement évolutive), Boucle feedback IA.
Deploy: Docker + docker-compose + nginx pour openfin.open-squared.tech

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:29:59 +02:00