fix(caliber): 流动/速动比率改「倍」口径 + 判定层同量纲直判(ASK-20260924-11 任总放行)
ci/woodpecker/push/main Pipeline failed
ci/woodpecker/push/main Pipeline failed
- caliber_units: F_CURRENT_RATIO/F_QUICK_RATIO 由 FACTOR_PERCENT(×100) 退场为 FACTOR_IDENTITY;declared_unit=倍 / caliber=倍(无量纲)/ evidence 改引 v2.1 锚;F_GROSS_MARGIN 保持 ×100 不动 - 引用面同步 7 文件:alert_generator / kpi_unit_crosscheck / migrate_...20260916 横幅 / 三个测试套件;self-test 两条改倍口径期望 yellow 口径: CMA-CALIBER-v2.1/kpi-unit@2026-09-24 取代 2a 之两项;其余比率类仍按裁定2a 百分比口径
This commit is contained in:
@@ -25,7 +25,9 @@ from scripts.alert_generator import generate_and_push, run_alert_check
|
||||
#: 固定「当月」= 2026-09 → 窗口 = 2026-04 ~ 2026-09(口径复算不依赖真实时钟)
|
||||
NOW = datetime(2026, 9, 19, 10, 0)
|
||||
|
||||
RED_EXPR = "<58.4" # 0<实测<10 比值形态不触发 dimension_suspect(见裁定2a 降级门)
|
||||
#: 降级门口径见 `app/utils/caliber_units.suspected_unit_mismatch`(阈值量级 <100 非百分数写法
|
||||
#: 且实测 14.45 非比率量级 ⇒ 不触发;与倍口径两项 F_CURRENT_RATIO/F_QUICK_RATIO 无关)
|
||||
RED_EXPR = "<58.4"
|
||||
|
||||
|
||||
def _ent(db, eid, status, name=None):
|
||||
|
||||
@@ -39,7 +39,10 @@ NOW = datetime(2026, 9, 22, 10, 0)
|
||||
PERIOD = "2026-09"
|
||||
|
||||
#: 阈值/实测形态沿用同族既有用例(test_alert_caliber_r1r4_20260919):
|
||||
#: 避免命中裁定2a「疑似单位错配」降级门(阈值百分数写法 + 实测比率量级)
|
||||
#: 形态前提按 `CMA-CALIBER-v2.1/kpi-unit@2026-09-24` + 裁定2a 复核后重写:
|
||||
#: 本用例阈值 `"<58.4"` **不是**百分数写法(量级 <100)、实测 14.45 **不是**比率量级(>10)
|
||||
#: ⇒ 按 `app/utils/caliber_units.suspected_unit_mismatch` 判据,**任何口径下都不触发降级门**;
|
||||
#: 与两个倍口径指标(F_CURRENT_RATIO / F_QUICK_RATIO,走对照表直判)无关。
|
||||
RED_EXPR = "<58.4"
|
||||
ACTUAL = 14.45
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""财务口径裁定 2026-09-17 落地测试(裁定1 / 2a / 2b)
|
||||
|
||||
依据:`wecom-finance/reports/CMA_口径裁定_20260917.md`
|
||||
依据:`wecom-finance/reports/CMA_口径裁定_20260917.md`(裁定1 / 2a / 2b)
|
||||
+ `wecom-finance/reports/CMA_口径裁定_20260924_比率类单位口径_取代2a两指标.md`
|
||||
(`CMA-CALIBER-v2.1/kpi-unit@2026-09-24`:**取代 2a 之 `F_CURRENT_RATIO` / `F_QUICK_RATIO` 两项**
|
||||
→ 改「倍」、无量纲直判、不再 ×100;其余比率类仍按 2a 百分比口径)
|
||||
· 裁定1:现金流「投资活动净额=0」= 本期无投资活动,**按 0 如实参与判定**(二维映射 + 标注);
|
||||
· 裁定2a:比率类 KPI 统一「百分比(%)」口径(取数×100),未核对/疑似错配**不推送**;
|
||||
· 裁定2a:其余比率类 KPI 统一「百分比(%)」口径(取数×100),未核对/疑似错配**不推送**;
|
||||
· 裁定2b:预警期间由「当月硬编码」→「最近可用期间」(排除 2026-H1/H2 伪期间)。
|
||||
"""
|
||||
import pytest
|
||||
@@ -65,14 +68,19 @@ class TestRuling1InvestingZero:
|
||||
assert c["classified"] is False and "缺失" in c["reason"]
|
||||
|
||||
|
||||
# ───────────────────────── 裁定2a:单位口径 ─────────────────────────
|
||||
# ───────────── 单位口径:裁定2a(百分比)+ v2.1 取代两项(倍)─────────────
|
||||
|
||||
class TestRuling2aCaliber:
|
||||
def test_current_ratio_normalized_to_percent(self):
|
||||
cal = resolve_caliber(1.29, _K("F_CURRENT_RATIO", "%", ">=200", ">=150", "<150"))
|
||||
assert cal["status"] == "normalized" and cal["factor"] == 100
|
||||
assert round(cal["value"], 2) == 129.0
|
||||
assert "口径归一" in cal["note"]
|
||||
def test_current_ratio_multiple_caliber_identity(self):
|
||||
"""`F_CURRENT_RATIO` 已按 v2.1 改「倍」口径 → **同量纲直判**(factor=1,不得再 ×100)。
|
||||
|
||||
反向量纲回归:只改 DB 不改判定层时 1.29×100=129 去比 `>=2.0` 会**恒绿**(比原「恒红」更坏);
|
||||
此处即锁「不被 ×100」这一反向风险。
|
||||
"""
|
||||
cal = resolve_caliber(1.29, _K("F_CURRENT_RATIO", "倍", ">=2.0", ">=1.0", "<1.0"))
|
||||
assert cal["status"] == "ok" and cal["factor"] == 1
|
||||
assert cal["value"] == 1.29
|
||||
assert cal["note"] is None, "倍口径直判无「口径归一」说明"
|
||||
|
||||
def test_percent_class_not_multiplied(self):
|
||||
"""返利率/收入增长率等取数已是百分数 → 因子 1(再 ×100 会反向越界)"""
|
||||
@@ -148,18 +156,18 @@ class TestGateAndDryRun:
|
||||
assert st["dimension_suspect"] == 1 and st["suspect_kpis"]
|
||||
assert db.query(KPIAlert).count() == 0
|
||||
|
||||
def test_listed_ratio_kpi_alert_uses_normalized_value(self, db: Session):
|
||||
"""表内比率 KPI:1.29 → 129% 参与判定,且消息里带口径归一说明"""
|
||||
kpi = create_test_kpi(db, kpi_code="F_CURRENT_RATIO", kpi_name="流动比率", unit="%",
|
||||
threshold_green=">=200", threshold_yellow=">=150", threshold_red="<150")
|
||||
def test_listed_ratio_kpi_alert_judged_in_multiple_caliber(self, db: Session):
|
||||
"""v2.1 两项按「倍」口径**同量纲直判**:1.29 落 [1.0,2.0) → 黄,且消息不带「口径归一」"""
|
||||
kpi = create_test_kpi(db, kpi_code="F_CURRENT_RATIO", kpi_name="流动比率", unit="倍",
|
||||
threshold_green=">=2.0", threshold_yellow=">=1.0", threshold_red="<1.0")
|
||||
db.add(KPIValue(entity_id=1, kpi_id=kpi.id, period="2026-08", actual_value=1.29))
|
||||
db.commit()
|
||||
st = {}
|
||||
n = run_alert_check(db, period="2026-08", dry_run=True, stats=st)
|
||||
assert n == 1 and st["planned"][0]["level"] == "red"
|
||||
assert st["planned"][0]["actual"] == 129.0 and st["planned"][0]["factor"] == 100
|
||||
assert "口径归一" in st["planned"][0]["message"]
|
||||
assert st["normalized"] == 1
|
||||
assert n == 1 and st["planned"][0]["level"] == "yellow"
|
||||
assert st["planned"][0]["actual"] == 1.29 and st["planned"][0]["factor"] == 1
|
||||
assert "口径归一" not in st["planned"][0]["message"]
|
||||
assert st["normalized"] == 0
|
||||
|
||||
def test_dry_run_writes_nothing(self, db: Session):
|
||||
kpi = create_test_kpi(db, kpi_code="T_DRY", kpi_name="dry", unit="万元",
|
||||
|
||||
Reference in New Issue
Block a user