| 1 | """Pure, provider-neutral sector leaderboard projection.""" |
| 2 | from __future__ import annotations |
| 3 | |
| 4 | from collections import defaultdict |
| 5 | from typing import Iterable |
| 6 | |
| 7 | |
| 8 | def normalize_sector(value: str) -> tuple[str, str]: |
| 9 | key = " ".join(str(value).casefold().split()) |
| 10 | aliases = {"financial services": ("financials", "Financials"), "financials": ("financials", "Financials"), "consumer cyclical": ("consumer-discretionary", "Consumer Discretionary"), "consumer discretionary": ("consumer-discretionary", "Consumer Discretionary"), "health care": ("healthcare", "Healthcare"), "healthcare": ("healthcare", "Healthcare")} |
| 11 | return aliases.get(key, (key.replace(" ", "-"), value.strip().title())) |
| 12 | |
| 13 | |
| 14 | def build_sector_leaderboard(candidates: Iterable[dict]) -> dict: |
| 15 | # Candidate selection happens by authoritative global identity before a |
| 16 | # duplicate can occupy a ranked sector slot. |
| 17 | winners: dict[str, dict] = {} |
| 18 | for candidate in candidates: |
| 19 | if not candidate.get("globalInstrumentId") or not candidate.get("sector") or candidate.get("score") is None: |
| 20 | continue |
| 21 | identity = str(candidate["globalInstrumentId"]) |
| 22 | prior = winners.get(identity) |
| 23 | key = (-candidate["score"], -int(candidate.get("evidenceCoverage") or 0), str(candidate.get("ticker") or "").upper(), identity) |
| 24 | if prior is None or key < (-prior["score"], -int(prior.get("evidenceCoverage") or 0), str(prior.get("ticker") or "").upper(), identity): |
| 25 | winners[identity] = dict(candidate) |
| 26 | grouped: dict[str, list[dict]] = defaultdict(list) |
| 27 | labels: dict[str, str] = {} |
| 28 | for candidate in winners.values(): |
| 29 | normalized, label = normalize_sector(candidate["sector"]); grouped[normalized].append(candidate); labels.setdefault(normalized, label) |
| 30 | sectors=[] |
| 31 | for normalized in sorted(grouped): |
| 32 | stocks = sorted(grouped[normalized], key=lambda c: (-c["score"], -int(c.get("evidenceCoverage") or 0), str(c.get("ticker") or "").upper(), str(c["globalInstrumentId"])))[:5] |
| 33 | sectors.append({"sector": labels[normalized], "normalizedSector": normalized, "stocks": stocks}) |
| 34 | return {"sectors": sectors} |