续接任务提示词 · 回测引擎 v2.0 → 多资产组合(阶段 1)
回测/engine_v1/(20 个文件,独立可运行、只读 数据/、不接入 fetch.py 管线):
续接任务提示词 · 回测引擎 v2.0 → 多资产组合(阶段 1)
生成:2026-09-27 | 仓库:
/var/minis/mounts/DUCKERRY_Warehouse用法:新对话直接粘贴本文件末节「八、供新对话粘贴的最小提示词」整段即可冷启动。
本文件是完整的离线上下文——上一轮会话很长,本文件已把「已完成的 / 已证伪的 / 待办的 / 会踩的坑 / 登记规范」全部固化,新会话不需要上一轮的对话历史。
零、开工前必读(iSH 环境纪律 —— 最容易翻车的一条)
| 纪律 | 说明 |
|---|---|
| 单进程 ≤ 2 分钟 | iSH 上单个 Python 进程约 2 分钟被静默 kill:rc=0、无 traceback、nohup 也挡不住。长任务必须拆成多个 <2 分钟的短进程串行跑(例:walk-forward 逐折单独跑、绘图单独跑) |
| nohup 的正确写法 | nohup sh -c '…' >/dev/null 2>&1 & ✔ | A && nohup B & ✘ —— 会把 A 也放进后台,并随 shell 退出一起被杀 |
| 无 CJK 字体 | 容器 fc-list 为空 → matplotlib 图例/标题一律 ASCII,否则满屏 Glyph missing 警告 |
| 算与画分家 | 绘图步骤本身也可能跑过 2 分钟 → 先落盘数据,再由独立脚本出图(见 回测/engine_v1/plot_compare.py 的先例) |
| 等待机制 | 用 shell_execute 的 delay 参数轮询,不要在命令里 sleep |
一、已完成、不要重做(可复核,勿破坏)
1.1 引擎 v2.0 已入库
回测/engine_v1/(20 个文件,独立可运行、只读 数据/、不接入 fetch.py 管线):
| 文件 | 说明 |
|---|---|
duckerry_backtest.py | 主引擎约 1490 行:L0–L4 决策栈 + 四因子 A/B/C + 降频 + 核心卫星 + 否决权 + walk-forward |
plot_compare.py | 独立绘图脚本(从已落盘 equity.csv 出图) |
README.md | 使用说明与口径边界 → 回测/engine_v1/README |
compare.csv / compare_curve.png | 六策略横向对比表与净值图(对数轴) |
curves/{BuyHold,Cash6040,D-L0L2VT,W-Adp60,W-Adp60NoEv,M-Adp60}.csv | 各策略净值曲线(date, equity, dd, sat_pos) |
wf/{oos_equity.csv,oos_summary.json,fold_0..5.json} | 样本外 walk-forward 全套(626 条周线,2014-01→2025-12) |
metrics_weekly_core60.json | 主推配置完整指标 + 实际生效 config |
工作区副本(可改):/var/minis/workspace/duckerry_backtest/;共享副本:/var/minis/shared/duckerry_backtest/。
1.2 三条设计指令已落地
- 强制降频:
--freq D|W|M;重采样在指标计算之前;日频阈值按√(252/ppy)缩放(周 ×2.20 / 月 ×4.58);年化口径随频率切换 - 宏观主观否决权:L0 断路 +
|收益|≥2.5σ+ 规则化非农(--veto-scope auto月频自动禁用);--veto-mode flat卫星清仓 - 核心60%+卫星40%:
总仓位 = core + (1−core)×卫星;成本只对卫星换手计;--strategy adaptive(趋势态顺势 / 震荡态均值回归)+--l1-method trendstate(ADX + Kaufman 效率比 + Hurst)
1.3 已修的 4 个实现缺陷(留档,勿回退)
- 月频事件否决「每月都被否 → 卫星永不交易」(→
--veto-scope auto) - 年化因子硬编码 252(周/月夏普被高估
√(252/ppy)倍 →infer_ppy()) build_event_veto每 bar 调pd.date_range(34s →searchsorted向量化 + 三层缓存)tgt = tgt * w使 int 变 float →f"{tgt:+d}"崩溃(→{tgt:+.2f})
1.4 自检状态(全绿,勿破坏)
arch_check 11/11 ✔(md=215 / 出链=770 / 死链 0 / 孤儿 0)|doc_sync_check --strict rc=0|moc_index 无需更新(复盘 96 / 归档 44)
二、核心结论(已论证,不要重新论证)
2.1 等敞口公平对比 → 卫星没有 alpha
| 变体 | 均敞口 | 收益/夏普/回撤 | 等敞口被动 |
|---|---|---|---|
| 周频·自适应+核心60%(事件否决) | 68.4% | 263.0% / 0.556 / −33.0% | 345.1% / 0.644 / −31.5% |
| 周频·同上但无事件否决 | 72.8% | 320.2% / 0.579 / −33.6% | 383.9% / 0.644 / −33.2% |
| 月频·自适应+核心60% | 75.3% | 339.9% / 0.562 / −39.7% | 383.9% / 0.640 / −32.3% |
2.2 但降频明确有效
样本外夏普:日频 0.286(落后基准 0.236)→ 周频 0.754(落后等敞口被动仅 0.058)。
2.3 事件否决的代价明确
同配置下非农否决:总收益 320% → 263%(−57pp),回撤仅改善 0.6pp。
2.4 ⭐ 多资产预检(这是下一步的依据,已用现成数据验证)
gold_pm.json + fred_NASDAQ100.csv,两条腿,零参数(60 日逆波动率加权),不做任何方向预测:
| 1986-01 → 2026-09(41 年 / 10475 交易日) | 年化 | 波动 | 夏普 | 最大回撤 | 卡玛 |
|---|---|---|---|---|---|
| 黄金 100% | 6.38% | 15.9% | 0.47 | −49% | 0.13 |
| 纳指 100% | 14.02% | 25.9% | 0.64 | −83% | 0.17 |
| 等权 金+纳指 | 11.41% | 15.1% | 0.79 | −52% | 0.22 |
| 风险平价 金+纳指 | 10.87% | 12.6% | 0.88 | −33% | 0.33 |
子区间(风险平价夏普 / 黄金夏普):1986–1999 0.77/0.00 | 2000–2009 0.64/0.79(唯一跑输) | 2010–2019 0.94/0.29 | 2020–2026 1.42/0.94
诚实口径:这不是"必胜"。2000–2009 组合跑输(那十年只有黄金好)。
它是用"放弃单一资产的极端表现"换全周期稳定性;但因为是无参数的,过拟合空间远小于前面的择时模型。
另一条重要发现:41 年黄金年化只有 6.38%、卡玛 0.13 —— "黄金 2006–2026 涨 7 倍"很大程度是选了个好窗口。
2.5 结论:换问题,不换参数
不继续调参(网格择优不稳定 + 单样本 + 无多重检验校正)。方向: ① 猜方向→管风险 | ② 单资产择时→多资产分散 | ③ 手搓 regime→统计 regime | ④ 单次网格→嵌套 WF + Deflated Sharpe
三、待办(按阶段,阶段 1 即本次任务)
阶段 1 ·【本次任务 · ✔ 已执行 2026-09-27】回测层多资产组合模块(仓库近乎零改动)
✔ 交付:
回测/engine_multi/(使用说明);结论与口径修正见驾驶舱 §九 v5.2.5。
目标:在回测层验证「分散」是否真的优于「择时」,产出可复核的净值与指标。
- 位置:新建
回测/engine_multi/(不要改engine_v1/,v2.0 需保持可复现),只读数据/ - 资产池(全部现成,无需新数据):
| 资产 | 源 | 起始 | 可交易性 |
|---|---|---|---|
| 黄金 | 数据/gold_pm.json | 1968-04 | 可交易 |
| 纳斯达克100 | 数据/fred_NASDAQ100.csv | 1986-01 | 可交易(期货) |
| 标普500 | 数据/fred_SP500.csv | 2016-09 | 可交易(期货) |
| WTI 原油 | 数据/fred_DCOILWTICO.csv | 1986-01 | 可交易(期货)⚠ 见 §六坑 3 |
| TLT / AGG | 数据/bond_{tlt,agg}.json | 2026-06 | 可交易(样本极短,仅作参考) |
- 组合方法:① 等权 ② 逆波动率(风险平价)③ 风险预算 / HRP(
PyPortfolioOpt、Riskfolio-Lib思路,可先手写) - 必须产出的三张表:
- 全样本(1986–2026 及 2006–2026 两个窗口)各资产 / 各组合 的 收益·波动·夏普·回撤·卡玛
- 子区间稳健性表(1986–1999 / 2000–2009 / 2010–2019 / 2020–2026)
- 等敞口公平对比(组合平均敞口 vs 同敞口被动;沿用报告 §3.2 的方法)
- 可选的进阶:给"决策栈"换一个决策变量——不再猜方向,而是决定每期权重(风险预算);保留 L0 作为降杠杆开关(而非清仓开关)
- 验收标准:① 三张表齐全且可复现;② 结论与 §2.4 一致或给出反例;③
arch_check11/11 +doc_sync_check --strictrc=0;④ 产出回测/engine_multi/README.md+ 净值曲线 CSV
阶段 2 ·(阶段 1 验证后再做)面板与分析层小改
scripts/dkpanel.py:build()的 FRED 循环加新 asset 列(加列不改行数,doc_sync_check第 10 项不受影响)CORE = ["gold_pm","10y_nom","10y_tips"]不动 → G1 闸门不受影响scripts/dkanalysis.py:283的s = T["gold_pm"]→ 加参数series="gold_pm"(向后兼容,黄金调用不变)- 新增
scripts/portfolio.py(等权 / 逆波动率 / 风险预算)——每日只算权重、只记录,不下单 数据/新资产数据 → 在 数据库说明 §〇·五·一 登记来源与口径
阶段 3 ·(真·大改,先别做)执行层与复盘层
| 文件 | 为什么是真活 |
|---|---|
scripts/paper_engine.py | 现在是单标的模型(buy_amount/short_amount/cash,无"品种"概念)→ 多腿权重 + 再平衡,约等于重写 |
复盘模板 + duckerry-daily-review SKILL | 全是黄金单标的叙事(L0-1 金/美同跌、L1 黄金5日动量、A/B/C 黄金主导因子)→ 每日 SOP 变重、失败点 ×N |
predict_regime_conditional.py / pattern_abc.py / brier_calibration.py | 整条黄金预测链 → 要么 per-asset(成本 ×N),要么保持黄金专用 |
必须先回答的设计问题:你要的是「组合层资产配置」(黄金只是其中一条腿 → 大改),还是「黄金择时增强」(黄金仍是主角、其他资产只当分散器 → 小改,阶段 2 就够)?
建议后者——整个仓库的叙事/技能/预测链都围绕黄金建立,没必要推倒。若选后者,则阶段 2 完成即收工。
四、GitHub 资源与整合方式(用户正在下载)
4.1 放哪里 / 怎么登记(重要)
- 解压到
/var/minis/mounts/武器库/(与现有PyBackLab-main/akshare-main/convex-main/fixed-income-mcp-main/trace-data-pipeline-main同级) - 在 数据库说明 §〇·五·一「外部思路源」段落登记,遵循既有红线原文:
「两者均未安装、无 pip 网络,只作设计参考,不接入、不 import」
- 不要把第三方库 import 进
scripts/生产链;需要用时在回测/下自建独立脚本
4.2 已核实仓库清单(2026-09-27 经 GitHub API 实测;★为当时星数)
| 仓库 | ★ | 对应阶段 | 用途 |
|---|---|---|---|
[pst-group/pysystemtrade](https://github.com/pst-group/pysystemtrade)(原 robcarver17,已改名) | 3.5k | 1·2 | 首选。Rob Carver 系统化交易:"不要预测,要分散"、多品种小仓位、forecast scaling、风险目标化 |
| [stefan-jansen/machine-learning-for-trading](https://github.com/stefan-jansen/machine-learning-for-trading) | 21.0k | 1·3 | regime detection 专章(HMM/GMM,可替换手搓 ADX/Hurst)+ 回测陷阱章节 |
| [hmmlearn/hmmlearn](https://github.com/hmmlearn/hmmlearn) | 3.4k | 3 | 标准 HMM;仓库已有 regime_hybrid.py,应对齐而非另起一套 |
| [polakowo/vectorbt](https://github.com/polakowo/vectorbt) | 9.2k | 1 | 向量化,参数扫描 / walk-forward 极快 |
| [pmorissette/bt](https://github.com/pmorissette/bt) | 3.0k | 1·2 | 组合层回测,天然支持分腿与再平衡 |
| [kernc/backtesting.py](https://github.com/kernc/backtesting.py) | 9.0k | 1 | 轻量引擎,内置优化器 |
| [mementum/backtrader](https://github.com/mementum/backtrader) | 23.3k | 1 | 最成熟;注意最后 push 2024-08,维护放缓 |
| [stefan-jansen/zipline-reloaded](https://github.com/stefan-jansen/zipline-reloaded) | 1.9k | 1 | Zipline 现代维护版 |
| [PyPortfolio/PyPortfolioOpt](https://github.com/PyPortfolio/PyPortfolioOpt) | 6.1k | 1·2 | HRP / Black-Litterman / 有效前沿 → 正式求解核心-卫星配比,替代拍脑袋的 60/40 |
| [dcajasn/Riskfolio-Lib](https://github.com/dcajasn/Riskfolio-Lib) | 4.5k | 1·2 | 风险预算 / 风险平价 / 最差回撤优化 |
| [cvxgrp/cvxportfolio](https://github.com/cvxgrp/cvxportfolio) | 1.3k | 2 | Boyd 组凸优化组合回测(多期 + 含交易成本),理论上最严谨 |
| [ranaroussi/quantstats](https://github.com/ranaroussi/quantstats) | 7.7k | 1 | 一键全套绩效报告,可替换手写 performance() |
| [stefan-jansen/pyfolio-reloaded](https://github.com/stefan-jansen/pyfolio-reloaded) | 616 | 2 | 组合/风险归因 |
| [stefan-jansen/alphalens-reloaded](https://github.com/stefan-jansen/alphalens-reloaded) | 657 | 3 | 检验"四因子到底有没有信息量"(IC / 分层回测) |
| [wilsonfreitas/awesome-quant](https://github.com/wilsonfreitas/awesome-quant) | 29.8k | — | 量化资源总索引 |
| [wangzhe3224/awesome-systematic-trading](https://github.com/wangzhe3224/awesome-systematic-trading) | 5.2k | — | 系统化交易索引(期货/持仓方向更全) |
⚠ 先明确一件事:以上几乎全是引擎/工具/方法论,没有一个是"现成的能赚钱的策略公式"。
换仓库拿到的是更可靠的流程与更少的自欺,不是 alpha。
五、仓库登记规范(加文件后必须做,否则自检失败)
| 规范 | 内容 |
|---|---|
| 地图计数口径 | arch_check.MAP_DIRS:回测/optimization/框架/资产/因子/概念/顶层文档 = all_direct(只数直属文件,不数目录);复盘 = md_direct;audit_evidence = md_recursive。新增子目录不改变声明数 |
新 .md 必须有入链 | 任何新 md 至少一条 [[wiki 链接]] 入链,否则判孤儿 → 在驾驶舱 §〇·五 加一行即可 |
| §九 必须含最新日期 | doc_sync_check 第 8 项:扫 optimization/*.md 全量取文件名内最大日期,该日期必须出现在 §九 区块内 |
| frontmatter 更新时间不能随手改 | doc_sync_check 第 1 项要求驾驶舱 frontmatter 更新时间 = latest.json 的 generated_at 日期(当前 2026-09-26),不是今天 |
| §九 版本倒序 | check_versions 只解析 ^### v(\d+)\.(\d+) 并要求单调倒序 → 新条目放 §九最前 |
| SKIP_DIRS | scripts/、数据/、tests/、.obsidian、__pycache__ 不计入链接/孤儿扫描 |
| 收尾三件套 | python3 scripts/moc_index.py → python3 scripts/arch_check.py(期望 11/11)→ python3 scripts/doc_sync_check.py --strict(期望 rc=0) |
| ⚠ 改前快照(v1.1 补) | 「纯新增」不等于「可以不做快照」:即使只新增目录/新增若干行,也必须先做改前快照并记录 md5,再动手。理由:本次阶段 1 就漏做过一次(两处均为纯新增 → 回滚虽精确但无 pre 件可 diff 核对)。做法:cp 目标文件到 /var/minis/shared/backup/DUCKERRY_pre_<主题>_<日期>/ + md5sum 清单 + REVERT.md |
| iSH 长任务纪律(v1.1 补) | 即便把 --task all 拆成逐子进程分派,单个子进程仍可能被静默 kill 且 rc=0 假成功(实测表 D g3-erc、表 C 四资产各丢过一整块)→ 拆到「池 × 方法 × 子区间」粒度 + 逐块增量落盘 + 跑完核对行数(本模块表行数应为 A=29 / B=44 / B2=20 / C=45 / D=108 / E=24) |
六、已知坑清单(别重踩)
- 月频 + 事件否决:若按"月内有非农"整月否决 → 每月都被否 → 卫星永不交易(交易次数 0),结果会退化成"60%金+40%现金"却看不出来。已用
--veto-scope auto修。 - 年化因子:任何多资产/降频计算,年化期数必须随频率切换(252/52/12),否则夏普与波动会被放大
√(252/ppy)倍。 - ⚠ WTI 负价:
fred_DCOILWTICO.csv在 2020-04-20 = −36.98 美元,pct_change直接变 −302%,会把任何含它的组合算崩(实测把等权组合算到"总收益 −109%")。多资产必须加负价格/极端值守卫。 pd.date_range别放进逐行循环:1084 次调用 = 28.5s。用searchsorted向量化。- iSH kill:见 §零。全折 walk-forward 单折约 140s(周频,含 swap 等待)→ 必须逐折独立进程。
- matplotlib 无 CJK:图例一律 ASCII。
- 缓存:
engine_v1内置三层缓存(原始帧 / 降频帧 / 层级判定),新增资产时注意_frame_key/_layer_key是否包含了新维度(漏加会导致串结果——本轮的veto_scope就漏过一次)。
七、纪律红线
- 回测口径 ≠ 实盘 ≠ 生产管线(
数据/panel.csv+paper_engine.py),数字不可互相引用;产出必须并列"不构成投资建议"。 - 引擎是只读消费者:只读
数据/,不写生产文件、不接入fetch.py管线。 - 不改
scripts/任何生产脚本、不改 框架/数据口径定义、不动归档区与已发布复盘、不动predictions.jsonl。 - 四因子权重是主观先验
[待验证];A/B/C 是可计算操作化代理;L0 阈值[待验证]。单次样本内结果不构成证据——关键结论一律以等敞口对比 + 样本外 + 子区间为准。 - 收尾用
memory_write写当日记忆,并回报:变更文件清单 / 自检结果 / 回滚点。
八、供新对话粘贴的最小提示词
读取仓库交接件(**完整离线上下文,不要另外找历史**):
/var/minis/mounts/DUCKERRY_Warehouse/optimization/继续任务提示词_2026-09-27_回测引擎v2.0与多资产.md
并读记忆 /var/minis/memory/2026-09-27.md(回测引擎 v2.0 相关的两条)。
仓库:/var/minis/mounts/DUCKERRY_Warehouse(挂载,可写)。环境:iSH,注意交接件「零、环境纪律」。
任务:执行交接件的「三、阶段 1」——在 `回测/engine_multi/` 新建**多资产组合回测模块**
(资产池用现成的 gold_pm / NASDAQ100 / SP500 / WTI;方法:等权 / 逆波动率 / 风险预算;
必须产出①全样本②子区间③等敞口公平对比 三张表)。
**不要改 `回测/engine_v1/`,不要碰 `scripts/` 生产脚本,不要接入 fetch 管线。**
执行顺序:
1) 先只读交接件 + 抽查 `回测/engine_v1/duckerry_backtest.py` 与 `数据/` 目录,确认资产可用性;
2) 给出**执行计划(文件清单 + 验收标准 + 预计耗时)**让我确认,**确认后再开工**;
3) 开工后按交接件「五、仓库登记规范」登记新文件,收尾跑 `moc_index` / `arch_check`(期望 11/11) / `doc_sync_check --strict`(期望 rc=0);
4) 最后用 memory_write 写当日记忆并回报变更清单与回滚点。
注意坑:WTI 在 2020-04-20 是负价(−36.98),必须加负值守卫;iSH 单进程约 2 分钟被静默 kill,长任务拆短进程跑。附 A · 关键数字速查
- 有效窗口:2006-01-03 → 2026-09-25(20.6 年);日频 5199 bar / 周频 1082 / 月频 249
- 成本:6bps 单边(1bp 佣金 + 5bps 滑点);核心底仓不计换手
- 买入持有(2006–2026):703.5% / 年化 10.63% / 波动 18.2% / 夏普 0.646 / 回撤 −44.6%
- 被动 60/40(金/现金):279.3% / 6.68% / 10.9% / 0.646 / −28.7% / 卡玛 0.233
- 周频·自适应+核心60%:263.0% / 6.39% / 12.6% / 0.556 / −33.0%
- 样本外(2014-01→2025-12,626 周):策略 126.2% / 夏普 0.754 / 回撤 −15.7%;等敞口被动(67.6%) 139.8% / 0.812 / −16.3%
- 41 年多资产预检:风险平价 金+纳指 夏普 0.88 / 回撤 −33% / 卡玛 0.33(vs 黄金 0.47 / −49% / 0.13)
附 B · 文件地图
| 用途 | 路径 |
|---|---|
| 本交接件 | optimization/继续任务提示词_2026-09-27_回测引擎v2.0与多资产.md |
| v2.0 完整报告 | optimization/四因子框架回测引擎v2.0_报告_2026-09-27.md |
| 引擎与资产曲线 | 回测/engine_v1/(+ README.md、curves/、wf/) |
| 工作区副本(可改) | /var/minis/workspace/duckerry_backtest/ |
| 共享副本 | /var/minis/shared/duckerry_backtest/ |
| 数据源 | 数据/(gold_pm.json、fred_*.csv、bond_*.json) |
| 生产管线(勿动) | scripts/fetch.py → dkpanel.py → dkanalysis.py → paper_engine.py |
| 外部资源(只作参考) | /var/minis/mounts/武器库/ |
修订记录
- 2026-09-27 v1.1:状态改为「阶段 1 已执行」;§五 规范补两条(改前快照:纯新增也要做、iSH 子进程静默 kill 的拆法与行数核对);§三 阶段 1 标注交付物。
- 2026-09-27 v1.0:首版。固化回测引擎 v2.0 的已完成项、核心结论(含等敞口否定式发现与多资产预检)、三阶段待办、16 个已核实 GitHub 仓库与武器库登记方式、仓库登记规范、7 条已知坑、环境纪律,并给出可直接粘贴的最小提示词。