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>
This commit is contained in:
@@ -942,6 +942,15 @@ def init_db():
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Idempotent column additions
|
||||
for _col_sql in [
|
||||
"ALTER TABLE market_events ADD COLUMN source_refs TEXT DEFAULT '[]'",
|
||||
]:
|
||||
try:
|
||||
c.execute(_col_sql)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -4545,18 +4554,22 @@ def save_market_event(ev: Dict[str, Any]) -> int:
|
||||
import json
|
||||
conn = get_conn()
|
||||
try:
|
||||
src_refs = ev.get("source_refs", [])
|
||||
if isinstance(src_refs, list):
|
||||
src_refs = json.dumps(src_refs)
|
||||
cur = conn.execute("""INSERT INTO market_events
|
||||
(name, start_date, end_date, level, category, description, market_impact,
|
||||
affected_assets, impact_score, parent_event_id,
|
||||
expected_value, actual_value, surprise_pct, unit, sub_type, absorption_pct)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
expected_value, actual_value, surprise_pct, unit, sub_type, absorption_pct,
|
||||
source_refs)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
(ev["name"], ev["start_date"], ev.get("end_date"),
|
||||
ev["level"], ev.get("category", "macro"), ev.get("description", ""),
|
||||
ev.get("market_impact", ""), json.dumps(ev.get("affected_assets", [])),
|
||||
ev.get("impact_score", 0.5), ev.get("parent_event_id"),
|
||||
ev.get("expected_value"), ev.get("actual_value"),
|
||||
ev.get("surprise_pct"), ev.get("unit"), ev.get("sub_type"),
|
||||
ev.get("absorption_pct")))
|
||||
ev.get("absorption_pct"), src_refs))
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
finally:
|
||||
@@ -4567,17 +4580,20 @@ def update_market_event(event_id: int, ev: Dict[str, Any]) -> bool:
|
||||
import json
|
||||
conn = get_conn()
|
||||
try:
|
||||
src_refs = ev.get("source_refs", [])
|
||||
if isinstance(src_refs, list):
|
||||
src_refs = json.dumps(src_refs)
|
||||
conn.execute("""UPDATE market_events SET
|
||||
name=?, start_date=?, end_date=?, level=?, category=?, description=?,
|
||||
market_impact=?, affected_assets=?, impact_score=?,
|
||||
absorption_pct=?, relevant_indicators=?
|
||||
absorption_pct=?, relevant_indicators=?, source_refs=?
|
||||
WHERE id=?""",
|
||||
(ev["name"], ev["start_date"], ev.get("end_date"),
|
||||
ev["level"], ev.get("category", "macro"), ev.get("description", ""),
|
||||
ev.get("market_impact", ""), json.dumps(ev.get("affected_assets", [])),
|
||||
ev.get("impact_score", 0.5),
|
||||
ev.get("absorption_pct"), json.dumps(ev.get("relevant_indicators", [])),
|
||||
event_id))
|
||||
src_refs, event_id))
|
||||
conn.commit()
|
||||
return True
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user