trader.news.alpaca_news module¶
Alpaca news adapter.
Alpaca’s news is 100% Benzinga and shares zero headlines with the yfinance feed (0 of 10 overlap on all five symbols probed over the same 30-day window, 2026-08-14). It is a second corpus, not a replacement for the first — which is why this provider exists alongside YFinanceNewsProvider under MergedNewsProvider rather than in place of it.
Two payload facts, both measured against the live API on 2026-08-15, both of which the design would be wrong without:
Omitting `start` returns the whole archive, not the current day the SDK’s own NewsRequest docstring claims (272 items came back for ANNX). The window this adapter sends is therefore deliberate, and asserted in tests.
`summary` is usually empty, because News.summary is typed str and Alpaca sends “” rather than omitting the key: 0 of 24 ANNX items and 0 of 37 ITRG items carried one over 30 days. content fills the gap in only 3 of 23 and 7 of 37 cases, so it is not requested at all.
limit caps the total returned, not a page — NewsClient.get_news paginates internally at 50. A limit read as a page size is what made a first coverage probe report a uniform 50 items for all 14 symbols.
- class trader.news.alpaca_news.AlpacaNewsProvider(api_key, api_secret, *, lookback_hours=168.0)[source]¶
Bases:
objectRecent news from Alpaca’s news API (Benzinga).
- Parameters:
api_key (str)
api_secret (str)
lookback_hours (float)
- get_recent_news(symbol, limit=10)[source]¶
Most recent items first, capped at limit.
- Raises:
MarketDataError – the provider call failed.
- Parameters:
symbol (str)
limit (int)
- Return type:
list[NewsItem]
- get_news_between(symbol, start, end)[source]¶
Every archived article for symbol published in [start, end).
The archive fetch, not the trading path: get_recent_news bounds itself by lookback_hours and a limit because a prompt wants the newest few items, while a backfill wants everything in a span someone named.
limit=None is what fetches a whole window. NewsClient.get_news paginates internally at 50 and limit caps the total returned, so any number here silently truncates the archive — measured, that is how a first coverage probe came to report exactly 50 items for all 14 symbols.
An article with no id is dropped: the id is the archive’s key, and an unkeyed row would re-insert on every backfill rather than dedupe.
- Raises:
MarketDataError – the provider call failed. Deliberately not caught here — a backfill that swallowed an outage would record the span as covered and leave a permanent hole reading as “this symbol had no news”, which is the ambiguity NewsArchiveCoverage exists to prevent.
- Parameters:
symbol (str)
start (datetime)
end (datetime)
- Return type:
list[ArchivedNewsItem]