feat(portfolio): C2 单股上限约束真实执行(Portfolio v1.1)
- portfolio.allocate_with_max_position:无上限=等权(与原实现一致);有上限=迭代 把超过 cap×当日组合市值的标的封顶并把剩余现金在其余标的中再分配,超出留现金 - TopKBacktestRunner 买入按约束分流(默认等权路径位级不变,回归数值保持) - unimplemented 只保留行业上限(依赖行业元数据注入,如实标注) - tests/test_portfolio_constraints.py(分配数值/封顶留现金/回测持仓权重≤上限+容差、 config_snapshot)+ 旧断言更新(单股不再标注);全量 pytest 通过
This commit is contained in:
@@ -138,11 +138,14 @@ class TestPortfolioEngine:
|
||||
assert not any("约束未建模" in u for u in result.unimplemented)
|
||||
|
||||
def test_constraint_declared_in_unimplemented(self, daily_df) -> None:
|
||||
"""C2:单股上限已建模(不再进 unimplemented);行业上限仍如实标注。"""
|
||||
from app.domain.entities.research import PortfolioSpec
|
||||
from app.quant.engine import LocalEngine
|
||||
|
||||
spec = _spec(portfolio=PortfolioSpec(max_position_pct=0.1))
|
||||
spec = _spec(portfolio=PortfolioSpec(max_position_pct=0.1, max_industry_weight_pct=0.25))
|
||||
result = LocalEngine().run_backtest(daily_df, spec)
|
||||
assert any("最大单股权重" in u for u in result.unimplemented)
|
||||
assert not any("单股" in u for u in result.unimplemented)
|
||||
assert any("行业" in u for u in result.unimplemented)
|
||||
# config_snapshot 记录组合配置
|
||||
assert result.config_snapshot["portfolio"]["max_position_pct"] == 0.1
|
||||
assert result.config_snapshot["portfolio"]["max_industry_weight_pct"] == 0.25
|
||||
|
||||
Reference in New Issue
Block a user