Stock Analysis Demo — fomo2 + yahoo_finance + trtools2 → mastermind → trade signal
What this does
One command turns a stock ticker into an actionable trade signal grounded in real, live data:
- Picks the latest fomo2 markdown report (news + financial narrative).
- Pulls Yahoo Finance data (live quote, recent news, market context).
- Pulls trtools2 / QuestDB (recent OHLCV bars + a small set of technical indicators).
- Concatenates everything into a single ≤ 8 KB markdown brief.
- Feeds the brief to the mastermind arena (4 specialists + judge, real Ollama Cloud LLM).
- Maps the resulting
Decisionto aTradeSignal(BUY / SELL / HOLD with confidence + horizon).
Prereqs
- Python:
pip install -e .[knowledge]from the MAF repo root. - Ollama Cloud key in
.envasOLLAMA_API_KEY=.... - QuestDB running on
localhost:8812(PG-wire). For a dev box the existingquestdbcontainer handles this. The demo degrades gracefully if it's down — bars + indicators slots becomeNonewith an entry inpack.errors. - fomo2 reports in
../fomo2/output/analyze_*.md. Optional — if the dir is empty, the fomo2 slot becomesNone. - Yahoo Finance is reached via
yfinance(no API key needed). - The mastermind also reads optional Redis (
REDIS_URL) and Neo4j (NEO4J_URI) when set, but the demo runs without them.
The 1-line command
cd /home/trbck/workspace/MAF
PYTHONPATH=src python -m maf.arenas.mastermind.stock_analysis_cli \
--ticker AAPL --horizon 24h
Mock-agent fast path (no LLM calls, ~1s):
PYTHONPATH=src python -m maf.arenas.mastermind.stock_analysis_cli \
--ticker AAPL --no-real-agents
What the output looks like
Real run (live Ollama Cloud, 30–90s wall) prints a header to stdout:
==========================================================================================
STOCK_ANALYSIS — AAPL (horizon=24h)
==========================================================================================
recommendation : HOLD AAPL 24h
confidence : 0.620 dissent: 0.300
trade_signal : HOLD confidence=0.527
pack_md_chars : 4218 sources_with_data=6
pack_path : /tmp/maf_stock_pack_AAPL_20260507T093412Z.md
------------------------------------------------------------------------------------------
REASONING (truncated to 600 chars):
The fundamentals point to a steady AAPL position over the next 24h: live price
$195.42 sits comfortably in the upper half of the 52w range; RSI_14=62.5 is
elevated but not extreme; the latest fomo2 narrative highlights buyback +
guidance-raise momentum. RiskSkeptic flags that the VIX is at 13.2 (near multi-year
lows) which historically precedes mean-reverting volatility expansion — short-dated
upside is therefore capped. Memory citation 9c4a... (HOLD AAPL 24h, 2026-05-04)
directly analogous and supports HOLD. Recommend HOLD; a single-day window does
not justify a fresh long given the elevated RSI.
==========================================================================================
Plus a full JSON report at .boil/iterations/iter-011/artifacts/stock_analysis_<TICKER>.json containing:
pack— the full StockPack (each adapter's raw return)pack_md_chars+pack_md_path— the rendered brief (truncated to ≤ 8000 chars)decision— the mastermind Decision (recommendation, confidence, dissent, reasoning, argument_tree, arena_votes, memory_citations, graph_citations)trade_signal—{signal, confidence, horizon, rationale}consumer-side mappingerrors— any per-source fetch failures
How it works
┌─ fomo2_report ─────┐
│ (latest .md file) │
ticker ─► gather ┼─ yahoo_quote/news/ ┼─► render_pack_as_markdown
(par- │ overview │ │
allel)│ (yfinance) │ ▼
├─ questdb bars │ /tmp/maf_stock_pack_<T>_<ts>.md
│ (last N bars) │ │
└─ technical │ ▼
indicators │ MastermindArena.run(target=...)
(sma, ema, rsi…) │ │
│ ▼
│ Decision (recommendation,
│ confidence,
│ argument_tree,
│ memory_citations…)
│ │
│ ▼
└► decision_to_trade_signal
│
▼
TradeSignal {BUY|SELL|HOLD,
confidence,
horizon,
rationale}
Each gather step is wrapped in a fault-tolerant _safe_fetch_* shim that returns an _AdapterError sentinel on failure rather than raising — the brief still renders if a source is down. The mastermind itself follows the iter-7 phase graph: frame → gather (specialists) → graph_query → memory_retrieve → debate → judge → emit.
How to extend
- Add a data source — write a
_safe_fetch_<name>async function instock_analysis.py, add a coroutine to thecoroslist ingather_stock_pack, add a slot toStockPack, wire a_render_<name>block intorender_pack_as_markdown. The pack budget isPACK_MARKDOWN_MAX_CHARS = 8000total — section caps areSECTION_MAX_CHARS = 2000each, fomo2 excerpt atFOMO2_EXCERPT_MAX_CHARS = 1500. - Swap the question template —
_build_question(ticker, horizon)instock_analysis_cli.py. Keep the prompt explicit about what the source document contains. - Use it as a library —
gather_stock_pack(ticker)+render_pack_as_markdown(pack)are pure async / pure functions; you can call them outside the CLI.
Honest limitations
- fomo2 report selection is naive — we use the latest report regardless of whether it mentions the ticker. T-0066 (filed) wants topical filtering.
- trtools2 indicators — uses pandas-ta defaults (sma, ema, rsi, atr). The set is configurable via
--indicators sma_20 ema_50 .... - No live trading — TradeSignal is advisory. Wiring it to a paper-trade engine is a separate concern (see
oddsoddyfor that pattern). - Mastermind judge confidence is conservative — typical decisions land 0.4–0.7. Iter-9 backtest showed mastermind beats every constituent on a 14d window but can lose on noisier 7d windows (see T-0063).