- Status: Accepted
- Date: 2026-05
The project originally tried to be a real-time intra-day analyzer. This led to a sprawling implementation surface:
- 7 free real-time quote fetchers, each with its own retry / cache logic
- A
BackgroundPollerthread polling every minute regardless of pipeline activity dashboard_watchlisttable tracking user "watch" statemarket_hourslookups gating display- 1-second frontend polling
- A
market_openbadge driving conditional UI
Real-time data is a different product than post-close analysis:
- it requires sub-second freshness guarantees we cannot deliver on free APIs
- it requires UI patterns (streaming, badges, hot-paths) that complicate the d3 heatmap
- it doubles the testing surface (pre-market / open / close / extended hours)
In practice users only consumed the daily digest after close.
The project is positioned as a post-close review tool only.
All real-time intra-day code was deleted. Quotes are read from the
stock_quote_snapshot SQLite table written by the analysis pipeline
at end of each batch run. The frontend does not poll on a timer; it
refreshes on (a) initial load, (b) explicit user click, (c) tab visibility
change after ≥ 5 min stale.
Easier
- Single source of truth for "current price": whatever the last batch wrote.
- BatchContext data alignment is well-defined (one trading day per run).
- Frontend has zero idle-tab CPU cost.
- Test surface contracts to one phase.
Harder
- Cannot serve true intra-day use cases (alerts, momentum scanners). Users needing this should adopt a different tool.
- Cold start of
/sectors/indicesbecomes user-visible (mitigated by kvcache pre-warm + 4s timeout cap). - Display must communicate "as-of date" prominently, otherwise users mistake
Friday's close for "right now". Implemented via mandatory
data_datefield in tooltips and an[as_of]label on the freshness button.
- Hybrid: keep poller off by default, allow opt-in. Rejected — the surface stays in code, latent bugs persist (e.g. silent staleness from Xueqiu — see CHANGELOG 2026-05 Fixed).
- Real-time only: rebuild around a single paid feed. Rejected — out of scope for a single-maintainer project.
- CHANGELOG 2026-05 / Removed / "Real-time intra-day code"
docs/context.md— Positioning statement