Backend (routers/simulator.py):
- GET /api/simulator/baseline aggregates current market values:
1. macro_gauge_snapshots → VIX, Brent oil
2. FRED economic_events → FEDFUNDS, ECBDFR, DFII10 (real yield)
3. yfinance live → EURUSD=X, ^IRX+^FVX interpolated US 2Y,
DE2YT=RR EU 2Y (or ECB rate +15bps fallback),
^VIX, BZ=F
- Returns sources dict so frontend can show data provenance
Frontend (EuroSimulator.tsx):
- Fetch /api/simulator/baseline on mount; use as base anchors
- compute(p, base) now takes dynamic base instead of hardcoded constants
- Reset button returns to today's live baseline, not hardcoded fallback
- Live/Fallback status badge with fetch date
- Sources panel showing data origin per field
- Chart reference line updates to show live base values
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FXStreet calendar.fxstreet.com/eventdate/ returns ~300-400 events over
6 weeks including consensus forecasts, no authentication required.
FF HTML scraper is blocked by Cloudflare even on residential IPs.
FMP free plan returns 403 on /economic_calendar (requires Starter plan).
- Add backend/services/fxstreet_calendar.py: single GET request returning
all major currencies; maps Volatility 0/1/2 → low/medium/high
- Add POST /api/eco/fxs-sync + GET /api/eco/fxs-sync/status endpoints
- Add FXStreet to daily background sync in main.py (runs every 24h)
- Add "Sync Upcoming (FXStreet)" button in ImportPanel (no key needed)
- Fix FMP 403 error message to say endpoint requires Starter plan
- Keep FMP panel for users who upgrade to FMP Starter ($14.99/month)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TE costs $199/month and its Economic Calendar is not in the free tier.
FMP (Financial Modeling Prep) offers a free API key (250 req/day) with
full economic calendar coverage including consensus estimates (forecasts).
- Add backend/services/fmp_calendar.py: fetches upcoming events from
GET /api/v3/economic_calendar (one request, all countries, date range)
- Replace /api/eco/te-key + te-sync endpoints with fmp-key + fmp-sync
- Update daily background sync in main.py to use fmp_calendar
- Replace TEPanel with FMPPanel in CalendarPage.tsx (link to FMP docs)
- Remove broken Cloudflare-blocked FF HTML scrape button from ImportPanel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New services/te_calendar.py: fetch_upcoming(weeks_ahead) calls TE API
for 9 countries (USD/EUR/GBP/JPY/AUD/CAD/NZD/CHF/CNY), converts to
ff_calendar format, upserts with source='te_api'
- New endpoints: GET/POST /api/eco/te-key, POST /api/eco/te-sync,
GET /api/eco/te-sync/status
- Daily scheduler in main.py: FF live sync + TE sync (if key configured)
run 60s after startup then every 24h
- CalendarPage: TEPanel with key input (password field, Enter to save,
"Get free key" link to tradingeconomics.com/api/login),
"Sync upcoming (6 weeks)" button with polling
FF HTML scraper kept as fallback but TE API is the primary source
for upcoming forecasts (no Cloudflare blocking on server IPs).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scrape_upcoming(weeks_ahead=5) in ff_calendar.py:
fetches forexfactory.com/calendar?week=... HTML for N weeks ahead,
parses calendar__table (date/time/currency/impact/event/forecast/previous),
converts ET times to UTC, upserts into ff_calendar
- Daily scheduler in main.py: runs scrape_upcoming at startup (after 30s delay)
then every 24h — no manual action needed
- New endpoints: POST /api/eco/ff-scrape?weeks=5, GET /api/eco/ff-scrape/status
- CalendarPage: "Scrape Upcoming (5w)" button (indigo) with polling + result
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove count>0 guard — import runs regardless of existing rows (idempotent upsert)
- After successful import, CSV is deleted from /app so next restart skips cleanly
- No more need to manually trigger import or remove CSV from git separately
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- forex_factory_cache.csv moved to backend/ (Docker build context)
→ available at /app/forex_factory_cache.csv inside container
- main.py startup: auto-imports CSV in background thread if ff_calendar empty
(idempotent — skips if rows already present)
- CSV path candidates: /app/ (Docker) → /tmp/ (upload) → local dev paths
- CalendarPage: remove Upload CSV + Import into DB buttons
→ replaced by auto-import status indicator + Sync Live only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- backend/services/fred_bootstrap.py: fetch 11 FRED series (PAYEMS, UNRATE, CPI, PCE, FEDFUNDS, ICSA, GDP, HY spread, T10Y2Y, T10Y3M) from public CSV endpoint — no API key needed; computes rolling z-scores and upserts into economic_events table
- backend/routers/eco.py: new /api/eco router with bootstrap (POST + status GET), events list with full filtering (date range, category, series, min z-score, direction, sort/pagination), series catalog, and db status endpoints
- backend/main.py: register eco router
- frontend/src/pages/CalendarPage.tsx: complete rewrite — real data table from /api/eco/events, Bootstrap FRED button with live polling, filter bar (date range, category, series chips, |z| threshold, direction), sort by date/z-score/series, pagination, z-score badges with color coding, sidebar with series inventory + geo alerts + z-score guide
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- MarketEvents: date presets (7j/30j/3m/6m/1an/Tout/Perso), instrument
impact filter (ticker + min score + direction → auto-sort by inst score),
sort controls (date/score/nom + asc/desc), clear-all button, count bar
- Market events list endpoint: full SQL JOIN rewrite supporting instrument
filter, date range, origin, sort_by=instrument_score
- Disable auto-bootstrap on startup (macro/eco/categories) — manual only
- CycleActions: bootstrap group (Macro/Eco/Categories) with force checkbox,
grouped layout (detection / bootstrap / data / ai / portfolio)
- cycle_actions router: /bootstrap-macro, /bootstrap-eco, /bootstrap-categories
endpoints + group field on all action catalogue entries
- InstrumentChart: greedy row placement for star labels (4 rows × 20px)
to eliminate horizontal overlap; labels now inline (★ + text)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both bootstrap_macro_events() and bootstrap_eco_events() are now called
in the FastAPI startup event. Idempotent — skips already-existing events.
Logs how many events were inserted on first run.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
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>
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>
- 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>
- 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>