- tradingagents/dataflows/universe.py: single source of truth for ticker
universe; all scanners now call load_universe(config) instead of
duplicating the 3-level fallback chain with hardcoded "data/tickers.txt"
- scripts/prefetch_ohlcv.py: nightly script using existing ohlcv_cache.py
incremental logic; first run downloads 1y history, subsequent runs append
only new trading days
- .github/workflows/prefetch.yml: runs at 01:00 UTC daily, before all other
workflows; commits updated parquet to repo
- Updated 6 scanners: minervini, high_52w_breakout, ml_signal, options_flow,
sector_rotation, technical_breakout — removed duplicate DEFAULT_TICKER_FILE
constants and _load_tickers_from_file() functions
- minervini, high_52w_breakout, technical_breakout: replace yf.download()
with download_ohlcv_cached() — reads from prefetched cache instead of
hitting yfinance at discovery time
- default_config.py: added discovery.ohlcv_cache_dir config key
- data/ohlcv_cache/: initial 1y backfill (588 tickers, 5.4MB parquet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Same issue as options_flow: early exit on candidate count discards strong
signals that happen to be later in iteration order.
insider_buying: Dict iteration order matched OpenInsider HTML scrape order,
not signal quality. Now scores by cluster buys + C-suite + dollar value,
then takes top N.
technical_breakout: Stopped at limit*2 in file order despite data already
being batch-downloaded (zero API cost to check all). Removed early exit,
scan full universe, sort by volume_multiple.
sector_rotation: Checked laggards in arbitrary dict order, spending API
calls on random tickers. Now sorts by most-negative 5d return first so
the strongest laggard candidates are checked before hitting the budget.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>