Commit Graph

1 Commits

Author SHA1 Message Date
Elie Habib
b83bf415dc feat(market-implications): validate LLM tickers against live Redis symbol set (#2433)
* feat(market-implications): validate LLM tickers against live Redis symbol set

Add _ticker-validation.mjs with loadTickerSet (reads market:stocks-bootstrap:v1)
and filterInvalidTickers. After static whitelist validation, equity cards are also
gated against the live symbol set from Redis — additive (ALL_ALLOWED_TICKERS union
live symbols), so curated ETF/defense tickers are never incorrectly dropped.
Drops are logged per-card for observability.

* fix(market-implications): move dynamic ticker gate before validation

The previous approach was a logical no-op: validateMarketImplications()
already filtered to ALL_ALLOWED_TICKERS, then the gate re-filtered
against ALL_ALLOWED_TICKERS ∪ liveSet — so every surviving card was
guaranteed to pass and filterInvalidTickers() could never drop anything.

Fix: load the live Redis ticker set first and pass it as the allowed set
into validateMarketImplications() (new allowedTickers parameter). When
Redis has data, effectiveTickers = NON_EQUITY_TICKERS ∪ liveTickerSet,
so hallucinated equity symbols absent from the live symbol set (WMTX,
GOOG, etc.) are dropped at the single validation pass. Falls back to
ALL_ALLOWED_TICKERS when Redis is unavailable. Remove now-dead
filterInvalidTickers export.

* fix(market-implications): use ALL_ALLOWED_TICKERS union liveTickerSet

NON_EQUITY_TICKERS + liveTickerSet incorrectly dropped curated ETF and
defense tickers (SPY, QQQ, XLE, RTX, LMT, NOC) that are in the static
allowlist but not in market:stocks-bootstrap:v1.

Correct model: ALL_ALLOWED_TICKERS is always preserved as the curated
baseline; liveTickerSet extends it with live-priced stocks (NFLX, WMT,
etc.) not in the static list. Hallucinations absent from both sets are
rejected. Remove now-unused NON_EQUITY_TICKERS constant.

* fix(market-implications): strip non-tradeable symbols before live ticker union

market:stocks-bootstrap:v1 contains index symbols (^GSPC, ^DJI, ^IXIC,
^NSEI) and foreign-exchange-suffixed symbols (RELIANCE.NS, TCS.NS) for
display/charting purposes. Unioning the full live set into effectiveTickers
would allow these non-tradeable instruments to pass card validation.

Filter liveTickerSet to /^[A-Z]{1,6}(-[A-Z])?$/ before the union so only
clean US-exchange symbols (NFLX, WMT, BRK-B) extend the static allowlist.
2026-03-28 19:51:29 +04:00