trader.ranking.base module¶
What a ranker takes, what it returns, and the ordering used without one.
A ranker never sees a strategy, a broker, an executor or a repository — the same discipline daemon/ follows. It takes value objects and returns an order. That is what lets it be tested without a model and swapped without touching the pipeline.
- trader.ranking.base.SOURCE_CONFIDENCE_ORDERING_ENABLED = 'confidence_ordering_enabled'¶
pipeline_config.confidence_ordering_enabled forced this order, bypassing whatever ranker was configured (issue #86). Distinct from SOURCE_FALLBACK_CONFIDENCE on purpose: that source means “no ranker was usable”; this one means “a ranker may well have been usable, an operator chose not to use it” — collapsing the two would misreport why a cycle’s order was what it was.
- trader.ranking.base.SOURCE_LLM = 'llm'¶
How an order was arrived at. Recorded on every decision row, so a log line or a stored row never claims a ranking basis it did not have.
- class trader.ranking.base.Candidate(symbol, confidence, reason, last_close, comparables)[source]¶
Bases:
objectOne approved BUY waiting on capital — the ranker’s whole input.
confidence is float | None rather than float: LlmStrategy puts one in Signal.indicators, and the rule strategies put nothing there. None means “this strategy does not report one”, which is a different claim from 0.0 and must stay distinguishable.
- Parameters:
symbol (str)
confidence (float | None)
reason (str)
last_close (Decimal)
comparables (Comparables)
- symbol: str¶
- confidence: float | None¶
- reason: str¶
- last_close: Decimal¶
- comparables: Comparables¶
- class trader.ranking.base.Ranker(*args, **kwargs)[source]¶
Bases:
ProtocolOrders approved candidates. Never raises, never vetoes, never sizes.
- rank(candidates)[source]¶
Return an order over candidates, best first.
The result must be a permutation of exactly the symbols passed in: never shorter, never longer, never containing a symbol nobody proposed. A ranker that could drop a candidate would be vetoing, which is deliberately not its job — every candidate has already been approved by its own per-symbol decision one call earlier.
- class trader.ranking.base.Ranking(order, source, notes=<factory>, inputs=<factory>)[source]¶
Bases:
objectAn order over candidate symbols, and how it was arrived at.
- Parameters:
order (tuple[str, ...])
source (str)
notes (Mapping[str, str])
inputs (Mapping[str, object])
- order: tuple[str, ...]¶
Best first. Always a permutation of exactly the candidate symbols.
- source: str¶
- notes: Mapping[str, str]¶
Symbol -> the ranker’s own words about it. Empty on every fallback path.
- inputs: Mapping[str, object]¶
Provenance for decisions.inputs_json.
- trader.ranking.base.fallback_ranking(candidates)[source]¶
Confidence descending, ties broken on symbol ascending.
Used whenever a model ranking is unavailable or unusable. Safe as a default precisely because ranking only orders: every candidate here has already passed its own decision and must still clear every guardrail, so a degraded order cannot unlock risk — it only spends the headroom in a less informed sequence. Refusing to trade at all on a ranker outage would make a dead endpoint a single point of failure for trading, which is the shape the discovery rules forbid.
Ties break on symbol so a cycle is reproducible.