Commit Graph

69 Commits

Author SHA1 Message Date
OpenSquared
ad07c8d886 feat: new cockpit 2026-07-14 11:21:43 +02:00
OpenSquared
e1681edffc feat: causal lab 2026-07-01 21:01:00 +02:00
OpenSquared
8b59eff744 feat: macro series 2026-07-01 16:16:51 +02:00
OpenSquared
292d2c6413 feat: bank forceasts 2026-06-30 21:47:20 +02:00
OpenSquared
bb614936c3 feat: macro series 2026-06-30 19:08:33 +02:00
OpenSquared
551ebc3ef4 feat: desk ia 2026-06-29 19:50:18 +02:00
OpenSquared
f7acca2152 feat: desk ia 2026-06-29 17:16:57 +02:00
OpenSquared
69418ab650 feat: desk ia 2026-06-29 15:45:21 +02:00
OpenSquared
c286c7c000 feat: desk IA 2026-06-28 17:14:40 +02:00
OpenSquared
e4e17330b4 feat: instrument analysis 2026-06-28 16:36:28 +02:00
OpenSquared
afbfeff468 feat: FF→FRED series mapping + MacroSeries visualization page
Backend:
- ff_calendar: add series_id column (migration) + FF_TO_FRED mapping dict
  (NFP→PAYEMS, CPI→CPIAUCSL, Jobless Claims→ICSA, GDP→GDPC1, FEDFUNDS, PCE)
- import_csv + sync_live now populate series_id on each FF event
- New GET /api/eco/series/{id}/history: FRED time series + linked FF events
  (surprises, forecast, actual) merged by date — enables context queries

Frontend:
- New MacroSeriesPage.tsx: sidebar with 11 FRED series grouped by category,
  recharts ComposedChart with area + z-score surprise reference lines (|z|≥1.5),
  KPI cards (latest/prev/min/max), FF events table (actual vs forecast coloring),
  z-score bar chart for recent surprises, range selector (1Y/2Y/5Y/10Y/All)
- Route /macro-series + Sidebar entry "Macro Series"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 16:51:55 +02:00
OpenSquared
4053e0669d feat: Forex Factory calendar — unified past+future list style Trading Economics
- New ff_calendar table (event_date, time, currency, impact, actual, forecast, previous)
- New service ff_calendar.py: bulk CSV import (83K events 2007-2025) + live sync
  from faireconomy.media JSON endpoint (this week / next week)
- New API endpoints: POST /api/eco/ff-import, POST /api/eco/ff-sync,
  GET /api/eco/calendar (period filter), GET /api/eco/ff-stats
- CalendarPage.tsx full rewrite: period tabs (Recent/Today/Tomorrow/This Week…),
  currency flags filter, impact filter, unified date-grouped table with
  Time·Flag·Currency·Impact·Event·Actual·Forecast·Previous columns,
  green/red actual vs forecast, TODAY badge, auto-refresh 60s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 16:32:26 +02:00
OpenSquared
325d52b3b9 feat: market events db migration + generation date filter
Database migration:
- Add 'origin' and 'source_refs' columns to market_events ALTER TABLE migration
  (sub_type/actual_value/expected_value/surprise_pct were already there)
- All new tables (macro_gauge_snapshots, ai_desks) created via CREATE TABLE IF NOT EXISTS
  on next init_db() call (container restart)

Backend:
- GET /api/market-events/db-status — health check returning row counts,
  latest dates, and missing columns for all 6 tables needed by the detector
- list_events() now accepts gen_date_from / gen_date_to query params
  filtering by date(created_at) — separate from start_date event date filters

Frontend (MarketEvents.tsx):
- MarketEvent interface: add created_at field
- EventRow: show generation date as MM-DD next to event date
- Extended filters: new ' Date de génération' section with from/to inputs
  filtered independently from the event date range
- Clear-all button includes genFrom/genTo reset

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 14:23:09 +02:00
OpenSquared
27ee4410cf refactor: separate Sentiment and Technical desks — no signal overlap
- Mark 6 price signals (ma_cross, rsi_extreme, bb_squeeze, new_52w_extreme, price_gap, volume_spike) as desk_type=technical so they no longer appear in the Sentiment desk
- Sentiment desk now shows MacroGaugeSelector (32 gauges grouped by bloc: Liquidité, Crédit, Volatilité, Métaux…) instead of the stock/ETF instrument picker
- Sentiment desk instruments seed updated to macro gauge keys (vix, vvix, skew, hyg, dxy, slope_10y3m, gold_copper_ratio)
- Signal init useEffect extended to cover sentiment desk as well as technical

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 13:48:14 +02:00
OpenSquared
85eb864584 feat: macro gauge DB + regime triggers + date-aware instrument snapshot
DB:
- New table macro_gauge_snapshots (daily snapshot of all 28+ gauges + dominant + scores)
- save_macro_gauge_snapshot / get_macro_gauge_snapshot_at / get_macro_gauge_history
- Auto-save once per calendar day on every macro-regime fetch (not just force=True)

API:
- GET /api/market/macro-gauges/at?date=YYYY-MM-DD — nearest snapshot ≤ date
- GET /api/market/macro-gauges/history?days=N

Detector (_check_macro_gauges in Eco Desk):
- Regime transition events (goldilocks→stagflation etc.) with severity scoring
- Yield curve inversion / désinversion (slope_10y3m sign change)
- DXY shock (% change over lookback window)
- Credit stress (HYG drop threshold)
- Gold/Copper ratio regime crossings

InstrumentDashboard:
- macroAtDate state: fetches /api/market/macro-gauges/at when crosshair date ≠ last date
- RegimeCard uses historical macro regime when on a past date
- MacroGaugePanel: full breakdown of all gauges by bloc (liquidité, crédit, énergie...)
  visible only when on a historical date — shows value + change_pct + regime scores bar

AIDesks: added fundamental + sentiment to AIDesk type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 09:34:35 +02:00
OpenSquared
a12d7a1ef3 feat: 6 AI desks complets — fundamental, report, sentiment (options triggers)
- Fundamental Desk: filtre corporate news (layoffs, M&A, earnings, credit)
  avec prompt dédié + dedup sémantique
- Report Desk: wiring desk config (days, min_importance, system_prompt)
- Sentiment Desk: 5 signaux VIX/SKEW pour options lab
  (vix_level thresholds, vix_spike %, vix_term_structure, vvix_extreme, skew_extreme)
  Chaque event contient options_note actionnable (vente puts, straddles, calendar spreads)
- check_new_market_events() couvre les 6 sources, charge desk configs dynamiquement
- Signal catalog: 12 signaux (7 technical + 5 sentiment), filtrés par desk_type dans UI
- AIDesks.tsx: FundamentalConfig + ReportConfig + SignalToggle filtré par desk type
- 3 nouveaux desks seedés dans init_db (idempotent)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 09:21:29 +02:00
OpenSquared
97706dea7b feat: AI Desks — configurable agent system for news/technical/eco processing
- New ai_desks table with CRUD (get_all/by_type/upsert/delete)
- ai_desks router: REST API + GET /signal-catalog (7 extensible signals)
- News Desk: semantic dedup via AI (±N days window, system_prompt hint)
- Technical Desk: 4 signal detectors driven by desk config
  (ma_cross, rsi_extreme, bb_squeeze, new_52w_extreme)
- 3 more signals in catalog ready to enable: price_gap, volume_spike, macd_crossover
- market_event_detector.py loads desk configs at runtime, falls back to legacy params
- AIDesks.tsx: full editor UI with signal toggles, param sliders, instrument multi-select
- Sidebar: Bot icon + /ai-desks route

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 23:08:14 +02:00
OpenSquared
06a27e4492 fix: add sub_type to update_market_event SQL — was silently dropped
The UPDATE statement listed all columns except sub_type, so the
AI-matched category auto-set was written to the object but never
persisted to the DB. The category dropdown stayed blank after evaluate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 22:18:09 +02:00
OpenSquared
0b1fcff49c feat: Market Events — catégories, cleanup sidebar, rename
- Supprime Timeline & ImpactMonitor du routing (redirects /impact + /timeline → /market-events)
- Renomme 'Instrument Snap.' → 'Instrument Analysis' dans la sidebar
- Onglet 'Catégories & Defaults' dans Market Events: CRUD complet (créer/éditer/supprimer)
  chaque catégorie a une table d'impacts par défaut (instrument, sensibilité, direction, notes)
- impact_service: meilleur matching catégorie (sub_type fuzzy + type fallback)
- DB: delete_event_category() + DELETE /api/impact/categories/{name}

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 21:11:24 +02:00
OpenSquared
bd28b6a73a feat: origin tracing on all market_events
- DB: colonne origin (migration + UPDATE heuristique sur données legacy)
- save/update_market_event: persist origin
- Tous les points de création taguent leur origine:
    bootstrap_macro/eco/ma/legacy | detector_news/eco/technical/report | manual
- UI MarketEvents: badge d'origine avec icône + description dans le panneau détail,
  icône tooltip dans la liste gauche, message explicite si pas de source_refs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 20:58:05 +02:00
OpenSquared
d5da4737ef feat: Market Events admin page — source_refs + per-instrument impacts
- DB: colonne source_refs sur market_events (migration idempotente)
- save/update_market_event: persist source_refs (JSON array de {url,title,source})
- market_event_detector: stocke source_refs + évalue impacts instruments après chaque création
- Nouveau router /api/market-events: CRUD + evaluate + impacts CRUD
- Page MarketEvents.tsx: liste filtrée/triée + panneau détail (sources cliquables,
  tableau impacts par instrument avec score/direction/rationale inline-éditables,
  ajout manuel, bulk-evaluate)
- Sidebar: entrée Market Events (Radio icon)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 18:29:09 +02:00
OpenSquared
51a5531454 refactor: align market_events categories with driver types + event stars on chart
- database.py: idempotent migration — calendar→event_calendar, geopolitique→geopolitical,
  macro events classified by name pattern (FOMC/CPI/BOJ/OPEC+→event_calendar,
  NVIDIA→report, rest→fundamental)
- eco_calendar_bootstrap.py: calendar→event_calendar (75 events)
- macro_events_bootstrap.py: all 30 events now carry aligned category + sub_type
  (FOMC×9, CPI×3, BOJ×3, OPEC+×2 → event_calendar ; war/geo×6 → geopolitical ;
   ChatGPT/BTC/PBOC → fundamental ; NVIDIA×2 → report)
- InstrumentDashboard: replace EventTimelineStrip (horizontal bars below chart)
  with EventStarsStrip (★ icons above chart, sized by impact_score, colored by category)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 17:01:07 +02:00
OpenSquared
a68896cf67 feat: Impact Monitor — AI impact evaluation for eco events & geopolitical news
- New DB tables: event_categories (18 bootstrap categories) + instrument_impacts
- impact_categories_bootstrap.py: FOMC/NFP/CPI/GDP/PCE/ISM/BOJ/ECB/BOE/OPEC+ + 7 géopolitical categories with per-instrument sensitivity & direction defaults
- impact_service.py: GPT-4o-mini evaluation (0-1 score, direction, rationale) + monitor data aggregation
- routers/impact.py: GET/POST endpoints for evaluate/bulk/monitor/adjust/categories
- ImpactMonitor.tsx: two-tab page (Évalués / À évaluer), top instruments bar, inline score override modal, category browser
- Startup auto-bootstrap for impact categories
- Route /impact + sidebar nav entry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:26:13 +02:00
OpenSquared
3470205d54 feat: eco calendar bootstrap + driver types + timeline cursor
Backend:
- eco_calendar_bootstrap.py: 75 historical events 2020-2026 (FOMC, NFP,
  CPI, GDP, ISM, BOJ, ECB, BOE) with expected_value/actual_value/
  surprise_pct/unit/absorption_pct fields
- database.py: 5 new columns on market_events (expected_value,
  actual_value, surprise_pct, unit, sub_type) + updated save_market_event
- timeline.py: POST /api/timeline/bootstrap-eco endpoint
- instrument_service.py: _get_relevant_events now returns eco fields
- instruments.json: type field on all 90 drivers across 20 instruments
  (event_calendar | report | geopolitical | fundamental | sentiment | technical)

Frontend (InstrumentDashboard):
- EventTimelineStrip: vertical cursor line tracking crosshair selectedDate
- EventsCard: active-event highlight at hovered date + expected/actual/
  surprise_pct display + absorption progress bar
- DriversPanel: type selector dropdown per driver
- DriverTypeBadge: colored micro-badge on driver labels in strip

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 00:07:41 +02:00
OpenSquared
aeb5233deb feat: frise sub-lanes + event manager + MA indicators + absorption
Frise chronologique:
- Sub-lane stacking (assignSubLanes) — overlapping events se décalent verticalement
- Zone d'overlap semi-transparente sur la période commune entre 2 événements
- Hauteur dynamique selon nb de sub-lanes par niveau
- Événements en cours avec flèche ▶ à droite, gradient de fin
- Tri par start_date pour placement greedy

Event Manager (composant EventManager.tsx):
- Tableau filtrable par niveau (Long/Moyen/Court)
- Edit modal complet : tous les champs + absorption_pct éditable
- Bouton "IA — Enrichir" par événement → POST /api/timeline/events/{id}/ai-enrich
  → GPT-4o-mini suggère absorption_pct + indicateurs pertinents par niveau temporel
- Delete avec confirmation double-clic
- Expand row pour voir description + indicateurs
- Intégré Timeline page via bouton "Gérer événements"

Backend:
- Nouvelles colonnes market_events: absorption_pct + relevant_indicators (ALTER idempotent)
- DELETE /api/timeline/events/{id}
- POST /api/timeline/events/{id}/ai-enrich

Snapshot Externe:
- AbsorptionBar par événement dans cellule Géopolitique
- MA indicators : fetch 200j history, compute MA10/MA20/MA100 per level (short/med/long)
- Affichage prix vs MA + % écart dans CellMarkets
- Si relevant_indicators configurés sur l'event → utilise ces symbols au lieu des défauts
- Calendar : horizons exclusifs (short 0-7j, medium 8-30j, long 31-90j) — bug corrigé

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 20:31:57 +02:00
OpenSquared
c6178c14d5 feat: Timeline Navigator — contexte historique 3 temporalités COVID → aujourd'hui
- 2 nouvelles tables SQLite : market_events + timeline_context
- 32 événements historiques seedés (long/medium/short de feb 2020 à juin 2026)
- timeline_service.py : bootstrap, get_events_for_date, génération commentaires GPT-4o-mini
- /api/timeline router : GET /day/{date}, GET /events, POST /generate/{date}, POST /bootstrap
- Timeline.tsx : navigateur date avec strip visuel, 3 panneaux contextuels, catalogue d'événements
- Sidebar : entrée Timeline avec icône Layers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 17:45:35 +02:00
OpenSquared
5005324653 fix: SQLite UNIQUE constraint on forward_curve_data — expressions not allowed
Replace UNIQUE(asset, DATE(fetched_at)) with dedicated fetch_date column
+ UNIQUE(asset, fetch_date). SQLite prohibits function calls in inline
UNIQUE/PRIMARY KEY constraints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 18:07:29 +02:00
OpenSquared
3b7fa35456 feat: Specialist Desks v2 — COT, Forward Curves, Surprise Index, Hawk/Dove scorer
- COT Positioning: CFTC disaggregated + financial futures (19 markets) via Socrata free API
  net MM position % OI + weekly change stored in cot_data table
- Forward Curves: yfinance front-month vs +3M slope (8 commodities)
  contango/backwardation/flat stored in forward_curve_data table
- Surprise Index: consensus_estimate + actual_value on specialist_reports
  auto-computes surprise_score = actual - consensus on save
- Hawk/Dove Text Scorer: GPT-4o-mini endpoint for CB statements
  score -1..+1, label, summary, key_phrases (forex/bonds: hawk/dove; commodities: bull/bear)
- AI context injection: COT net positioning, forward curve structure,
  surprise scores, upcoming consensus estimates injected into all desk blocks
- Frontend: COT panel (net% bars), Forward Curves panel, SurpriseInput
  on report cards, Hawk/Dove scorer in forex/bonds config tab
- auto_cycle.py: non-blocking COT + curve refresh before each cycle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 18:00:46 +02:00
OpenSquared
91f12e177f 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>
2026-06-23 12:38:16 +02:00
OpenSquared
2fb683eec5 feat: Specialist Desks — per asset-class fundamental configs + report catalogue
- 7 pre-seeded desks (Forex, Metals, Agri, Energy, Indices, Crypto, Bonds)
  each with default fundamental drivers, macro regime sensitivities and
  price delta thresholds
- Global report catalogue (specialist_reports) fully manual — add any report
  including non-calendar ones (e.g. Cocoa Grinding Report, ICCO)
- Many-to-many report ↔ desk linking (report_desk_links table)
- 12 default reports pre-seeded (COT, EIA, WASDE, FOMC, ECB, CPI, NFP…)
- AI scorer injects SPECIALIST DESK context block for asset classes present
  in each scoring batch (upcoming reports, key drivers, regime sensitivity)
- /specialist-desks page: desk sidebar + fundamentals editor + macro
  sensitivity tag editor + reports tab + global reports catalogue + modal
  to create/edit any report with desk assignment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 09:57:18 +02:00
OpenSquared
33097e1812 fix: custom tickers now placed in their natural asset-class tab
- Detect yfinance quote_type (CURRENCY→forex, FUTURE→energy, INDEX→indices,
  ETF→etfs, EQUITY→equities) when adding a custom ticker and persist it in
  market_watchlist.asset_class
- get_all_quotes() merges custom tickers into their proper group (e.g. EURUSD=X
  appears under Forex) instead of always under a separate "Custom" group
- "Custom" tab only shows tickers whose type couldn't be detected
- Add market_watchlist.asset_class migration; ensure backtest_lab_runs and
  market_watchlist are always created at init_db() time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 22:11:31 +02:00
OpenSquared
c3ea0b7f8c feat: dynamic market ticker watchlist (Markets page)
Add ability to add/remove custom tickers (e.g. EURCHF=X) on the
Markets & Prices page without editing config. Tickers are validated
via yfinance, persisted in market_watchlist SQLite table, merged into
the quotes feed as a 'custom' group, and shown in a dedicated tab
with per-card remove buttons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 21:54:58 +02:00
OpenSquared
a435c11246 feat: regime system — Find Matching + By Regime view
- Pattern Lab: "Find Matching" button per pattern uses GPT-4o-mini to classify against library (merge_as_instance / counter_scenario / new_pattern); shows match badge + confidence + suggested #regime_tag; conditional action buttons (Merge / Save counter / Save new)
- save_pattern_from_run handles action='instance' (appends to historical_instances + updates stats), action='counter' (new pattern with counter_of link, tags parent regime_tag), action='new' (unchanged + regime_tag support)
- useApi.ts: extended useSaveLabPattern type + new useFindMatchingPattern mutation + MatchResult export type
- DB migrations: regime_tag + counter_of columns on custom_patterns
- PatternExplorer: new "By Regime" view groups saved patterns by regime_tag; RegimeCard shows historical instances, hit rate, counter-of link (orange); untagged group at bottom

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 20:52:11 +02:00
OpenSquared
cbf989502c feat: Pattern Lab — historical backtest engine for pattern discovery
- Remove all built-in patterns (no proof of legitimacy); seed_builtin_patterns is now a no-op
- DB: add backtest_lab_runs table + backtest_hits/runs_count columns on patterns
- services/pattern_lab.py: build_historical_context (yfinance + RSI/MA200),
  run_ai_backtest (GPT-4o as historical analyst), evaluate_outcomes (actual moves at T+horizon)
- routers/pattern_lab.py: POST /run, POST /evaluate/{id}, GET /runs, DELETE /runs/{id},
  POST /save-pattern (promotes hit pattern to library with reliability counters)
- PatternLab.tsx: 34 preset events 2015-2025 (macro/geo/credit/fx/commodities/volatility/tech),
  3-panel layout — preset selector + wizard + run history, market data table,
  AI pattern cards with hit/miss outcome display, Save to Library button
- useApi.ts: usePatternLabRuns, useRunPatternLab, useEvaluatePatternLab, useSaveLabPattern, useDeleteLabRun
- Sidebar + App.tsx: /pattern-lab route + FlaskConical nav link

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 17:55:48 +02:00
OpenSquared
a68a08d9af feat: trade mandate (budget + horizon) wired end-to-end
- database.py: add trade_budget_eur / preferred_horizon_min/max config
  defaults and include them in cycle config migrations
- auto_cycle.py: read trade params from config and inject into cycle_meta
- ai_analyzer.py: inject INVESTOR TRADE MANDATE block into scoring and
  suggestion prompts so GPT-4o penalises horizon mismatches and sizes
  within the capital cap
- Config.tsx: Trade Parameters card with budget + horizon sliders and live
  mandate summary
- TradeIdeas.tsx: horizon filter pills (< 1M / 1-3M / 3-6M / > 6M) and
  budget/horizon indicator pulled from saved config
- useApi.ts: extend useUpdateCycleConfig type with new config fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 17:24:38 +02:00
OpenSquared
9b98594c07 fix: 3 bugs from system logs — timedelta, scoring IndexError, lxml
- database.py: add timedelta to datetime import (used in
  get_recent_economic_surprises, was raising NameError)
- ai_analyzer.py: scoring split was searching French string
  'Retourne UNIQUEMENT ce JSON valide:' but prompt is now in English
  'Return ONLY this valid JSON:' — caused IndexError crashing every cycle
- requirements.txt: add lxml>=5.0.0 (yfinance earnings_dates dependency,
  was silently failing all 23 ticker fetches every hour)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 17:11:23 +02:00
OpenSquared
10ffc345d6 feat: Pattern Explorer — taxonomy tree + 23 historical patterns + instrument lens
- PatternExplorer.tsx: new page with two views:
    • Tree View — 6-root taxonomy (geopolitical, monetary_policy, economic,
      commodity, risk_off, market_structure) with collapsible sub-nodes;
      pattern cards appear on node selection
    • Instrument Lens — search any ticker (e.g. GLD, FXE) to see every
      pattern + scenario that references it, with matching trades highlighted
- geo_analyzer.py: PATTERN_TAXONOMY tree constant + taxonomy_path on all
  patterns; 15 new documented patterns P009-P023 (BoJ YCC, SVB crisis,
  Taiwan semis, OPEC cuts, Fed pivot, Debt ceiling, Iran nuclear, DPRK,
  VIX backwardation, ECB surprise, Extreme Fear contrarian, S. China Sea,
  European energy, CPI hot print, Flash crash)
- patterns.py: GET /api/patterns/taxonomy, GET /api/patterns/by-instrument
- database.py: taxonomy_path migration + seed_builtin_patterns updates path
- App.tsx: /patterns → PatternExplorer, /patterns/edit → PatternEditor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 16:42:45 +02:00
OpenSquared
d178615c74 feat: Phase 2 — economic event surprise tracker (FRED actuals + z-score)
- economic_events table in DB (series_id, actual, forecast_baseline, surprise_pct, surprise_zscore, direction)
- DB helpers: save_economic_event(), get_recent_economic_surprises(), get_economic_events_for_calendar()
- fred_fetcher.py: _compute_zscore_surprise() computes 12-period MA as implied consensus + z-score deviation; save_fred_releases_to_db() persists releases per cycle; build_economic_surprise_block() formats significant surprises for AI prompt
- auto_cycle.py: saves FRED releases to economic_events each cycle, appends surprise block to fred_block for injection into both suggestion and scoring prompts
- data_fetcher.py: get_economic_calendar() now merges static upcoming events with past FRED actuals from DB (Prev/Fcst/Actual/z-score fields populated)
- CalendarPage.tsx: past events show colored z-score badge ( for |z|≥1.5, bullish/bearish colors)
- EconomicEvent type: added surprise_zscore, surprise_direction, source fields

Activates automatically once fred_api_key is set in Configuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 14:00:35 +02:00
OpenSquared
3edbd6b0b7 feat: institutional reports — CFTC COT + EIA petroleum weekly
- New institutional_reports table (DB) with importance, signals per asset class, key points, absorption tracking
- cot_fetcher.py: CFTC Socrata API (6dca-aqww), 7 instruments (Gold/Silver/Copper/WTI/NatGas/SP500/EURUSD), net positioning + 52-week z-score
- eia_fetcher.py: EIA API v2, 4 series (crude/Cushing/gasoline/distillates), WoW surprise detection
- institutional.py router: GET /reports, GET /reports/{id}, POST /refresh, GET /stats
- institutional_scheduler.py: weekly auto-fetch (COT Saturdays, EIA Wednesday afternoons)
- ai_analyzer.py: build_institutional_block() + institutional_block param injected into AI scoring prompt
- auto_cycle.py: inject institutional block into suggestion + scoring, absorption tracking via keyword overlap after each cycle commentary
- InstitutionalReports.tsx: full page with filter bar (type/category/importance/period), cards with key point bullets, EXTREME alerts highlighted, signal badges, absorption badge, trading implications, expandable detail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 13:45:07 +02:00
OpenSquared
952e326590 feat: pattern convergence engine — categories, signal_direction, conviction scores
Phase 1 — Catégorisation:
- database.py: ADD COLUMN category + signal_direction on custom_patterns (migration);
  save_custom_pattern persists category/signal_direction; new helpers:
  get_unclassified_patterns(), update_pattern_classification(),
  get_patterns_with_last_score()
- ai_analyzer.py: PATTERN_CATEGORIES dict (8 categories: géopolitique, macro_monétaire,
  technique, commodités_supply, risk_off, flux_saisonnier, géo_économique, crédit_stress);
  classify_patterns_batch() → GPT-4o-mini batch classification
- suggest schema: added category + signal_direction fields so new patterns are
  classified from birth
- auto_cycle.py: Step 3.1 classifies all unclassified patterns after each suggestion

Phase 2 — Convergence layer (post-scoring, no extra AI call):
- ai_analyzer.py: _compute_convergence() groups scored patterns by (underlying, signal_direction);
  conviction_bonus = min(20, +5 per additional agreeing pattern); adds conviction_score,
  conviction_bonus, convergence_count, convergence_underlying, convergence_partners to each result;
  called at end of score_patterns_with_context(), re-sorts by conviction_score
- auto_cycle.py: logs convergence summary after scoring; propagates category/signal_direction
  to scored results for display

Phase optionnelle — Convergence in suggestion prompt:
- ai_analyzer.py: suggest_patterns_from_market_context() accepts convergence_block param;
  injected into prompt so AI knows which underlyings have multi-pattern agreement
- auto_cycle.py: before suggestion, loads last-cycle scores via get_patterns_with_last_score(),
  calls _compute_convergence() to build convergence block, passes to suggester

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 20:22:08 +02:00
OpenSquared
96327bec8f fix: weekend-aware cycle — IVGate, pandas MultiIndex, ticker aliases, day/session in AI prompt
- auto_cycle.py: detect weekend/market session, build cycle_meta with day_of_week/is_weekend/market_note;
  IVGate skips iv_rank>=99 on weekends to avoid artificial weekend option premium cascade;
  inject portfolio context (open trades + price moves + concentration) before AI scoring;
  pass portfolio_context_block + run_id to both AI scorer and suggester
- ai_analyzer.py: _build_temporal_news_block injects market session banner (WEEKEND warning,
  pre/after-market note, or open session label) so AI knows markets are closed and defers execution to Monday
- iv_engine.py: add WHEAT/EUR/USD ticker aliases; skip saving IV snapshots on weekends to protect history;
  resolve aliases before slash-format conversion in _resolve_ticker
- technical_indicators.py: fix pandas MultiIndex from yfinance>=0.2 (droplevel+squeeze);
  use period proportional to lookback instead of fixed period=1d
- database.py: asset_class ticker-based fallback (_asset_class_from_ticker); one-time backfill migration
  for all NULL asset_class rows; ai_call_logs table + save/get helpers; normalize_ticker public function

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 19:38:08 +02:00
OpenSquared
4ad3a9a782 feat: portfolio context injection + AI call log viewer
Portfolio context (portfolio_context.py):
- get_open_trades_with_moves(): fetches open trades + 1d/5d yfinance price moves
- get_portfolio_concentration(): counts by asset_class
- build_portfolio_context_block(): formatted prompt block with strict AI instructions
  (no double positions, flag contradictions, avoid overweight classes)

AI call logging:
- ai_call_logs table in DB (run_id, call_type, system/user prompt, response, tokens, ms)
- _chat() now accepts log_meta dict → saves call to DB non-blocking after each call
- suggest and score_batch calls pass run_id + call_type for full traceability

auto_cycle.py:
- Builds portfolio context before snapshot and both AI calls
- Context snapshot now includes portfolio_open_positions key

SystemLogs.tsx:
- "Contexte IA" tab gains sub-tabs: Contexte / Appels IA
- AiCallRow: expandable with 3 panes (user prompt / system prompt / response)
  shows model, tokens breakdown, duration, call type badge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 10:36:05 +02:00
OpenSquared
5d3ff19393 fix: ticker-based asset_class fallback + backfill migration for NULL rows
- _normalize_asset_class() now accepts ticker param and infers class from
  a full ticker→class lookup table (energy/metals/agri/indices/equities/forex)
- init_db() runs one-time UPDATE to backfill all NULL asset_class rows in
  trade_entry_prices and skipped_trades using known ticker lists
- log_trade_entries and log_skipped_trade pass ticker to normalizer
- Frontend _normalizeAssetClass() gets same ticker lookup + pattern fallbacks
  for =F futures, NSE: prefixed equities, =X currency pairs
- All 3 filter calls now pass t.underlying as second argument

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:58:25 +02:00
OpenSquared
7c0ff703b0 fix: filtres Journal de Bord — direction + asset_class tous onglets
Direction (Ouvert) : t.direction n'existe pas dans trade_entry_prices → utilisait
undefined, excluait tout. Remplacé par _isBearishStr(t.strategy) comme Fermés.

Asset class (Ouvert, Fermés, Non loggés) : l'IA retournait parfois "commodities",
"currencies", "fx", "equity" au lieu des clés canoniques. Double correction :
- Frontend : _normalizeAssetClass() mappe les variantes → energy|metals|agriculture|
  indices|equities|forex dans les 3 sections filtrées
- Backend database.py : _normalize_asset_class() appliqué à l'INSERT dans
  trade_entry_prices et skipped_trades (nouveaux trades normalisés au stockage)
- Prompt ai_analyzer.py : suggested_trades[].asset_class contraint à l'enum explicite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 18:44:14 +02:00
OpenSquared
a21699805b feat: Phase 4+5 — price discovery status + replay historique
Phase 4 — Price Discovery Status (la pièce maîtresse) :
- price_discovery.py (nouveau) : capture_price_snapshots() sauve les prix des tickers
  liés à chaque news scorée (energy→BZ=F/NG=F, metals→GC=F/HG=F, indices→^GSPC/IWM)
- compute_absorptions() mesure combien du mouvement attendu s'est déjà produit
  (status: not_yet_priced <30% / partially_priced 30-80% / fully_priced >80%)
- build_price_discovery_block() → bloc prompt avec opportunités classées
- database.py : table news_price_snapshots + save/get/purge fonctions
- auto_cycle.py : capture après ai_score_news_batch, compute avant suggestions,
  block injecté dans suggestion + scoring prompts + context snapshot
- ai_analyzer.py : param price_discovery_block dans suggest + score

Phase 5 — Replay historique :
- cycle.py : POST /api/cycle/contexts/{run_id}/replay — recharge le snapshot historique
  et relance suggest_patterns_from_market_context avec le contexte original
- useApi.ts : hook useReplayCycle
- SystemLogs.tsx : bouton "Rejouer ce cycle" dans onglet Contexte IA avec champ
  notes, résultats inline (liste des patterns générés), section price_discovery
  ouverte par défaut en rouge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 16:58:57 +02:00
OpenSquared
9c0ebbd138 feat: Phase 2 + context log — FRED releases, cycle context snapshot, onglet Contexte IA
Phase 2 — Données macro FRED :
- fred_fetcher.py (nouveau) : 7 séries FRED (CPI, NFP, UNRATE, FEDFUNDS, GDP, ICSA,
  spread 10Y-2Y) avec détection direction bullish/bearish et block prompt formaté
- ai_analyzer.py : param fred_block dans suggest + score, injecté dans les deux prompts
- auto_cycle.py : fetch FRED non-bloquant avant la suggestion

Context log — Snapshot du contexte complet :
- database.py : table cycle_context_snapshots + save/get/list fonctions
- auto_cycle.py : sauvegarde le snapshot (meta, news partitionnées, FRED, tech, IV, quotes)
- cycle.py : GET /api/cycle/contexts + GET /api/cycle/contexts/{run_id}
- useApi.ts : hooks useCycleContextSnapshots + useCycleContextSnapshot
- SystemLogs.tsx : onglet "Contexte IA" avec liste de cycles et visualiseur JSON
  par section (cycle_meta, macro, news, FRED, tech) avec accordéon

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 16:51:02 +02:00
OpenSquared
d5e31bc897 feat: Phase 1 — delta temporel + decay news + cycle_meta dans prompts IA
- database.py: get_last_completed_cycle_ts() pour mesurer le delta entre cycles
- auto_cycle.py: calcul delta_minutes + cycle_meta dict transmis aux fonctions IA
- ai_analyzer.py: apply_news_decay() (halflife par catégorie), partition_news_by_age()
  (3 buckets: inter_cycle / recent_24h / older), _build_temporal_news_block() pour
  le prompt suggestion; cycle_meta injecté aussi dans score_patterns_with_context()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 16:36:54 +02:00
OpenSquared
d4a016a535 feat: P&L côte à côte (Ouvert|Réalisé) + filtres journal + suppression trades fermés
- Dashboard: P&L card séparé en deux colonnes (Ouvertes/Réalisées) pour Simulé et Portfolio
- Dashboard: closed trades P&L locked from pnl_realized, ne fluctue plus après fermeture
- Journal Ouvert: filtres ticker/stratégie + classe d'actif + direction (haussier/baissier)
- Journal Fermés: mêmes filtres + filtre P&L (gagnants/perdants) + bouton supprimer par ligne
- Journal Non loggés: filtres ticker + classe d'actif + raison de skip
- Backend: DELETE /api/journal/trades/{id} + delete_trade() dans database.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 11:00:31 +02:00
OpenSquared
c7ccf237d7 feat: IV gate — block ALERT trades before logging + configurable thresholds
- auto_cycle.py: pre-fetch IV snapshots at step 1.9; _apply_iv_gate() runs
  before log_trade_entries, removes ALERT-verdict trades (not just reports)
- options_technical_agent.py: _IVR_HIGH/_IVR_EXTREME/_SKEW_THRESH as
  module-level vars; straddle/strangle penalty -60 (vs -56 naked) at extreme IVR
  so Long Straddle at IVR ≥ 80% → ALERT; thresholds respected in rule engine
- database.py: seed 4 iv_gate config keys (iv_gate_enabled, iv_gate_ivr_high=60,
  iv_gate_ivr_extreme=80, iv_gate_skew_threshold=8) — editable from Config page
- Blocked trades logged as skipped_trades with [IV_GATE] detail + optimal strategy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 10:15:45 +02:00
OpenSquared
3ee39d5f08 feat: options technical agent — IV/skew/term structure validation per trade
- New options_technical_agent.py: rule engine (IVR, skew, term structure, flow)
  + GPT-4o narrative per trade; verdict OK/WARN/ALERT + fit_score
- options_trade_assessments table in DB for Journal badge persistence
- auto_cycle.py step 5.2: assess newly logged trades after log_trade_entries;
  results embedded in cycle report
- suggest_patterns_from_market_context: +iv_context param + explicit IV→strategy
  rules in prompt (IVR<30%→Long, 30-60%→Spread, >60%→no naked long, >80%→short)
- Pre-fetch iv_context at step 1.9 so suggestion step gets strategy rules
- reports.py: /api/reports/assessments/latest + /assessments/{run_id} endpoints
- RapportIA.tsx: "Validation Technique Options" section with per-trade IVBar,
  VerdictBadge, issues list, GPT-4o analysis, optimal strategy suggestion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 09:36:35 +02:00