Commit Graph

142 Commits

Author SHA1 Message Date
OpenSquared
aecbdc9929 feat: instrument model 2026-07-02 20:31:30 +02:00
OpenSquared
ae5865a156 feat: pressure 2026-07-02 18:07:21 +02:00
OpenSquared
01709e5edf feat: causal lab 2026-07-02 16:46:38 +02:00
OpenSquared
5126360ce9 feat: causal lab 2026-07-02 14:42:50 +02:00
OpenSquared
5081514898 feat: calendar 2026-07-02 11:27:45 +02:00
OpenSquared
8098104f5b feat: causal lab 2026-07-02 09:26:52 +02:00
OpenSquared
916b7b38e6 feat: causal tab 2026-07-01 22:09:01 +02:00
OpenSquared
e1681edffc feat: causal lab 2026-07-01 21:01:00 +02:00
OpenSquared
1829335ad1 feat: macro series 2026-07-01 17:38:33 +02:00
OpenSquared
8b59eff744 feat: macro series 2026-07-01 16:16:51 +02:00
OpenSquared
776c19e1ae feat: macro series 2026-07-01 15:58:47 +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
9904c066b2 feat: instrument analysis 2026-06-30 16:15:39 +02:00
OpenSquared
5e37cd81a2 fix: pass prediction_json and actual_json through to snapshot events
The filtered event dict was built with explicit fields and omitted these two columns,
so the frontend always received null despite the DB having valid data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 23:34:32 +02:00
OpenSquared
5e819b5b67 feat: instrument analysis 2026-06-29 20:44:03 +02:00
OpenSquared
f4a55a8009 feat: desk ia 2026-06-29 20:21:52 +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
5e65424500 feat: instrument analysis 2026-06-29 00:06:14 +02:00
OpenSquared
3bcecdab09 feat: instrument analysis 2026-06-28 23:43:52 +02:00
OpenSquared
c286c7c000 feat: desk IA 2026-06-28 17:14:40 +02:00
OpenSquared
bab09a1b09 feat: causal lab 2026-06-28 17:03:37 +02:00
OpenSquared
e4e17330b4 feat: instrument analysis 2026-06-28 16:36:28 +02:00
OpenSquared
1e44557551 feat:: causal lab 2026-06-28 15:38:19 +02:00
OpenSquared
20f1897211 feat: instrument analysis 2026-06-28 13:52:34 +02:00
OpenSquared
79d4a9f741 Calendar synchro 2026-06-28 12:15:25 +02:00
OpenSquared
e8fb7c13aa feat: causal lab — éditeur visuel, types nœuds, force/signe arêtes, NFP v2 2026-06-28 09:28:43 +02:00
OpenSquared
a7f5369d7b Causal lab v2 2026-06-27 23:25:59 +02:00
OpenSquared
a24cac38ad feat: eco desk enhanced config + EUR/USD causal simulator
Eco desk (market_event_detector.py + AIDesks.tsx):
- Add currencies filter (USD via FRED, EUR/GBP/JPY/etc via ff_calendar)
- Add min_impact filter (high / high+medium / all levels)
- Add create_market_event toggle — detect surprises without creating events
- Add lookback_releases — inject last N historical releases into event description
- New _check_ff_calendar_surprises() for non-USD surprising releases
- Frontend EcoConfig: currency chips, impact dropdown, releases input, toggle

EUR/USD Simulator (EuroSimulator.tsx):
- Pure frontend causal model — no API calls, no historical data
- 3-column layout: controls | causal chain SVG | results
- FED/BCE rate sliders + hawkish/dovish tone selector
- CPI/NFP/PMI surprise inputs
- SVG causal chain: CPI→CB→2Y→ΔRate→EURUSD with dynamic colors
- Real-time pip decomposition by factor, sensitivity bars
- Route /simulator + sidebar entry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 22:17:33 +02:00
OpenSquared
87ded9434f feat: import Trading Economics HTML calendar — 993 events with forecasts
Adds a one-click upload+parse flow for the TE calendar page HTML.
The TE page (tradingeconomics.com/calendar) contains ~1000 events with
actuals, previous, and analyst consensus (forecast) values.

- Add backend/services/te_html_parser.py:
  - parse_html(html): extracts events from <tr data-event> rows
  - Maps 14 countries to major currencies (all Eurozone → EUR)
  - Impact inferred from data-category (high/medium/low)
  - Times converted from Europe/Zurich (CET/CEST) → UTC via zoneinfo
  - Actual=td[5], Forecast=td[7] (analyst consensus), Previous=td[6]
- Add POST /api/eco/te-html-upload (saves file to /tmp)
- Add POST /api/eco/te-html-import + GET /status (background parse)
- Add "Import TE HTML" upload button in CalendarPage ImportPanel

Tested locally: 993 events parsed, 854 with forecast, 861 with actual,
date range 2025-03-31 → 2026-06-17, timezone conversion verified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 18:15:02 +02:00
OpenSquared
bdbb87962d feat: FXStreet calendar — free upcoming events with forecasts (no API key)
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>
2026-06-26 17:54:15 +02:00
OpenSquared
5c86d6e715 feat: replace Trading Economics with FMP for upcoming calendar forecasts
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>
2026-06-26 17:42:09 +02:00
OpenSquared
ec6fcc1e3d feat: Trading Economics API for upcoming events with forecasts
- 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>
2026-06-26 17:30:16 +02:00
OpenSquared
d9762deca7 feat: custom date range filter on calendar page
- Backend: /api/eco/calendar accepts date_from + date_to query params
  when period=custom; get_calendar() uses them directly without override
  Limit raised to 5000 for wide date ranges
- Frontend: "Custom" tab at end of period list; shows two date inputs
  (from/to) with Apply button; displays day count; fetches on Apply click
  (not on every keystroke to avoid hammering the API)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 17:17:01 +02:00
OpenSquared
c36b2b2198 feat: FF HTML scraper for upcoming weeks with forecasts
- 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>
2026-06-26 17:14:00 +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
b058b7297a fix: use FRED official JSON API (bypasses CloudFlare) + API key UI
- fred_bootstrap.py: switch from CSV graph endpoint (CloudFlare-blocked)
  to api.stlouisfed.org/fred/series/observations JSON API; reads key
  from DB config 'fred_api_key'; returns clear error if key missing
- eco.py: add GET/POST /api/eco/fred-key to check/save the FRED API key
- CalendarPage.tsx: BootstrapPanel shows API key section with status,
  input to paste key + save button, disables Launch if key missing

Free key: fred.stlouisfed.org -> My Account -> API Keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:47:16 +02:00
OpenSquared
202a8ce97c fix: FRED fetch — add browser User-Agent + print diagnostics to stdout
FRED blocks requests without a valid User-Agent. Added headers matching
a real browser. Also added print() calls so fetch errors appear in
docker logs (logger.warning goes to system_logs table, not stdout).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:33:06 +02:00
OpenSquared
d25ca92694 fix: FRED data quality — GDP growth %, CPI/PCE YoY%, ICSA in K
- GDPC1 replaces A191RL1Q225SBEA: compute annualized QoQ growth from
  GDP level ((val/prev)^4 - 1)*100 → displays proper ~2-3% not 31 819
- CPIAUCSL/CPILFESL/PCEPILFE: yoy_pct transform (val/val_12m_ago-1)*100
  → displays 3.x% YoY inflation, not raw index level 334
- ICSA: div1000 transform → displays 226 K claims, not 226 000 K
- delta_absolute flag: pp change for rate/% series, % change for levels
- SurprisePct component: shows 'pp' suffix for %, '%' for K/levels
- Column header renamed from 'Δ%' to 'Δ vs préc.' with tooltip
- Deprecated A191RL1Q225SBEA rows cleaned from DB on next bootstrap
- Warm-up periods: 2yr for yoy_pct, 3yr for qoq_annualized, 1yr others

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:16:44 +02:00
OpenSquared
64ff777da6 feat: FRED bootstrap + Calendar page complete rebuild
- 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>
2026-06-26 14:42:44 +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
d0816fd9ff feat: Sentiment desk — gauge threshold alerts (Option B)
Each macro gauge selected in the Sentiment desk can now be independently
configured with three alert criteria:
- Seuil bas (≤): alert when value crosses below
- Seuil haut (≥): alert when value crosses above
- Variation % (Δ%): alert when N-day % change exceeds threshold

Frontend: GaugeThresholdConfig component — one row per selected gauge,
compact grid layout with enable toggle + 3 numeric inputs.
Stored in config.gauge_thresholds[gauge_id].

Backend: _check_sentiment() extended — after CBOE signals, reads
macro_gauge_snapshots history, checks each enabled gauge threshold,
emits sentiment market_events with options_note for each breach.
Gauge → affected_assets mapping covers all 32 gauge keys.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 13:59:40 +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
069b398d75 feat: apply category defaults first then AI adjusts + remove chips
Backend: merge strategy — category defaults are applied as baseline
(ai_generated=0), AI impacts override/extend them (ai_generated=1).
All N category defaults appear in the impacts list; AI covers them
explicitly with event-specific score/direction adjustments.
Prompt: instruct AI to cover ALL default instruments.

Frontend: remove default impact chips under category selector —
they now appear directly in the instrument impacts list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 22:23:38 +02:00