📋 期货AI基金经理 · 工作日报 (交易日 2026-10-14_数据重建与zadj基线重算) ⏭ 跳到最新(2026-11-12)
# 数据重建 + zadj 基线重算(2026-10-14,交接未完成项 0-①)
> 用户批准的动作:**重建三品种 15m 数据集 + 给数据闸门补缺根检查 → 重算 EXPECTED**。
> 结论:**基线合计由 +419,019 修正为 +163,640(旧值高估 2.6 倍)**,其中 **SC 的边际不再成立**
> (夏普 2.39→**0.66**、最大回撤 **−132,720 > 净利**、前半−73,780/后半+153,000 不一致)。
## 一、闸门补了什么(本次事故的直接原因)
`data_quality_gate.py` 原来**只抓"假柱"**(开=高=低=收且同前收 → 判前值填充),
**抓不到"少掉真 K 线"**。三个 zadj 回测文件因此全部以"死柱 0.00% ✅通过"的名义放行,
实际各有 40/727/51 个时段段根数不符(最严重=**整个夜盘 0 根 vs 真实 22 根**)。
新增:
| 函数 | 作用 | 结果 |
|---|---|---|
| `missing_bar_stats(df, tf_min)` | 按 (交易日,时段) 用**自校准期望网格**查缺根(不需要外部参考源) | 旧数据:SC **40/802**、AU **727/2233**、AG **51/727** 段不合格 → 🚨 |
| `dead_run_stats(df)` | 把"连续同价"分成 **停板**(有成交量=真实涨跌停锁死)与 **停更**(无量=假) | SC 5 段停板 / AG 2 段;**旧闸门把它们一律当假数据** |
| `gate(..., tf_min=)` | 缺根纳入总判定;停板只告警(并提示"停板期间不可假设能成交") | 旧数据现已**正确判不合格** |
> 说明:先前的诊断里我把"死柱 21 根"当成数据缺陷,实测是 **SC/AG 的涨停锁死**
> (冻结价 641.1,每根仍有 6~457 手成交)—— **真实行情,但不可成交**。闸门已按成交量区分。
## 二、重建(`rebuild_zadj_15m.py`)
设计上不做"自己从具体合约拼"(我第一版按 session 选主力,主力在夜盘/日盘之间来回抖动,
导致复权量累加成假跳空,已废弃),而是:
1. **基座 = 主连 `KQ.m@`** —— 因为**实盘交易的就是它**(`SPECS.symbol`),回测与实盘必须同序列;
主连的 bar 网格完整、合约选择由交易所口径决定,不需要我用持仓量去猜。
2. 用具体合约**识别主连每一根 bar 底下是哪个合约**(收盘价相等匹配 + 与前一根同合约优先)→ 换月点。
3. 换月点做**后向复权**:把该点**之前**的 bar 整体减去累计价差 → 拼缝处 bar 间变动 = **新合约自身变动**,
且**最新一段保持真实价位**。
结果(三品种均):
| | 结果 |
|---|---|
| 根数/跨度 | 8964 根,2025-09-29 ~ 2026-10-14 |
| **时段完整性** | **734/734 全部完整** ✅ |
| 合约识别 | SC/AU 8964/8964,AG 8960/8964 |
| 换月点 | SC 12、AU 6、AG 6;价差极小(SC −2.4~+0.1、AU −2.5~−3.0、AG −24~+207) |
| 复权验证 | AG 2026-03-06 换月(价差 +207):原主连该 bar 跳空 **−811** → 复权后 **−604**,差 **+207** = 价差 ✅ |
| 价位保持 | 最新段复权量 **0.00**(现价真实),历史段分段常数(13 档) |
| 闸门 | 三品种 ✅ 通过(停板段已正确归类) |
旧文件备份为 `*_clean15m.csv.bak-20261014-missingbar`(不删),并写出 `*.meta.json` 记来源/换月点/体检。
## 三、重算后的基线(**这是本次最重要的结论**)
| 品种 | 旧 EXPECTED | **新 EXPECTED** | 夏普 | 最大回撤 | 前半 / 后半 |
|---|---|---|---|---|---|
| SC 原油 | 409笔 / +247,120 | 379笔 / **+79,220** | 2.39 → **0.66** | **−132,720** | **−73,780 / +153,000** |
| AU 沪金 | 158笔 / +124,994 | 19笔 / +57,570 | — / 5.01 | −10,919 | +68,489 / −10,919 |
| AG 沪银 | 206笔 / +46,905 | 208笔 / **+26,850** | 1.61 → **1.04** | −29,685 | +14,355 / +12,495 |
| **合计** | **+419,019** | **+163,640** | | | |
- **SC 是最大的修订**:夏普跌到 0.66、**最大回撤(−132,720)大于其全部净利(+79,220)**、
前后半符号相反、最好的 3 个月占总盈亏 **192%**、2026-03 单月 **−63,000**。
→ **SC 的边际不能算成立**。且 1 手 SC 名义值 ≈75 万 ≈ 账户的 78%,这个回撤在账户层面是 −13.7%。
- **AU 无法判定**:只剩 19 笔、全在 2026-01~03,**100% 来自一个月**。旧 158 笔的样本覆盖 3.4 年,
主连 15m 只能回溯 8964 根(≈12.5 个月)→ 要复现 AU 的长样本必须做**按交易日**选主力的合约拼接。
- **AG 最稳**:前后半都为正(+14,355/+12,495),夏普 1.04;但回撤(−29,685)仍大于净利(+26,850)。
## 四、重建数据的**交叉验证**(证明修对了)
| 验证 | 结果 |
|---|---|
| 复权算术 | AG 换月处 Δ = +207 = 价差,**精确** |
| 模型 vs 实盘(实盘窗口 SC) | 模型 **−66,020** vs 实盘 **−65,360** → 差 **+660**(修数据前是 −8,760)→ **SC 的"执行差"是数据伪影** |
| 模型 vs 实盘(实盘窗口 AG) | 模型 **+4,410**(4笔) vs 实盘 **−5,540**(11笔) → **−9,950** → 剩余差距**全在 AG 的执行**(重复开仓) |
| 两套实现等价 | `--selfcheck` 第 2 步(实盘 StrategyCore)与第 1 步 **Δ=0** ✅ |
| 回归门 | 已按修正值更新 `EXPECTED`(并注明旧值与作废原因),`--selfcheck` **全部通过** |
## 五、对"要不要迭代策略"的修订结论
原来的答案是"**不要迭代**,因为那段是坏抽样、且基线本身失真"。数据修好后:
- **"为了挽回最近这几天的亏损去迭代"仍然 ❌ 不成立** —— 模型在实盘窗口同样亏 **−61,610**,
这段依旧是坏抽样,动参数就是拟合噪音。
- **但现在出现了一个"决策级"的改动理由,且它不是调参**:
1. **SC 降级或停用**(唯一有数据支撑的动作):夏普 0.66、回撤>净利、前后半矛盾。
2. **修 AG 的执行**(重复开仓/一次平多手/滑点 36~76 tick)——实盘窗口 AG 比模型多亏 −9,950。
3. **AU 补样本**(按交易日拼合约),否则无法判断。
- 以上任一项要上实盘,仍须 walk-forward + 样本内外 + Deflated Sharpe(harness 已在)。
## 六、待办
- [ ] SC:用重建数据做 walk-forward(滚动前推)确认"无边际",然后**降档或停用**(需你拍板)。
- [ ] AG:查 10-12 的重复开仓(15 分钟内两次开空)与 `close -2`,修执行层。
- [ ] AU:按交易日的合约拼接恢复长样本,再判 158 笔那个结论是否成立。
- [ ] `SPECS['SC'].fee_close_today` 0 → 60(外部资料;模拟盘收 20)+ 1/2/3 tick 滑点敏感度。
- [ ] `pnl_attrib.realized()` 改为尊重 `CLOSETODAY`/`CLOSE` 的配对(面板/日报在用)。