5.4 KiB
ADR 014: Finviz Smart Money Scanner — Phase 1b Bottom-Up Signal Layer
Status
Accepted
Context
The macro scanner pipeline produced top-down qualitative analysis (geopolitical events, market movers, sector rotation) but selected stocks entirely from macro reasoning. There was no bottom-up quantitative signal layer to cross-validate candidates. Adding institutional footprint detection (insider buying, unusual volume, breakout accumulation) via finvizfinance creates a "Golden Overlap" — stocks confirmed by both top-down macro themes and bottom-up institutional signals carry higher conviction.
Key constraints considered during design:
run_tool_loop()hasMAX_TOOL_ROUNDS=5. The market_movers_scanner already uses ~4 rounds. Adding Finviz tools to it would silently truncate at round 5.finvizfinanceis a web scraper, not an official API — it can be blocked or rate-limited at any time.- LLMs can hallucinate string parameter values when calling parameterized tools.
- Sector rotation context is available from sector_scanner output and should inform smart money interpretation.
Decisions
1. Separate Phase 1b Node (not bolted onto market_movers_scanner)
A dedicated smart_money_scanner node avoids the MAX_TOOL_ROUNDS=5 truncation risk entirely. It runs sequentially after sector_scanner (not in the Phase 1a parallel fan-out), giving it access to sector_performance_report in state. This context lets the LLM cross-reference institutional footprints against leading/lagging sectors.
Final topology:
Phase 1a (parallel): START → geopolitical_scanner
START → market_movers_scanner
START → sector_scanner
Phase 1b (sequential): sector_scanner → smart_money_scanner
Phase 2: geopolitical_scanner, market_movers_scanner, smart_money_scanner → industry_deep_dive
Phase 3: industry_deep_dive → macro_synthesis → END
2. Three Zero-Parameter Tools (not one parameterized tool)
Original proposal: get_smart_money_anomalies(scan_type: str) with values like "insider_buying".
Problem: LLMs hallucinate string parameter values. The LLM might call get_smart_money_anomalies("insider_buys") or get_smart_money_anomalies("volume_spike") — strings that have no corresponding filter set.
Solution: Three separate zero-parameter tools:
get_insider_buying_stocks()— hardcoded insider purchase filtersget_unusual_volume_stocks()— hardcoded volume anomaly filtersget_breakout_accumulation_stocks()— hardcoded 52-week high + volume filters
With zero parameters, there is nothing to hallucinate. The LLM selects tools by name from its schema — unambiguous. All three share a _run_finviz_screen(filters_dict, label) private helper to keep the implementation DRY.
3. Graceful Degradation (never raise)
finvizfinance wraps a web scraper that can fail at any time (rate limiting, Finviz HTML changes, network errors). _run_finviz_screen() catches all exceptions and returns a string starting with "Smart money scan unavailable (Finviz error): <message>". The pipeline never hard-fails due to Finviz unavailability. macro_synthesis is instructed to note the absence and proceed on remaining reports.
4. breakout_accumulation over oversold_bounces
Original proposal included an oversold_bounces scan (RSI < 30). This was rejected: RSI < 30 bounces are retail contrarian signals, not smart money signals. Institutions don't systematically buy at RSI < 30. Replaced with breakout_accumulation (52-week highs on 2x+ volume) — the O'Neil CAN SLIM institutional accumulation pattern, where institutional buying drives price to new highs on above-average volume.
5. Golden Overlap in macro_synthesis
macro_synthesis now receives smart_money_report alongside the 4 existing reports. The system prompt includes explicit Golden Overlap instructions: if a smart money ticker fits the top-down macro narrative (e.g., an energy stock with heavy insider buying during a supply shock), assign it "high" conviction. If no smart money tickers align, proceed on remaining reports. The JSON output schema is unchanged.
Consequences
- Pro: Dual evidence layer — top-down macro + bottom-up institutional signals improve conviction quality
- Pro: Zero hallucination risk — no string parameters in any Finviz tool
- Pro: Pipeline never fails due to Finviz — graceful degradation preserves all other outputs
- Pro: Sector context injection — smart money interpretation is informed by rotation context from sector_scanner
- Con:
finvizfinanceis a web scraper — brittle to Finviz HTML changes; requires periodic maintenance - Con: Finviz screener results lag real-time institutional data (data is end-of-day); not suitable for intraday signals
- Con: Adds ~620 tokens to scanner pipeline token budget (quick_llm tier, acceptable)
Source Files
tradingagents/agents/scanners/smart_money_scanner.py(new)tradingagents/agents/utils/scanner_tools.py(3 new tools +_run_finviz_screenhelper)tradingagents/agents/utils/scanner_states.py(smart_money_reportfield)tradingagents/graph/scanner_setup.py(Phase 1b topology)tradingagents/graph/scanner_graph.py(agent instantiation)tradingagents/agents/scanners/macro_synthesis.py(Golden Overlap prompt)pyproject.toml(finvizfinance>=0.14.0)tests/unit/test_scanner_mocked.py(6 new tests for Finviz tools)