feat: hk_backtest补全summary_stats——复用calc_summary全字段(胜率/盈亏/夏普/盈亏比/持仓/普适)+portfolio_sim组合模拟,与A股同构

This commit is contained in:
hmo
2026-08-15 08:48:49 +08:00
parent 6ad5c30ab1
commit bf0e1c2dbc
+16 -5
View File
@@ -198,10 +198,10 @@ def window_returns(nav_series):
def portfolio_metrics(trades, capital=1000000, slots=8):
"""资金模拟 + 窗口收益(净值曲线"""
"""资金模拟 + 完整 summary_stats(复用 strategy_lab.calc_summary,与A股同构"""
import strategy_lab as lab
nav, stats = portfolio_nav(trades, capital, slots)
win = window_returns(nav)
# 年化(用首末净值)
cagr = None
if nav:
items = sorted(nav.items())
@@ -209,14 +209,23 @@ def portfolio_metrics(trades, capital=1000000, slots=8):
d1, v1 = items[-1]
yrs = max((datetime.strptime(d1, "%Y-%m-%d") - datetime.strptime(d0, "%Y-%m-%d")).days / 365.0, 0.5)
cagr = (((v1 / v0) ** (1 / yrs)) - 1) * 100 if v0 > 0 else None
# 完整 summary_stats(复用 A 股 calc_summary——字段结构与A股完全一致)
cs = lab.calc_summary(trades, capital)
pf = lab.portfolio_sim(trades, capital, max_positions=slots) or {}
pff = lab.portfolio_sim_full(trades, capital) or {}
summary = dict(cs)
summary["sizing_slots"] = slots
summary["portfolio"] = pf
summary["portfolio_full"] = pff
return {
"summary_stats": summary,
"cagr": cagr,
"year1": win.get("year1"),
"month6": win.get("month6"),
"month3": win.get("month3"),
"trades": len(trades),
"skipped": stats.get("skipped", 0),
"win_rate": sum(1 for t in trades if t["profit_pct"] > 0) / len(trades) * 100 if trades else 0,
"win_rate": cs.get("win_rate"),
}
@@ -261,14 +270,16 @@ def main():
trades = [t for t in trades if td_run.get(t["entry_date"], 0) <= args.td_guard]
print(f" 温区调度({reg})+防守: 保留 {len(trades)}", flush=True)
m = portfolio_metrics(trades, slots=args.slots)
print(f" 交易{m['trades']} 胜率{m['win_rate']:.0f}% 组合年化{m['cagr']}% "
ss = m["summary_stats"]
print(f" 交易{ss['total_trades']} 胜率{ss['win_rate']}% 组合年化{m['cagr']}% "
f"近1年{m['year1']:+.1f}% 近6月{m['month6']:+.1f}% 近3月{m['month3']:+.1f}%\n", flush=True)
all_trades += trades
if all_trades and not args.version:
print("=== 港股策略组合(全温区)===", flush=True)
m = portfolio_metrics(all_trades, slots=args.slots)
print(f" 组合: 交易{m['trades']} 胜率{m['win_rate']:.0f}% 组合年化{m['cagr']}% "
ss = m["summary_stats"]
print(f" 组合: 交易{ss['total_trades']} 胜率{ss['win_rate']}% 组合年化{m['cagr']}% "
f"近1年{m['year1']:+.1f}% 近6月{m['month6']:+.1f}% 近3月{m['month3']:+.1f}%", flush=True)
ok = (m['cagr'] or 0) > 10 and (m['year1'] or 0) > 10 and (m['month6'] or 0) > 5 and (m['month3'] or 0) > 0
print(f" 验收: {'✅ 达标' if ok else '❌ 未达标'}(年化>10/近1年>10/近6月>5/近3月>0", flush=True)