fix(portfolio): run_backtest_json透传factor_topn四参——矩阵三跑全空仓总根因:CLI --json走本函数手工拼Namespace漏factor_dir(缺省空串→策略「未配置」直接空仓16秒假快),进程内诊断路径完整掩盖此bug;main --json分支params与Namespace双侧补齐+mock截获Namespace回归测试,全量1207绿 [vps]
CI/CD / test (push) Successful in 31s
CI/CD / nas-deploy (push) Successful in 34s
CI/CD / nas-verify (push) Successful in 9s

This commit is contained in:
2026-09-12 08:42:36 +08:00
parent 96e373ae73
commit d75691e64d
2 changed files with 35 additions and 0 deletions
+11
View File
@@ -494,6 +494,13 @@ def run_backtest_json(params: Dict[str, Any]) -> Dict[str, Any]:
stamp_duty_rate=float(params.get("stamp_duty_rate", 0.001)),
min_commission=float(params.get("min_commission", 5.0)),
slippage=float(params.get("slippage", 0.0)),
# factor_topn 四参数(2026-09-12:漏透传=矩阵三跑全空仓的根因——
# CLI --json 走本函数手工拼 Namespace,factor_dir 缺省空串使策略
# 「factor_dir 未配置」直接空仓跑完)
factor_name=params.get("factor_name", "composite_quant12_v2a"),
factor_dir=params.get("factor_dir", ""),
top_n=int(params.get("top_n", 100)),
rebalance_days=int(params.get("rebalance_days", 21)),
initial_positions=json.dumps(params["initial_positions"])
if params.get("initial_positions") else "",
)
@@ -829,6 +836,10 @@ def main() -> None:
"stamp_duty_rate": args.stamp_duty_rate,
"min_commission": args.min_commission,
"slippage": args.slippage,
"factor_name": getattr(args, "factor_name", ""),
"factor_dir": getattr(args, "factor_dir", ""),
"top_n": getattr(args, "top_n", 100),
"rebalance_days": getattr(args, "rebalance_days", 21),
})
print(json.dumps(result, ensure_ascii=False, default=str))
else:
+24
View File
@@ -170,3 +170,27 @@ def test_initialize_registers_daily_schedule(factor_dir):
st.broker.run_daily = lambda fn, t: calls.append((fn, t))
st.initialize(_ctx("2024-10-08"))
assert calls == [(st.rebalance, "9:30")]
def test_run_backtest_json_passes_factor_topn_params(monkeypatch):
"""CLI --json 路径(run_backtest_json 手工拼 Namespace)必须透传 factor 四参——
2026-09-12 矩阵三跑全空仓根因: 漏透传factor_dir=""策略未配置直接空仓,
而进程内 run_backtest(parse_args()) 路径完整(诊断一直成交掩盖此 bug)."""
from sanguo_portfolio import runner_backtest
captured: dict = {}
def _fake_run_backtest(args):
captured.update({
k: getattr(args, k, "<MISSING>")
for k in ("factor_name", "factor_dir", "top_n", "rebalance_days")
})
return {}
monkeypatch.setattr(runner_backtest, "run_backtest", _fake_run_backtest)
runner_backtest.run_backtest_json({
"strategy": "factor_topn",
"factor_name": "composite_test", "factor_dir": "/x/y",
"top_n": 50, "rebalance_days": 10,
})
assert captured == {"factor_name": "composite_test", "factor_dir": "/x/y",
"top_n": 50, "rebalance_days": 10}