66619c17d8
fund_ccc(-)/fund_send_total_12m(不定正向注册待实证)/fund_gdhs_chg(-)/ fund_topholder_chg(+)/fund_ep_vb(+)/fund_bp_vb(+);注册总数 69→75 (P0 32+P1 37+P1-B 6,既有计数契约同步更新);batch e2e 锁死 vb+dividend 域级引用瘦身 join 路径。
73 lines
3.0 KiB
Python
73 lines
3.0 KiB
Python
# tests/factor/test_fundamental_p1b_library.py
|
||
"""P1-B 批财务因子表达式库: 四新域 6 个注册(5 因子,D14 双注册)契约锁定.
|
||
|
||
契约:
|
||
- 表达式裸标识符 ⊆ adapter 特征列 + close/log/cs_rank
|
||
- 全部 cs_rank 一层截面;E08/E12 负 IC 取负,E11 不定按正向注册待实证
|
||
- E13/D14 正向;vb 两因子直接消费 vb 域日频列(不经 close×share_capital)
|
||
"""
|
||
import re
|
||
import sys, os
|
||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "vnpy_v4.4.0")))
|
||
|
||
import pytest
|
||
|
||
from sanguo_factor import fundamental_library # noqa: F401 import 即注册
|
||
from sanguo_factor.fundamental_adapter import FEATURE_COLUMNS
|
||
from sanguo_factor.fundamental_library import FUNDAMENTAL_P1B_FACTORS
|
||
from sanguo_factor.registry import list_factors, get_factor
|
||
|
||
|
||
@pytest.fixture(autouse=True)
|
||
def _ensure_fundamental_registered():
|
||
"""其它测试模块清空 _REGISTRY 后逐测试幂等重注册(顺序依赖前科)."""
|
||
fundamental_library._register_all()
|
||
|
||
|
||
_ALLOWED = set(FEATURE_COLUMNS) | {"close", "cs_rank", "log"}
|
||
|
||
|
||
def test_p1b_6_factors_registered():
|
||
facs = {f["name"]: f for f in list_factors("fundamental")}
|
||
names = {n for n, _e, _d, _ic in FUNDAMENTAL_P1B_FACTORS}
|
||
assert len(names) == 6, f"P1-B 应 6 个注册(5 因子,D14 双注册),实际 {len(names)}"
|
||
for name in names:
|
||
assert name in facs, f"{name} 未注册"
|
||
assert facs[name]["category"] == "fundamental"
|
||
|
||
|
||
def test_p1b_expressions_only_reference_feature_columns():
|
||
for name, expression, _d, _ic in FUNDAMENTAL_P1B_FACTORS:
|
||
idents = set(re.findall(r"[A-Za-z_][A-Za-z0-9_]*", expression))
|
||
bad = idents - _ALLOWED
|
||
assert not bad, f"{name} 引用了未产出列: {bad} in {expression}"
|
||
|
||
|
||
def test_p1b_all_cross_sectional_rank_one_layer():
|
||
for name, expression, _d, _ic in FUNDAMENTAL_P1B_FACTORS:
|
||
assert expression.startswith("cs_rank("), f"{name}: {expression}"
|
||
assert expression.endswith(")")
|
||
|
||
|
||
def test_p1b_negative_ic_factors_flipped():
|
||
"""E08(CCC 低=效率高)/E12(户数降=筹码集中)取负;E13/D14/E11 正向."""
|
||
assert get_factor("fund_ccc")["expression"] == "cs_rank(-ccc)"
|
||
assert get_factor("fund_gdhs_chg")["expression"] == "cs_rank(-gdhs_chg)"
|
||
assert get_factor("fund_topholder_chg")["expression"] == "cs_rank(topholder_chg)"
|
||
# E11 方向不定(公告前+/除权后−混合)→ 正向注册,由 IC 实测定去留
|
||
assert get_factor("fund_send_total_12m")["expression"] == "cs_rank(send_total_12m)"
|
||
|
||
|
||
def test_p1b_vb_factors_consume_vb_columns():
|
||
"""D14 双注册直接消费 vb 域列(长史 1990 起含退市,分域验证用)."""
|
||
assert get_factor("fund_ep_vb")["expression"] == "cs_rank(ep_vb)"
|
||
assert get_factor("fund_bp_vb")["expression"] == "cs_rank(bp_vb)"
|
||
|
||
|
||
def test_p1b_registration_idempotent():
|
||
fundamental_library._register_all()
|
||
fundamental_library._register_all()
|
||
# P0 32 + P1 37 + P1-B 6 = 75
|
||
assert len(list_factors("fundamental")) == 75
|