diff --git a/backend/routers/wavelet.py b/backend/routers/wavelet.py
index ba4bff5..7e4abf3 100644
--- a/backend/routers/wavelet.py
+++ b/backend/routers/wavelet.py
@@ -302,5 +302,5 @@ def remove_simulation(sim_id: str):
@router.get("/watchlist-signals")
def watchlist_signals():
- from services.database import get_latest_wavelet_signals
- return {"signals": get_latest_wavelet_signals()}
+ from services.database import get_latest_wavelet_state_by_instrument
+ return {"signals": get_latest_wavelet_state_by_instrument()}
diff --git a/backend/services/database.py b/backend/services/database.py
index 41aca5e..7cd7273 100644
--- a/backend/services/database.py
+++ b/backend/services/database.py
@@ -3622,6 +3622,36 @@ def get_latest_wavelet_signals() -> List[Dict]:
return [dict(r) for r in rows]
+def get_latest_wavelet_state_by_instrument() -> List[Dict]:
+ """One row per Watchlist instrument from the most recent scan — a fired signal if this
+ run had one for it (any band), otherwise the fastest band's current slope/direction, so
+ every scanned instrument shows *something* here instead of only the ones with an active
+ trigger this run. get_latest_wavelet_signals() (fired-only) stays as-is for any other
+ caller; this is specifically for the Dashboard's Wavelets Signal card, which should
+ reflect the latest state per instrument, not just a list of firings."""
+ run_id = _latest_wavelet_run_id()
+ if not run_id:
+ return []
+ conn = get_conn()
+ rows = conn.execute(
+ "SELECT * FROM wavelet_watchlist_signals WHERE run_id=? AND band_label != 'ridge' "
+ "ORDER BY ticker, (signal_kind IS NULL), period_low_days ASC",
+ (run_id,),
+ ).fetchall()
+ conn.close()
+ by_ticker: Dict[str, Dict] = {}
+ for r in rows:
+ d = dict(r)
+ by_ticker.setdefault(d["ticker"], d)
+ out = list(by_ticker.values())
+ # No fired signal this run for this band -> direction is null; fall back to the band's
+ # own slope sign so the card can still show an up/down arrow instead of a blank one.
+ for d in out:
+ if d.get("direction") is None and d.get("slope") is not None:
+ d["direction"] = "up" if d["slope"] > 0 else "down"
+ return out
+
+
def get_latest_wavelet_state() -> List[Dict]:
"""Every (ticker, band) row from the most recent cycle scan — signal or
not. Used for the rich AI chat context block (slope/energy/ridge state)."""
diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx
index 0306802..01bd5cd 100644
--- a/frontend/src/pages/Dashboard.tsx
+++ b/frontend/src/pages/Dashboard.tsx
@@ -1056,8 +1056,8 @@ export default function Dashboard() {