trader.persistence.analyst_consensus module¶
Repository for analyst_consensus_history (issue #27).
Append-only writes from trader scan-universe; reads answer “what is the newest-enough opinion for each of these symbols”, which is the only question discover_symbols’s analyst-scan candidate source and scan-universe’s own freshness skip ever ask.
- class trader.persistence.analyst_consensus.AnalystConsensusRepository(session_factory)[source]¶
Bases:
objectWrites and reads analyst_consensus_history.
- Parameters:
session_factory (sessionmaker[Session])
- append(symbol, opinion, *, fetched_at, source)[source]¶
Record one fetch. Returns the new row id.
Always inserts — never upserts. A later fetch is evidence the consensus moved, not a correction of the earlier one.
- Parameters:
symbol (str)
opinion (AnalystOpinion)
fetched_at (datetime)
source (str)
- Return type:
int
- latest_for_symbols(symbols, *, max_age, now)[source]¶
The newest-per-symbol opinion, for symbols fetched within max_age.
A symbol with no row, or only a stale one, is simply absent from the result — the same “this source contributes nothing” degrade discover_symbols already gives an empty themes list, never an exception.
- Parameters:
symbols (Collection[str])
max_age (timedelta)
now (datetime)
- Return type:
dict[str, AnalystOpinion]
- history()[source]¶
Every row, oldest first — the full history a rank-persistence computation (issue #39) ranks over.
Unlike latest_for_symbols, this is not scoped to a symbol set or a freshness window: the rank-persistence screen’s whole point is comparing a symbol’s older readings against its newest one, so filtering to “fresh” here would defeat it. Bounded by how often trader scan-universe runs, not by index size, so a full-table read is fine for a report command; there is no unbounded growth path this needs to guard against yet.
- Return type:
list[ConsensusHistoryRow]
- class trader.persistence.analyst_consensus.ConsensusHistoryRow(symbol, fetched_at, strong_buy, recommendation_mean)[source]¶
Bases:
objectOne analyst_consensus_history row, reduced to what a rank-over-time read needs (issue #39) — deliberately not the full AnalystOpinion shape, since history() can return hundreds of rows and every extra field would be carried for nothing a caller here uses.
- Parameters:
symbol (str)
fetched_at (datetime)
strong_buy (int)
recommendation_mean (float | None)
- symbol: str¶
- fetched_at: datetime¶
- strong_buy: int¶
- recommendation_mean: float | None¶