"""场景二 · 市场业务真实性:养卡骗补检测(R9)。 检测"脉冲式增长 + 规律性衰减"的周期性造假:渠道每月新增大量用户订购, 固定周期后这些用户集中退订(骗补后弃养)。结合佣金与业务质量匹配度。 """ from __future__ import annotations from dataclasses import dataclass @dataclass class CohortPoint: """某新增批次(cohort)在第 N 个月的留存率。""" month_index: int retention: float # 0-1 @dataclass class ChurnFinding: cliff_month: int | None max_drop: float pulse_then_decay: bool def detect_pulse_decay( retention_curve: list[CohortPoint], cliff_drop: float = 0.5, ) -> ChurnFinding: """识别留存曲线中的"断崖式集中退订"。 若某月留存相对上月骤降超过 cliff_drop(默认 50%),判为规律性衰减。 """ ordered = sorted(retention_curve, key=lambda p: p.month_index) max_drop = 0.0 cliff_month: int | None = None for prev, cur in zip(ordered, ordered[1:], strict=False): drop = prev.retention - cur.retention if drop > max_drop: max_drop = drop if drop >= cliff_drop: cliff_month = cur.month_index return ChurnFinding( cliff_month=cliff_month, max_drop=round(max_drop, 3), pulse_then_decay=cliff_month is not None, ) def commission_quality_mismatch( commission_paid: float, active_ratio: float, zero_usage_ratio: float, ) -> float: """佣金与业务质量不匹配度(0-1)。 active_ratio:仍活跃用户占比;zero_usage_ratio:零通话/零流量用户占比。 佣金已发但活跃低、零使用高 → 不匹配度高。 """ if commission_paid <= 0: return 0.0 mismatch = 0.6 * zero_usage_ratio + 0.4 * (1 - active_ratio) return round(min(max(mismatch, 0.0), 1.0), 3) def churn_risk_score(finding: ChurnFinding, mismatch: float) -> float: """综合评分:断崖退订 + 佣金质量不匹配。""" if not finding.pulse_then_decay: return round(0.3 * mismatch, 3) base = 0.4 + 0.4 * finding.max_drop + 0.2 * mismatch return round(min(base, 1.0), 3) def build_rationale(finding: ChurnFinding, mismatch: float) -> str: if finding.pulse_then_decay: return ( f"渠道新增用户在第 {finding.cliff_month} 个月出现断崖式集中退订" f"(最大单月留存骤降 {finding.max_drop:.0%}),呈" f"'脉冲式增长 + 规律性衰减'特征;佣金与业务质量不匹配度 {mismatch:.0%}," f"高度疑似养卡骗补(骗补后弃养)。" ) return ( f"未见明显断崖退订,但佣金与业务质量不匹配度为 {mismatch:.0%},建议关注。" )