"""端到端集成测试:验证 110 个 Paper Factors 能被本地引擎计算。 测试目标: 1. 加载 paper factors 库 2. 使用 LocalFactorEvaluator 计算每个因子 3. 验证输出形状为 (M, T) 且不含全 NaN 4. 统计成功率和跳过数 运行命令:uv run pytest tests/test_factorminer_e2e.py -v """ import pytest def test_paper_factors_e2e(): """端到端测试:验证 110 个 Paper Factors 能被本地引擎计算。 注意:此测试需要数据库中有 pro_bar 数据。 如果数据不足,会在计算时失败。 """ from src.factorminer.core.library_io import import_from_paper from src.factorminer.evaluation.local_engine import LocalFactorEvaluator # 1. 加载 paper factors 库 library = import_from_paper() factors = library.list_factors() total = len(factors) print(f"\n[e2e] 总计加载 {total} 个因子") # 2. 过滤 unsupported 因子 supported_factors = [f for f in factors if not f.metadata.get("unsupported", False)] unsupported_count = total - len(supported_factors) print(f"[e2e] 可计算因子 {len(supported_factors)} 个") print(f"[e2e] 跳过(未实现算子){unsupported_count} 个") if not supported_factors: print("[e2e] 没有可计算的因子,测试跳过") pytest.skip("No supported factors to test") # 3. 实例化 LocalFactorEvaluator evaluator = LocalFactorEvaluator( start_date="20200101", end_date="20201231", ) # 4. 批量计算每个因子 success_count = 0 fail_count = 0 skip_count = 0 specs = [(f.name, f.formula) for f in supported_factors] print(f"[e2e] 开始批量计算 {len(specs)} 个因子...") try: results = evaluator.evaluate(specs) except Exception as e: print(f"[e2e] 批量计算失败: {e}") pytest.fail(f"Batch evaluation failed: {e}") # 5. 验证结果 for name, result in results.items(): if result is None: fail_count += 1 continue # 检查形状 if result.ndim != 2: print(f"[e2e] 因子 {name} 形状错误: {result.ndim}D(期望 2D)") fail_count += 1 continue # 检查是否全 NaN if np.isnan(result).all(): print(f"[e2e] 因子 {name} 输出全为 NaN") fail_count += 1 continue success_count += 1 print( f"[e2e] 成功 {success_count}/{total}," f"跳过 {skip_count} 个,失败 {fail_count} 个" ) # 断言:至少 50% 的因子能成功计算(宽松标准) success_rate = success_count / total assert success_rate >= 0.5, f"成功率 {success_rate:.1%} 低于 50% 阈值" if __name__ == "__main__": import numpy as np from src.factorminer.core.library_io import import_from_paper from src.factorminer.evaluation.local_engine import LocalFactorEvaluator # 手动运行测试 library = import_from_paper() factors = library.list_factors() total = len(factors) print(f"\n[e2e] 总计加载 {total} 个因子") supported_factors = [f for f in factors if not f.metadata.get("unsupported", False)] unsupported_count = total - len(supported_factors) print(f"[e2e] 可计算因子 {len(supported_factors)} 个") print(f"[e2e] 跳过(未实现算子){unsupported_count} 个") if supported_factors: evaluator = LocalFactorEvaluator( start_date="20200101", end_date="20201231", ) specs = [(f.name, f.formula) for f in supported_factors] print(f"[e2e] 开始批量计算 {len(specs)} 个因子...") results = evaluator.evaluate(specs) print(f"[e2e] 批量计算完成,共 {len(results)} 个结果")