trader.persistence.news_archive module¶
Repository for the historical news archive and its coverage spans.
Separate from trader/persistence/news.py-style live storage on purpose: there is none. The live path records what it saw into decisions.inputs_json and never reads a news table. This one accumulates backwards from Alpaca’s archive so a past decision can be replayed on the news it would have had.
- class trader.persistence.news_archive.NewsArchiveRepository(session_factory)[source]¶
Bases:
objectReads and writes archived news, and tracks which spans were fetched.
- Parameters:
session_factory (sessionmaker[Session])
- save_items(items)[source]¶
Insert archived items, skipping any already held. Returns inserted count.
The symbol comes from each item rather than from an argument, so a caller cannot file one symbol’s story under another’s ticker — the mistake save_bars(symbol, …) leaves available by ignoring Bar.symbol.
An article already present is left exactly as it was. Benzinga corrects stories in place under the same id, and the decision being replayed was made on the original wording.
- Parameters:
items (Sequence[ArchivedNewsItem])
- Return type:
int
- load_items(symbol, start, end)[source]¶
Archived items published in [start, end), most recent first.
Half-open, and that is the point. The replay’s claim is that the model saw nothing published at or after the decision instant, so an inclusive end would hand it the headline it is being scored for anticipating. load_bars is inclusive at both ends because a bar timestamp names a whole period; a publication instant names a moment.
Most recent first because that is the order the provider returns, the prompt renders, and news_fingerprint digests. The article_id tiebreak makes a same-second batch deterministic: without it two stories published in the same second come back in whatever order SQLite scans, and one replay could build a different prompt from the next.
- Parameters:
symbol (str)
start (datetime)
end (datetime)
- Return type:
list[NewsItem]
- covered_ranges(symbol)[source]¶
Merged, sorted spans known to have been fetched.
- Parameters:
symbol (str)
- Return type:
list[tuple[datetime, datetime]]
- record_coverage(symbol, start, end)[source]¶
Record a fetched span, merging it into any it overlaps or touches.
Read, delete and insert in one transaction, for BarRepository’s reason: split apart, two callers each rewrite the row set from a stale read and the later commit silently discards the other’s span.
- Parameters:
symbol (str)
start (datetime)
end (datetime)
- Return type:
None
- missing_ranges(symbol, start, end)[source]¶
Sub-spans of [start, end) that have never been fetched.
Half-open like load_items, and unsnapped: news has no bar grid, so there is no width to floor onto and no adjacency but exact contact.
- Parameters:
symbol (str)
start (datetime)
end (datetime)
- Return type:
list[tuple[datetime, datetime]]