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>
This commit is contained in:
OpenSquared
2026-06-25 00:07:41 +02:00
parent aec9ced74f
commit 3470205d54
6 changed files with 878 additions and 160 deletions

View File

@@ -575,8 +575,14 @@ def _get_relevant_events(
"title": ev.get("name") or ev.get("event_name") or "",
"level": ev.get("level", "medium"),
"category": ev.get("category", ""),
"sub_type": ev.get("sub_type") or None,
"description": (ev.get("description") or "")[:120],
"impact_score": float(ev.get("impact_score") or 0.5),
"expected_value": ev.get("expected_value") or None,
"actual_value": ev.get("actual_value") or None,
"surprise_pct": ev.get("surprise_pct"),
"unit": ev.get("unit") or None,
"absorption_pct": ev.get("absorption_pct"),
})
# Sort by start_date asc for timeline display, cap at 30