- 新增 add_factor_by_name() 方法,从 metadata 查询 DSL 表达式并注册 - FactorEngine 支持可选的 metadata_path 参数初始化 - 将 regression.ipynb 和 learn_to_rank.ipynb 转换为 Python 脚本 - 新增 test_factor_engine_metadata.py 测试文件
107 lines
3.7 KiB
Python
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"])
|