Fetch market data
Steps
- Validate the ticker list — strip whitespace, uppercase, dedupe, drop empties.
- Choose the data source in this preference order:
yfinanceif no broker keys configured (free, anonymous)alpaca-pyifALPACA_KEY+ALPACA_SECRETset (better data quality, included with Alpaca account)polygon-api-clientifPOLYGON_API_KEYset (real-time)
- Fetch in one batch call when the library supports it (yfinance does via
yf.download(tickers=[...])). Don't per-ticker loop in serial. - Record provenance in session memory:
{ticker, source, fetched_at, period, interval}. - On rate-limit error: backoff exponentially (cap 60s), retry up to 3 times; if still failing, surface the error per-ticker — don't fail the whole run.
- On missing ticker: report it; don't fabricate data.
Output shape
{
"AAPL": DataFrame(index=DatetimeIndex, columns=["Open", "High", "Low", "Close", "Volume"]),
"MSFT": DataFrame(...),
...
}
Failure modes to avoid
- Per-ticker serial fetch in a loop (slow + multiplies rate-limit risk).
- Silent failure on missing tickers.
- Caching forever — quote data is stale within minutes during market hours.
- Hard-coded API keys.
- Calling broker WebSocket subscriptions during a one-shot analysis (paid streaming for a single read).