Files
ProStock/tests/test_factor_engine_metadata.py
liaozhaorun 2bb7718dd1 feat(factors): 集成 metadata 模块,支持按名称注册因子
- 新增 add_factor_by_name() 方法,从 metadata 查询 DSL 表达式并注册
- FactorEngine 支持可选的 metadata_path 参数初始化
- 将 regression.ipynb 和 learn_to_rank.ipynb 转换为 Python 脚本
- 新增 test_factor_engine_metadata.py 测试文件
2026-03-11 22:54:52 +08:00

107 lines
3.7 KiB
Python

"""FactorEngine 与 Metadata 集成测试。
测试 add_factor_by_name 方法的功能。
"""
import pytest
from src.factors import FactorEngine
from src.factors.metadata import FactorManager
class TestFactorEngineMetadataIntegration:
"""测试 FactorEngine 与 Metadata 的集成功能。"""
@pytest.fixture
def metadata_file(self):
"""使用 data 目录下的 factors.jsonl 文件。"""
return "data/factors.jsonl"
def test_init_without_metadata(self):
"""测试不启用 metadata 时初始化引擎。"""
engine = FactorEngine()
assert engine._metadata is None
def test_init_with_metadata(self, metadata_file):
"""测试启用 metadata 时初始化引擎。"""
engine = FactorEngine(metadata_path=metadata_file)
assert engine._metadata is not None
assert isinstance(engine._metadata, FactorManager)
def test_add_factor_by_name_success(self, metadata_file):
"""测试从 metadata 成功添加因子。"""
engine = FactorEngine(metadata_path=metadata_file)
# 添加 return_5 因子
result = engine.add_factor_by_name("return_5")
# 验证链式调用返回自身
assert result is engine
# 验证因子已注册
assert "return_5" in engine.list_registered()
def test_add_factor_by_name_with_alias(self, metadata_file):
"""测试使用别名添加因子。"""
engine = FactorEngine(metadata_path=metadata_file)
# 使用不同名称注册 metadata 中的因子
engine.add_factor_by_name("my_ma", "ma_5")
# 验证使用别名注册的因子
assert "my_ma" in engine.list_registered()
assert "ma_5" not in engine.list_registered()
def test_add_factor_by_name_not_found(self, metadata_file):
"""测试添加不存在的因子时抛出异常。"""
engine = FactorEngine(metadata_path=metadata_file)
with pytest.raises(ValueError) as exc_info:
engine.add_factor_by_name("nonexistent_factor")
assert "未找到因子" in str(exc_info.value)
assert "nonexistent_factor" in str(exc_info.value)
def test_add_factor_by_name_without_metadata(self):
"""测试未配置 metadata 时调用 add_factor_by_name 抛出异常。"""
engine = FactorEngine() # 不传入 metadata_path
with pytest.raises(RuntimeError) as exc_info:
engine.add_factor_by_name("return_5")
assert "未配置 metadata 路径" in str(exc_info.value)
def test_chain_calls(self, metadata_file):
"""测试链式调用。"""
engine = FactorEngine(metadata_path=metadata_file)
# 链式添加多个因子
(
engine.add_factor_by_name("return_5")
.add_factor_by_name("ma_5")
.add_factor_by_name("custom_ma20", "ma_20")
)
# 验证所有因子都已注册
assert "return_5" in engine.list_registered()
assert "ma_5" in engine.list_registered()
assert "custom_ma20" in engine.list_registered()
def test_add_factor_by_name_preserves_existing_add_factor(self, metadata_file):
"""测试 add_factor_by_name 不影响原有的 add_factor 方法。"""
engine = FactorEngine(metadata_path=metadata_file)
# 使用 add_factor 添加字符串表达式
engine.add_factor("manual_factor", "ts_mean(close, 10)")
# 使用 add_factor_by_name 添加 metadata 因子
engine.add_factor_by_name("return_5")
# 验证两者都正常工作
assert "manual_factor" in engine.list_registered()
assert "return_5" in engine.list_registered()
if __name__ == "__main__":
pytest.main([__file__, "-v"])