feat: 量化引擎加固 — 新增测试 + 数据/因子/回测层优化
- 新增 finance/tests/ 6 个测试套件(agents/backtest/dao_upsert/factors/features/fundamental_lookahead) - 数据层: data_manager / dao 优化,新增 upsert 逻辑 - 因子层: 基本面因子抽象定位 _mapping、ROE/PE/PB 重构 - 回测层: vectorbt/engine 大改动(251 行),report 增强 - ML 层: features/backtest_integration 特征工程与回测优化 - CLI: agent_cli 重构 - config/settings 扩充配置项
This commit is contained in:
@@ -82,34 +82,46 @@ class MLStrategy(BaseStrategy):
|
||||
|
||||
|
||||
class MLBenchmark:
|
||||
"""ML 模型基准对比测试。"""
|
||||
"""ML 模型基准对比测试。
|
||||
|
||||
入参的 feature_engine 应已用模型训练集 fit 过(scaler/winsor/median 已缓存)。
|
||||
run() 对 **样本外测试数据**(test_factor_df/test_price_df)用 fit=False 转换后
|
||||
计算预测 IC,避免"同一时间段既训练又评估"的前视泄漏。
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
models: list[BaseModel],
|
||||
feature_engine: FeatureEngine,
|
||||
price_df: pd.DataFrame,
|
||||
factor_df: pd.DataFrame,
|
||||
test_factor_df: pd.DataFrame,
|
||||
test_price_df: pd.DataFrame,
|
||||
bt_engine: VectorBTEngine | None = None,
|
||||
):
|
||||
self.models = models
|
||||
self.feature_engine = feature_engine
|
||||
self.price_df = price_df
|
||||
self.factor_df = factor_df
|
||||
self.test_factor_df = test_factor_df
|
||||
self.test_price_df = test_price_df
|
||||
self.bt_engine = bt_engine or VectorBTEngine()
|
||||
|
||||
def run(self) -> pd.DataFrame:
|
||||
"""对比各模型的预测质量和回测表现。"""
|
||||
"""对比各模型在样本外测试集上的预测质量和回测表现。"""
|
||||
rows = []
|
||||
# 标签由规则(前视收益)决定,预测时可直接用同一 build_labels 构造,
|
||||
# 避免依赖 build(fit=False) 不产标签的语义。
|
||||
y_test = self.feature_engine.build_labels(self.test_price_df)
|
||||
X_test, _ = self.feature_engine.build(self.test_factor_df, self.test_price_df, fit=False)
|
||||
if X_test is None or X_test.empty or y_test is None or y_test.dropna().empty:
|
||||
raise RuntimeError(
|
||||
"MLBenchmark: 样本外测试集为空或 feature_engine 未在训练集上 fit。")
|
||||
|
||||
for model in self.models:
|
||||
# OOS 回测:MLStrategy 用同一已 fit engine 对测试集生成信号
|
||||
strategy = MLStrategy(model, self.feature_engine)
|
||||
report = self.bt_engine.run(strategy, self.price_df, self.factor_df)
|
||||
report = self.bt_engine.run(strategy, self.test_price_df, self.test_factor_df)
|
||||
|
||||
# OOS 预测 vs 真实值
|
||||
X, y_true = self.feature_engine.build(self.factor_df, self.price_df, fit=True)
|
||||
y_pred = model.predict(X)
|
||||
|
||||
ic = y_pred.corr(y_true) if len(y_pred) > 0 else 0
|
||||
preds = model.predict(X_test)
|
||||
common = X_test.index.intersection(y_test.dropna().index)
|
||||
ic = preds.reindex(common).astype(float).corr(y_test.reindex(common).astype(float)) if len(common) > 1 else 0
|
||||
|
||||
rows.append({
|
||||
"model": model.name,
|
||||
|
||||
Reference in New Issue
Block a user