"""合成行业内中位数筛选:按有效观测数设置最低组规模。""" import json from collections import defaultdict from decimal import Decimal as D from statistics import median rows = [("T1", "Tech", "10"), ("T2", "Tech", "20"), ("T3", "Tech", "30"), ("U1", "Utility", "4"), ("U2", "Utility", "6"), ("U3", "Utility", "8"), ("R1", "Rare", "2"), ("R2", "Rare", "4"), ("M1", None, "12"), ("T4", "Tech", None)] def screen(records, minimum=3): groups = defaultdict(list) for symbol, industry, pe in records: if industry is not None and pe is not None and D(pe) > 0: groups[industry].append(D(pe)) thresholds = {g: median(values) for g, values in groups.items() if len(values) >= minimum} results = {} for symbol, industry, pe in records: if industry is None: state = "missing_industry" elif pe is None: state = "missing_metric" elif industry not in thresholds: state = "small_group" else: state = "pass" if D(pe) > 0 and D(pe) <= thresholds[industry] else "fail" results[symbol] = state return thresholds, results, {g: len(values) for g, values in groups.items()} thresholds, result, counts = screen(rows) assert thresholds == {"Tech": D("20"), "Utility": D("6")} assert sorted(s for s, state in result.items() if state == "pass") == ["T1", "T2", "U1", "U2"] assert result["R1"] == result["R2"] == "small_group" assert result["M1"] == "missing_industry" and result["T4"] == "missing_metric" assert counts == {"Tech": 3, "Utility": 3, "Rare": 2} assert screen(list(reversed(rows))) == (thresholds, result, counts) print(json.dumps({"thresholds": {g: str(v) for g, v in thresholds.items()}, "valid_group_counts": counts, "states": result}, sort_keys=True))