Files
InternalAuditInterprise/backend/app/scenarios/churn_fraud.py
T

86 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""场景二 · 市场业务真实性:养卡骗补检测(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%},建议关注。"
)