Files
sanguo_vnpy_v2/tests/factor/test_decay.py
T

80 lines
2.6 KiB
Python

# tests/factor/test_decay.py
"""衰减判定 TDD——spec §4.2 决议 E(成熟度门)/F(三条件)/C(集体水位)."""
from sanguo_factor.decay import (
ABSOLUTE_FLOOR,
COLLECTIVE_MEDIAN_FLOOR,
CONSECUTIVE_MONTHS,
RELATIVE_DROP,
collective_level,
judge_factor,
)
def pts(*ts_pairs):
"""ts_pairs: ("2026-05", 3.1) 形元组序列→月度点 list."""
return [{"month": m, "t": t} for m, t in ts_pairs]
def test_not_promoted_never_judged():
v = judge_factor(pts(("2026-07", 0.5)), promotion_t=None, factor="fa_x")
assert v.state == "not_promoted" and v.months_consecutive == 0
def test_no_data():
v = judge_factor([], promotion_t=4.0, factor="fa_x")
assert v.state == "no_data"
def test_ok_when_t_strong():
# 晋级基准 4.01,当前 3.2: ratio=0.80>0.5 且 t>=2.0 → ok
v = judge_factor(pts(("2026-07", 3.2)), promotion_t=4.01, factor="p")
assert v.state == "ok" and v.months_consecutive == 0
assert v.ratio == 3.2 / 4.01
def test_yellow_one_month():
v = judge_factor(pts(("2026-07", 1.2)), promotion_t=4.01, factor="p")
assert v.state == "yellow" and v.months_consecutive == 1
def test_alert_three_consecutive_months():
v = judge_factor(
pts(("2026-04", 3.9), ("2026-05", 1.1), ("2026-06", 1.0), ("2026-07", 0.9)),
promotion_t=4.01, factor="p")
assert v.state == "alert" and v.months_consecutive == 3
def test_two_months_still_yellow():
v = judge_factor(pts(("2026-06", 1.1), ("2026-07", 1.0)), promotion_t=4.01, factor="p")
assert v.state == "yellow" and v.months_consecutive == 2
def test_gap_month_breaks_streak():
# 4 月弱→5 月缺→6-7 月弱:序列断月,连续计数只算尾部 2 个月
v = judge_factor(
pts(("2026-04", 1.1), ("2026-06", 1.0), ("2026-07", 0.9)),
promotion_t=4.01, factor="p")
assert v.state == "yellow" and v.months_consecutive == 2
def test_high_t_but_small_ratio_not_decay():
# 晋级基准 10.0(超强),当前 4.5: ratio=0.45<0.5 但 t=4.5>=2.0 → 未触绝对地板,不算衰减月
v = judge_factor(pts(("2026-07", 4.5)), promotion_t=10.0, factor="p")
assert v.state == "ok"
def test_constants_unchanged():
assert (RELATIVE_DROP, ABSOLUTE_FLOOR, CONSECUTIVE_MONTHS, COLLECTIVE_MEDIAN_FLOOR) \
== (0.5, 2.0, 3, 1.0)
def test_collective_level_median_and_flag():
assert collective_level([3.0, 1.2, 0.4]) == {
"median": 1.2, "floor": 1.0, "is_collective_decay": False, "n": 3}
r = collective_level([3.0, 0.8, 0.4])
assert r["is_collective_decay"] is True and r["median"] == 0.8
def test_collective_level_empty():
assert collective_level([])["is_collective_decay"] is False