From 0aad266e4397637439febc571b934126b919e089 Mon Sep 17 00:00:00 2001 From: shaofl <2899218482@qq.com> Date: Sat, 25 Jul 2026 11:25:51 -0700 Subject: [PATCH] docs: record refactor step D5a (PR #95) and the D4b insertion --- AGENTS.md | 3 ++- CLAUDE.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 29fa153..6bbc60f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -57,7 +57,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri ## 开发约定 - **交流中文**;代码/注释/commit message 用**英文**。 -- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 +- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)、#94(进度文档)、#95(因子层重构 D5a:exec 基线冻结 + 11 runner 差异编目 + 可行性探测)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -372,6 +372,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - **D2(PR #89,整步已关账——首个动数学步骤,实测逐位一致)**:`factors/ops/` 7 算子(momentum/volatility/liquidity/overnight_mom 改写其上,naive-oracle 等值锁定)+ `factors/compute/minute/`(primitives 吸收 `peak_mask_for_symbol` 单点定义 + 11 因子一因子一文件,数学+surface+声明同文件)+ R14 粒度 shim 化(10 纯模块 + intraday_derived AST 锁纯度;aggregate 通用核留真实代码;共享常量安家 intraday_schema——live import 测试证留 aggregate 成真环)。**验收三条独立路径互证**:① 逐格对账 vs D1 冻结基线 **14/14 `max_rel_diff=0.0`、canonical hash 全等(逐位一致)**;② 88 行分层手算锚 0 失配(脚本运行时守卫禁 import 引擎,曾自抓 3 个口径错);③ mutation 证据实跑 rc=1/rc=0 三组(评审活体复跑其二)。I5 四 run 值级锚全命中(I5b/I5f 1.019318;I5d Spearman +0.9;I5e −0.5)。PR-D 测量债清偿(4.58% 窗含真 ex-date,评审从冻结 manifest 独立复算,维持 CROSSED_DISCLOSED)。provisional 锚全精度值入测试(PROVISIONAL,D6 转正)。评审 APPROVE-WITH-NITS(1 LOW:guard_boundary 静默跳过无机器可读披露——当场修,skip 显式落 JSON)。留 D6 两注记:shim 期 aggregate→factors.minute 方向(披露的临时例外,D6d 日落);`asof_daily_features` 的 mmp_ew hook 届时需新家。gates:**1955 passed** / ruff / 31 configs / phase0 锚不变 / secret 0。 - **D3(PR #91,整步已关账——store 层,纯附加未接线)**:`factors/store/`(hashing/code_hash/fingerprint/keys/values/run_registry/incremental,全 <800 行)+ **R5 前置修复**(`fina_tail_days` 单一真相迁至 `data.cache.fina_tail_days`,回测 `_build_cache` 与 data-update 两 builder 统一传 fina 400 尾 override——回测 read-through 现会补 fina 尾窗,行为变更已披露;`data_update.fina_tail_days` 删除对 repo 外旧 YAML 属 breaking,仓内两 config 已迁)。key = params_hash + code_hash(自身模块 + 枚举共享集{minute primitives/ops/base/spec} + **one-hop 直接项目内 import 折叠**:AST 自动派生、无手工清单、不做传递闭包——评审 MEDIUM 实测 `reversal_20` 可 build 且值=−momentum 而 momentum.py 取值面不入 key = 陈旧复用洞,据此修;改 momentum → candidates 系 key 变、financial/分钟系不变,无全局过度失效)+ view + 数据指纹(schema-version 维 = data/clean PIT 承重模块内容 hash;`price_level` 另掺 per-symbol adj_factor 事件表 hash 含锚值,收官集零成员不豁免 fixture 测试)。存储:单文件 parquet date 排序 / 原子写 tmp+`os.replace` / per-artifact O_CREAT|O_EXCL 锁(两进程 gap-fill 零丢行实测;锁 neuter mutation 证明锁对原子写也承重)/ JSONL append-only 运行注册表(no-secret:sanitize_text 过自由文本,redaction 测试钉住)/ 损坏文件=miss / **不建 coverage ledger**(值确定性可重算)/ 启动一致性断言(registry 条目必须命中代码注册表)。tail-recompute:`w_overlap=max(W_dep, 端点修订视界)`——W_dep=传递 lookback 深度经 **`FactorSpec.lookback_depth`(optional 附加字段,contract v1.1)**声明、store 消费点 HARD-REQUIRE(14 真实因子未声明 → loud 报错,声明属预注册动作留 D4);视界经 `revision_horizon()` 从 live config 派生(调大 refresh_recent_days → 重叠窗变宽 mutation 实证,无硬编码 14/400);重叠 NaN-aware bitwise,失配按 adjustment 分类(returns_invariant→loud 上游回改记录 / price_level→预期);schema 指纹失配 → schema_void_full 全量重算不误报 revision;§六.18 teeth(headline 深度欠采 → 假 mismatch)测试钉住。#adjustment NET-NEW 性质测试钉本格:扰动 qfq 锚 → returns_invariant 真因子(日频 volatility_20 + 分钟 valley_relative_vwap)逐 bit 不变,批量 census 9/5/0 ≡ D0 表。评审 APPROVE-WITH-NITS(0 CRIT/HIGH,1 MEDIUM+3 LOW+1 NIT;MEDIUM/LOW-1/LOW-3 合并前修于 `fd906f4` 并经 delta 复核三项 CLOSED——评审亲手重跑 momentum on-disk mutation 5/5、allowlist 注入、锁 neuter,并猎杀「不可能失败的测试」零发现)。留 D4 注记:materializer 必须传 live `data.cache.fina_tail_days` 勿靠 400 默认;two-hop 组合链是 one-hop 折叠的已知边界(今日无实例,设计明令不做传递遍历器);`availability_policy` 编辑会 over-invalidate 其 importer 的 store(安全方向、D4/D5 churn 期真实重算成本);单点填≡批量填(P8)是 D4 验收项。gates:**2031 passed**(=1955+76)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 - **D4(PR #93,整步已关账——FactorService + materializer;四轮评审揪出两个 HIGH + 一项设计修正)**:`factors/service.py`(frozen `DecisionPoint` + `cross_section`/`panel` **都 read-through 读 D3 store**,miss 触发唯一引擎,配对合法性复用 D0 `require_legal_pairing` 构造期强制)+ decision-view materializer(R18 **全** policy-lag:日线非-open ≤ d−1、**open[d] 字段级例外从 policy 表派生**、daily_basic/fina ≤ d−1、分钟 ≤14:50;ex-date 只暴露**布尔**的类型边界;`CacheHorizonConfig` 从 live config 构造缺属性即 raise)+ process 编排下沉 `factors/process/orchestrate.py`(`_process_factors` 薄委托逐字行为保持)+ 14 因子 `lookback_depth` 预注册(参数化派生+测试钉死)+ 热路径计时 smoke(真实缓存 cache-only 40 票共享读 ≈2.0x,诚实标注不外推)。**评审故事(P8 单点填≡批量填连揪三层真缺陷)**:①【设计修正】valid-day **pooled** 因子(8/11 分钟因子按滚动机制码检划分,非按观察到分歧的 3 个——#82 教训)trailing N 个**有效日**的日历深度数据依赖、**无界** → **证否 v3.2 §3.3 R4「W_dep=各 lookback 之和」假设**,固定 40 日 trim 使单点填 vs 批量填 finite↔NaN 分歧;②首版不动点判据(值稳定+nbars 稳定)被评审构造 **>1 chunk 停牌 gap 反例**击穿(finite-vs-finite 静默错值)→ 改**结构性判据**(锁定单调性:丢窗口头部 baseline_days 交易日其余分类 FINAL;锁定区 output-date 计数 ≥ lookback_days,gap-immune)+ provider 显式 `earliest_available`(nbars 推断删除,中段 gap 不许当 data start),上版「divergence is gone」overclaim 在 commit message 开篇更正;③判据循环只遍历**有输出的** symbol → 长停牌票**无否决权被静默丢出截面**(撞 I5a 红线)→ 改遍历**请求的** symbol 列表,评审 fixture(600519 丢名复现 + 锁定偏移 416.0 vs 438.0 静默错值)全部落成 committed 测试 + 源码级 mutation 双 witness(rc=1/rc=0,评审亲手用自己未改动的脚本独立复跑确认)。`_MAX_SATURATION_CHUNKS` 耗尽改 loud raise(红线 #9)+ raise 分支有测试。**代价如实入 docstring**:凑不满 lookback 有效日的票拖全 universe 扩到声明 floor;per-symbol 饱和起点是 D5 优化**且非纯优化**(`intraday_amp_cut` 截面 z-score 耦合)。**早期区域量化(D5 面板腿归因名目)**:分钟缓存真实起点 **2015-01-05** → D1 冻结基线(锚 2021-07-01)对 pooled 因子属 **anchor 截断**,饱和加载在 2021-07→10 五票上 ridge 有 157/184 cell 不同(79 NaN→finite,按月递减至零)——D5 对账须具名归因「saturation vs anchor truncation」。JC1 已裁定:P8 逐 bit 对滚动因子降为 ≤1e-12 可归因浮点重排(实测 floor ~3.5e-18,真缺行效应 ≥7 个数量级于容差;NaN mask 必须精确)。留 D5/D6:声明 floor 应从分钟 coverage ledger 派生 per-symbol(现为硬编码常量,声明偏晚会静默截断);`valley_price_quantile` 分钟绑定 DEFERRED(loud 报错,已声明 pooled,D5 绑定继承饱和路径**不许**固定 trim 绕过);零输出否决语义已被测试+mutation 钉住,D5 为性能回退它=放回 HIGH;blanket shift 依赖「因子输入面板只含端点列」的 D6 wiring 契约。gates:**2098 passed**(=2031+67)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 + - **D5a(PR #95,D5 的前三块——冻结/编目/探测;探测结论迫使插入新迁移步 D4b)**:**C1 冻结 exec 对账基线**(`qt/exec_baseline_freeze.py`)——22 份 exec artifact 是后续一切对账的参照,却 **gitignored 只存在于本机**,且设计假定的耐久副本 `scratchpad/baseline_reports/` **早已不存在**;新 runner 沿用同名输出路径,**跑一次就毁掉唯一基线**,随后的「对账」会比对刚被自己覆盖的文件(= 本仓在案的 `compare_postmerge.py` 空对账形态)。实冻 **77 个文件**(不是交办的 44——同族还有 11 份 `_exec_basis_sanity.md` + 22 张 dashboard,同样单份不可再生),**sha256 manifest 入 git**(字节留 gitignored,哈希只能经评审 diff 变动),每次读都验哈希,读取器结构性拒绝 live 路径(直连/symlink 别名/`..` 三种绕过全拒)。**provenance 按证据强度分级**:观察到的是 77 文件共享毫秒级 mtime(批量拷贝签名),对照 44 份 close 基准的 11 个递进 mtime 与 #74 重跑窗口吻合;「字节出自 #79 run」标注为**推断非观察**,字段名故意叫 `frozen_at_git_head` 而非 `producing_sha`。**C2 编目 11 runner 差异**(§六.5「未编目的差异算失败」)——用 **AST 级比对**而非抽读证明完整性(`_build_book_factors`/`_write_report`/`_section_payload` 11 份逐字符相同;其余 helper 剥掉字符串常量后坍缩成 1 组),另记 **7 个既有 bug**(只标不修)与 `FactorSpec` 16→20 键漂移(来自 #86/#91,须预登记否则对账时会被当 D5 回归去追)。**探测(`qt/saturation_probe.py`,可复跑工具非一次性脚本):D4 的 materializer 在真实评估面上跑不了**——995 票中 **84 票**首根 1min bar ≥ emit_start ⇒ pooled 饱和**永远无法提前终止、必打到 floor**(D4 已披露的代价在全规模是**构造性**兑现);磁盘 8.18/16.43 GB,名义内存 52.7/122.2 GB,而 **frame:峰值RSS 实测 2.2–2.45×**(`minute_bars` 逐票读完 `pd.concat`,parts 与结果同时在内存)⇒ 评估窗真实峰值 **≈115 GB vs 可用 56 GB**;**不止 pooled**——bounded 路径同样整 universe 单帧(`materialize.py:262`),光评估窗就超可用内存约一倍。**三条更便宜的出路全部证否**:按票分批会因 `service._ensure_coverage` 的缺口判定**只按日期不按 (date,symbol)** 而**静默丢名**(I5a 红线);按时间分块只救 3 个 bounded 因子;缩短窗口不动 pooled 加载左端(锚在 floor)。**关门的是 `intraday_amp_cut`**(**同时 pooled × 截面**)——按票分批毁其截面、按时间分块管不住其深度,两轴都绕不开。切口位置已实测:纯因子逐票 ≡ 整 universe **逐位相同**(728/1524 个可比 cell `max|diff|=0.0`),`intraday_amp_cut` 逐票 **1860 finite → 0** ⇒ **切口必须落在截面 combine 之前**。**暴露的设计层缺口(照实记)**:§八只给**决策热路径**(20 日尾窗)定过规模预算,**从未给评估路径定规模**,所以「整 universe 单帧」在设计评审里没人拦;而旧 runner docstring 白纸黑字写着 "the multi-year all-symbol minute panel is NEVER materialized"——**D4 的加载几何相对被替换对象是回归**,只是 D4 验收跑在 40 票 smoke 上看不见。lead 提的「复用 `panel_freeze.py` 的加载形态代替 D4b」**已证否**:它没有自己的加载形态,是 import 11 个 runner 调其私有 `_load_*_panel`——「复用」等于保留决策③要杀的第二条取数路径;可复用的是**形状**不是调用路径。⇒ **插入迁移步 D4b(per-symbol 流式物化)**,设计文档记为实施期修订 A1;C3–C6 刻意未开始(修 materializer 是改取值路径,须自带四腿验收,混进 D5 当「让 run 跑起来」正是本项目反复抓到的形态)。**评审两轮**:首轮 BLOCK 1 HIGH——被文档称作「幂等」的再冻结命令**静默销毁 provenance**(未改动树上跑,输出 `copied: 0 / already ok: 77` 报纯成功,git 里却清空 `source_note` 并把 `frozen_at_git_head` 改指向重跑者 = **主动的假声明**,而 **16 个测试全程绿灯**)→ 改为 provenance 继承 + 内容不变则一个字节不写 + **恒跑断言**(`source_note` 非空 / head ^[0-9a-f]{40}$ / sha256 合法 hex(原只验长度)/ `size_bytes`>0),评审逐条 mutation 四条全红;另修 2 MEDIUM(**本 PR 自己 suite 里的空 mutation**——那条 git-tracking 测试全程不碰 git,注释掉 `.gitignore` 仍通过 → 改查 **git 索引** `git ls-files -- `;**C6 爆炸半径漏编目 3 个 runner importer**,含**生产 D1 冻结基线的 `panel_freeze.py` 本身**,其重跑流程是「旧 SHA + 当前分支文件」的混合式、两种 C6 处置下都会失效)。**方法论(三个空 mutation,全部照实记)**:实现方两次(tamper 测试替换了文件里**不存在**的字节串;git 索引 mutation 用 `git add -f` 被 symlink 拒绝执行 → 什么也没改、测试**为错误的理由通过**),评审一次(它建议的 `git ls-files --error-unmatch` 对「未跟踪」与「路径不存在」**返回相同 rc=1**,据此的断言会在**最需要它的机器上空过**)——**三次都不是被测试抓住的,而是被「与预期矛盾的观察」抓住的;评审建议本身也需要 mutation 证据**。**顺带更正一条长期误诊**:「本机 pytest 摘要行被环境吞掉」是假的——`pyproject.toml:53` 已有 `addopts="-q"`,我们再传 `-q` 就是 `-qq`;去掉即出现 `N passed` 摘要行(点计数仍是有用的交叉校验,本轮就抓到 2113 vs 2114 之差,但它从来不是因为摘要不可得才必须存在)。gates:**2117 collected**(2116 passed + 1 skipped——跳的是字节绑定测试,其字节 gitignored;manifest 自洽测试**无 skipif 恒跑**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `--verify` 77/77 且 head 仍 `45c14aa` / 冻结面板 mtime 未变。 - ✅ 质量门(**当前 `main` @ `f432dc5` 实测**:`python -m pytest -p no:warnings` **1776 passed**、`ruff` clean、`validate-config` **31/31 配置逐个 OK**、`run-phase0`(demo)**ic 0.9600 / annual 0.8408 不变**)。构成对得上:`aa19968` 实测 **1740** → #78 加 2(含钉住破折号闭合的那条)= **1742** → #79 加 34(两个新测试文件,0 个既有测试被挤掉)= **1776**。新增测试分组(`--collect-only` 实数,`aa19968` 口径):**因子评估契约层 contract=337 + standard=113 + figures=7 / 十一因子(factor + eval runner,21 文件)=421 / PR#75 exec-vwap-basis=46 / D3 market quality 15→21(含 #77 `decreasing_adj_factor` 及其相对-vs-绝对尺度 mutation 测试)**。历史分组(旧 793 基线):`pytest` **793 passed**(P0=97 / P1=78 / P2-1=22 / P2-2=22 / P2-3=14 / P2-4=8 / P3-1=10 / P3-2=18 / P3-3=16 / P3-4=15 / P3-5=22 / P3-6=27 / P3-7=25+1 throttle / P3-8=8 / P4-1=28 / P4-2=17 / **intraday I1 schema=14 + feed=9 / I2 cache=10 / I3 aggregate=13 / I4 execution=10 / P4-3 cache=10 + updater=7 / P-I5a event-backtest=19 / P-I5b exec-feasibility=16 / P-I5c mmp-minute=18 / P-I5d mmp-quintile=19 / P-I5e 仅 config(无新测试,`test_cache_config` 的 config glob 自动 +1)/ P-I5f intraday-liquidity=17(+ `test_cache_config` config glob 自动 +1)/ D1 token-dedup index-feed +2 / D2 cache-modularization +5 / D3 data-quality market=15 + intraday=12 + report=14 / D3b data-update-quality=18 / D4 coverage-ledger-scaling=13 / D5 scheduler=9 + concurrency=12 / schema-registry-guard=62 / all-A-incremental=12 / all-A-backfill=22**);当时 `ruff` clean、`validate-config` 20 配置(data_update + phase_i5a…phase_i5f)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 自 P0 起从未变过**)。 - ⚠️ 剩余(已显式披露):日线 only、demo 路径非真数据、旧三因子无信号(P3-3/P3-4 实证;但其组合在 2024-2026 holdout 上 SSE50/CSI300/CSI500 全正、CSI500 高达 +17.8%——小样本/regime 翻转的持续例证);value/低波信号获得**独立样本符号级确认**(P3-7 SSE50/CSI300 量级衰减;P3-8 CSI500 泛化成立且更强),组合级盈利能力仍未确立(排名跨 cell 翻转);subset 报告文件名已可配置(P3-8 起不再互覆盖)。**分钟因子侧新增披露**:十一个复现因子全部 EXPLORATORY、**封顶 Watch,无一到 Adopt**,1× 费率下净多空为正的只有 2 个(PR-F/PR-L,且 PR-L 扛不住 2×)——**IC 强 ≠ 可交易**;MMP 的唯一正面证据(I5d)在修正引擎上退化、I5e 负结果加强;I5f 的容量结论已按**真实 100 万名义**重写(1000 万口径的"约半数不足"作废);**日频除权审计已完成**(GENUINE、无 vintage 接缝、评估池暴露 1/603,258,不重述任何因子结果),**分钟路径的复权缺陷已在 PR #75 修**;exec-to-exec 改基准已随 **PR #79 合并**,close-to-close 与 exec 两套 artifact 并存;⚠️ **#79 的 code review 未返回、靠自查合并**,其"未独立核"清单(五条 mutation 声称 / 十一个 runner 改动是否机械等同 / `execution_capacity` 透传)仍待后续检查——若查出问题,重述 exec 基准数字而非 close-to-close;schema 守卫**仍未接** live `data-update` 暖跑路径;HTML compendium(`artifacts/reports/factor_compendium.html`)**还读 v0.8 结果,待按最终结果修订**。 - 路线图下一步:**MMP 暂缓推进——理由在修正引擎上比过去更强,不是不变**(I5e 独立 universe CSI300 同窗口机器冻结复跑 → 单调性 **FAILS/反转** 且**在修正引擎上更负**:Spearman **−0.5000 不变**、Q5 高 MMP 仍最差、合成 Q5−Q1 累计 **−26.77% → −31.82%**;而 I5d 的 CSI500 完美单调性在修正引擎上**退化**(Spearman **+1.0000 → +0.9000**、Q5−Q1 **+17.15% → +8.65%**、Q5 让位 Q4),四档归因实测**归到复权修正本身**——原结论实质是"把除权下跌记成亏损"的产物 → **在出现 disjoint 窗口 / 第三 universe 的正向证据前,不把 MMP 当稳健或可交易信号推进**;新 intraday 因子候选只作显式 EXPLORATORY 工作);**I5f 已落地 → I5g(可选,须单独显式 goal)**(I5f 已加 report-only 执行流动性/容量诊断;**按用户真实规模 100 万 RMB / 5% 参与率重测:below-1.0x 由 20 笔变 0 笔、最紧 1.22×——单分钟容量在该 universe/窗口不构成约束**;此前"10M RMB 下约半数不足"的说法**已作废**,它描述的组合比本项目会跑的大一个数量级;**强制 partial-fill / volume-cap(真正约束成交)= 可能的 I5g,仅在单独显式 goal 后启动**,本阶段未做,不声称已实现);**盘后全A auto-fetch**(数据正确性审计 PASS——D3 质量层实测 80GB 真实缓存结构干净、ann_date PIT 轴 100%、跨 shard schema 无漂移;PR #59 = PR-1 全A 增量 auto-warm + systemd @21:00 default-off 已落地;**PR #61 = PR-2 全A 历史回填**——分块/断点续跑/分钟全窗口 + per-symbol 失败隔离 + `start>today` 守卫,已落地。**建设侧完成,剩 live rollout = 用户 Stage-1**:先 `data-backfill` 补全A 历史(可续跑)→ 手动跑增量 warm 观察 → enable systemd timer);**P4-3 follow-up**(fina 按 ann_date 建披露日历 ledger 以去掉启发式 tail / data-update summary 落 cache-stats artifact);**数据层 D6**(D1+D2+D3+D3b+D4+D5 已 merge:契约文档化 + token 解析收敛 + `TushareCache` specs/parsers 拆分 + report-only `data/quality/` 质量层 + default-off `data-update` 质量报告钩子 + coverage ledger `record_many` 批量写 + 进程内查找缓存 + opt-in 有界并发 + 全局限频器 + **schema 注册表/default-off drift 守卫(PR #57)**;剩余数据层 follow-up:schema 守卫接 live `data-update` 暖跑路径(当前仅接 pipeline/回测) + 分钟 schema 守卫;**D6**=`PanelStore` append/partition / 可选物化派生面板存储,**仅当因子研究需要可复用派生面板时才启动**——均尚未实现);**因子层收尾**(① `feat/exec-to-exec-rebasis` 两基准对照已跑完并随 **PR #79 合并**——22 格中 20 格不变、2 格朝更保守走;**补一次 #79 的 code review**(原评审未返回,未独立核的三项见上);② HTML compendium 按最终结果修订;③ 十一因子**无一到 Adopt、净多空几乎全负** → 下一步优先做**换手/成本敏感**的组合层验证与更长 holdout,而不是继续堆新因子);研究侧:更长 holdout 滚动复检 / 成本模型细化。 diff --git a/CLAUDE.md b/CLAUDE.md index 29fa153..6bbc60f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -57,7 +57,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri ## 开发约定 - **交流中文**;代码/注释/commit message 用**英文**。 -- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 +- **Git**:feature 分支 + PR。**PR #1(P0+P1)、#2(P2-1)、#3(P2-2)、#4(进度文档)、#5(P2-3)、#6(进度文档)、#7(P2-4)、#8(进度文档)、#9(P3-1)、#10(进度文档)、#11(P3-2)、#12(P3-3)、#13(进度文档)、#14(P3-4)、#15(进度文档)、#16(P3-5)、#17(进度文档)、#18(P3-6)、#19(P3-7)、#20(进度文档)、#21(P3-8)、#22(进度文档)、#23(P4-1)、#24(进度文档)、#25(P4-2)、#28(tushare 权限/限频探测 + capability registry)、#29(I1–I4 分钟级 intraday pipeline,4 commit 一 PR)、#30(进度文档)、#31(P4-3 因子支撑端点缓存 + 21:00 data updater,2 commit 一 PR)、#33(P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model,4 commit 一 PR)、#35(P-I5b 分钟尾盘执行期 raw stk_limit 涨跌停可行性,4 commit 一 PR)、#37(P-I5c MMP 分钟因子端到端 opt-in alpha)、#39(P-I5d MMP 五分位分组回测 standalone,含 I5c plumbing)、#41(数据层 D1 契约文档 + token 解析去重)、#43(数据层 D2 TushareCache specs/parsers 拆分)、#45(数据层 D3 report-only 数据质量层)、#47(数据层 D3b default-off `data-update` 质量报告钩子)、#49(数据层 D4 coverage ledger 批量写 + 进程内查找缓存)、#51(数据层 D5 opt-in 有界并发 + 全局限频器)、#53(P-I5e MMP 五分位 CSI300 独立泛化检验,负结果)、#55(P-I5f 分钟尾盘执行流动性/容量诊断,report-only)、#57(数据层 schema 注册表 + default-off drift 守卫)、#59(数据层 全A 增量 auto-warm + systemd 定时,default-off)、#61(数据层 全A 历史回填 `data-backfill`,分块/续跑/失败隔离)、#62(进度文档)、#63(因子评估契约层 `analytics/eval/` + StandardFactorEvaluator + dashboard + PR-C 因子,4 commit 一 PR)、#64–#73(PR-D…PR-M 十个分钟因子复现,**一因子一分支一 PR**)、#74(因子评估契约 v0.8 + v0.9 判定门修复)、#75(尾盘执行价 VWAP + 分钟持有期收益复权)、#76(报告披露修正 + I5f 名义按真实规模重测)、#77(`adj_factor` 下降质量检查)、#78(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、#79(十一因子改 14:51 VWAP exec-to-exec 基准,**评审未返回、靠自查合并**)、#82(闸门/成交价描述全仓清扫,12 处;#78 守卫射程不足的修正)、#80(进度文档)、#84(因子层重构 D0 纸面契约:availability policy 常量 + 预指派表 + 性质编目)、#85(进度文档)、#86(因子层重构 D1:registry + PanelField requires + FactorSpec 契约 v1.0)、#87(因子层重构 D1 面板冻结:14 因子 raw 基线 + manifest)、#88(进度文档)、#89(因子层重构 D2:minute primitives + ops + 11 因子迁移,与冻结基线逐位一致)、#90(进度文档)、#91(因子层重构 D3:store 层——稀疏值存储 + key/指纹 + tail-recompute + R5 fina 视界统一)、#92(进度文档)、#93(因子层重构 D4:FactorService + decision-view materializer + pooled 饱和填充)、#94(进度文档)、#95(因子层重构 D5a:exec 基线冻结 + 11 runner 差异编目 + 可行性探测)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -372,6 +372,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - **D2(PR #89,整步已关账——首个动数学步骤,实测逐位一致)**:`factors/ops/` 7 算子(momentum/volatility/liquidity/overnight_mom 改写其上,naive-oracle 等值锁定)+ `factors/compute/minute/`(primitives 吸收 `peak_mask_for_symbol` 单点定义 + 11 因子一因子一文件,数学+surface+声明同文件)+ R14 粒度 shim 化(10 纯模块 + intraday_derived AST 锁纯度;aggregate 通用核留真实代码;共享常量安家 intraday_schema——live import 测试证留 aggregate 成真环)。**验收三条独立路径互证**:① 逐格对账 vs D1 冻结基线 **14/14 `max_rel_diff=0.0`、canonical hash 全等(逐位一致)**;② 88 行分层手算锚 0 失配(脚本运行时守卫禁 import 引擎,曾自抓 3 个口径错);③ mutation 证据实跑 rc=1/rc=0 三组(评审活体复跑其二)。I5 四 run 值级锚全命中(I5b/I5f 1.019318;I5d Spearman +0.9;I5e −0.5)。PR-D 测量债清偿(4.58% 窗含真 ex-date,评审从冻结 manifest 独立复算,维持 CROSSED_DISCLOSED)。provisional 锚全精度值入测试(PROVISIONAL,D6 转正)。评审 APPROVE-WITH-NITS(1 LOW:guard_boundary 静默跳过无机器可读披露——当场修,skip 显式落 JSON)。留 D6 两注记:shim 期 aggregate→factors.minute 方向(披露的临时例外,D6d 日落);`asof_daily_features` 的 mmp_ew hook 届时需新家。gates:**1955 passed** / ruff / 31 configs / phase0 锚不变 / secret 0。 - **D3(PR #91,整步已关账——store 层,纯附加未接线)**:`factors/store/`(hashing/code_hash/fingerprint/keys/values/run_registry/incremental,全 <800 行)+ **R5 前置修复**(`fina_tail_days` 单一真相迁至 `data.cache.fina_tail_days`,回测 `_build_cache` 与 data-update 两 builder 统一传 fina 400 尾 override——回测 read-through 现会补 fina 尾窗,行为变更已披露;`data_update.fina_tail_days` 删除对 repo 外旧 YAML 属 breaking,仓内两 config 已迁)。key = params_hash + code_hash(自身模块 + 枚举共享集{minute primitives/ops/base/spec} + **one-hop 直接项目内 import 折叠**:AST 自动派生、无手工清单、不做传递闭包——评审 MEDIUM 实测 `reversal_20` 可 build 且值=−momentum 而 momentum.py 取值面不入 key = 陈旧复用洞,据此修;改 momentum → candidates 系 key 变、financial/分钟系不变,无全局过度失效)+ view + 数据指纹(schema-version 维 = data/clean PIT 承重模块内容 hash;`price_level` 另掺 per-symbol adj_factor 事件表 hash 含锚值,收官集零成员不豁免 fixture 测试)。存储:单文件 parquet date 排序 / 原子写 tmp+`os.replace` / per-artifact O_CREAT|O_EXCL 锁(两进程 gap-fill 零丢行实测;锁 neuter mutation 证明锁对原子写也承重)/ JSONL append-only 运行注册表(no-secret:sanitize_text 过自由文本,redaction 测试钉住)/ 损坏文件=miss / **不建 coverage ledger**(值确定性可重算)/ 启动一致性断言(registry 条目必须命中代码注册表)。tail-recompute:`w_overlap=max(W_dep, 端点修订视界)`——W_dep=传递 lookback 深度经 **`FactorSpec.lookback_depth`(optional 附加字段,contract v1.1)**声明、store 消费点 HARD-REQUIRE(14 真实因子未声明 → loud 报错,声明属预注册动作留 D4);视界经 `revision_horizon()` 从 live config 派生(调大 refresh_recent_days → 重叠窗变宽 mutation 实证,无硬编码 14/400);重叠 NaN-aware bitwise,失配按 adjustment 分类(returns_invariant→loud 上游回改记录 / price_level→预期);schema 指纹失配 → schema_void_full 全量重算不误报 revision;§六.18 teeth(headline 深度欠采 → 假 mismatch)测试钉住。#adjustment NET-NEW 性质测试钉本格:扰动 qfq 锚 → returns_invariant 真因子(日频 volatility_20 + 分钟 valley_relative_vwap)逐 bit 不变,批量 census 9/5/0 ≡ D0 表。评审 APPROVE-WITH-NITS(0 CRIT/HIGH,1 MEDIUM+3 LOW+1 NIT;MEDIUM/LOW-1/LOW-3 合并前修于 `fd906f4` 并经 delta 复核三项 CLOSED——评审亲手重跑 momentum on-disk mutation 5/5、allowlist 注入、锁 neuter,并猎杀「不可能失败的测试」零发现)。留 D4 注记:materializer 必须传 live `data.cache.fina_tail_days` 勿靠 400 默认;two-hop 组合链是 one-hop 折叠的已知边界(今日无实例,设计明令不做传递遍历器);`availability_policy` 编辑会 over-invalidate 其 importer 的 store(安全方向、D4/D5 churn 期真实重算成本);单点填≡批量填(P8)是 D4 验收项。gates:**2031 passed**(=1955+76)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 - **D4(PR #93,整步已关账——FactorService + materializer;四轮评审揪出两个 HIGH + 一项设计修正)**:`factors/service.py`(frozen `DecisionPoint` + `cross_section`/`panel` **都 read-through 读 D3 store**,miss 触发唯一引擎,配对合法性复用 D0 `require_legal_pairing` 构造期强制)+ decision-view materializer(R18 **全** policy-lag:日线非-open ≤ d−1、**open[d] 字段级例外从 policy 表派生**、daily_basic/fina ≤ d−1、分钟 ≤14:50;ex-date 只暴露**布尔**的类型边界;`CacheHorizonConfig` 从 live config 构造缺属性即 raise)+ process 编排下沉 `factors/process/orchestrate.py`(`_process_factors` 薄委托逐字行为保持)+ 14 因子 `lookback_depth` 预注册(参数化派生+测试钉死)+ 热路径计时 smoke(真实缓存 cache-only 40 票共享读 ≈2.0x,诚实标注不外推)。**评审故事(P8 单点填≡批量填连揪三层真缺陷)**:①【设计修正】valid-day **pooled** 因子(8/11 分钟因子按滚动机制码检划分,非按观察到分歧的 3 个——#82 教训)trailing N 个**有效日**的日历深度数据依赖、**无界** → **证否 v3.2 §3.3 R4「W_dep=各 lookback 之和」假设**,固定 40 日 trim 使单点填 vs 批量填 finite↔NaN 分歧;②首版不动点判据(值稳定+nbars 稳定)被评审构造 **>1 chunk 停牌 gap 反例**击穿(finite-vs-finite 静默错值)→ 改**结构性判据**(锁定单调性:丢窗口头部 baseline_days 交易日其余分类 FINAL;锁定区 output-date 计数 ≥ lookback_days,gap-immune)+ provider 显式 `earliest_available`(nbars 推断删除,中段 gap 不许当 data start),上版「divergence is gone」overclaim 在 commit message 开篇更正;③判据循环只遍历**有输出的** symbol → 长停牌票**无否决权被静默丢出截面**(撞 I5a 红线)→ 改遍历**请求的** symbol 列表,评审 fixture(600519 丢名复现 + 锁定偏移 416.0 vs 438.0 静默错值)全部落成 committed 测试 + 源码级 mutation 双 witness(rc=1/rc=0,评审亲手用自己未改动的脚本独立复跑确认)。`_MAX_SATURATION_CHUNKS` 耗尽改 loud raise(红线 #9)+ raise 分支有测试。**代价如实入 docstring**:凑不满 lookback 有效日的票拖全 universe 扩到声明 floor;per-symbol 饱和起点是 D5 优化**且非纯优化**(`intraday_amp_cut` 截面 z-score 耦合)。**早期区域量化(D5 面板腿归因名目)**:分钟缓存真实起点 **2015-01-05** → D1 冻结基线(锚 2021-07-01)对 pooled 因子属 **anchor 截断**,饱和加载在 2021-07→10 五票上 ridge 有 157/184 cell 不同(79 NaN→finite,按月递减至零)——D5 对账须具名归因「saturation vs anchor truncation」。JC1 已裁定:P8 逐 bit 对滚动因子降为 ≤1e-12 可归因浮点重排(实测 floor ~3.5e-18,真缺行效应 ≥7 个数量级于容差;NaN mask 必须精确)。留 D5/D6:声明 floor 应从分钟 coverage ledger 派生 per-symbol(现为硬编码常量,声明偏晚会静默截断);`valley_price_quantile` 分钟绑定 DEFERRED(loud 报错,已声明 pooled,D5 绑定继承饱和路径**不许**固定 trim 绕过);零输出否决语义已被测试+mutation 钉住,D5 为性能回退它=放回 HIGH;blanket shift 依赖「因子输入面板只含端点列」的 D6 wiring 契约。gates:**2098 passed**(=2031+67)/ ruff / 31 configs / phase0 锚不变 / provisional 锚绿 / secret 0。 + - **D5a(PR #95,D5 的前三块——冻结/编目/探测;探测结论迫使插入新迁移步 D4b)**:**C1 冻结 exec 对账基线**(`qt/exec_baseline_freeze.py`)——22 份 exec artifact 是后续一切对账的参照,却 **gitignored 只存在于本机**,且设计假定的耐久副本 `scratchpad/baseline_reports/` **早已不存在**;新 runner 沿用同名输出路径,**跑一次就毁掉唯一基线**,随后的「对账」会比对刚被自己覆盖的文件(= 本仓在案的 `compare_postmerge.py` 空对账形态)。实冻 **77 个文件**(不是交办的 44——同族还有 11 份 `_exec_basis_sanity.md` + 22 张 dashboard,同样单份不可再生),**sha256 manifest 入 git**(字节留 gitignored,哈希只能经评审 diff 变动),每次读都验哈希,读取器结构性拒绝 live 路径(直连/symlink 别名/`..` 三种绕过全拒)。**provenance 按证据强度分级**:观察到的是 77 文件共享毫秒级 mtime(批量拷贝签名),对照 44 份 close 基准的 11 个递进 mtime 与 #74 重跑窗口吻合;「字节出自 #79 run」标注为**推断非观察**,字段名故意叫 `frozen_at_git_head` 而非 `producing_sha`。**C2 编目 11 runner 差异**(§六.5「未编目的差异算失败」)——用 **AST 级比对**而非抽读证明完整性(`_build_book_factors`/`_write_report`/`_section_payload` 11 份逐字符相同;其余 helper 剥掉字符串常量后坍缩成 1 组),另记 **7 个既有 bug**(只标不修)与 `FactorSpec` 16→20 键漂移(来自 #86/#91,须预登记否则对账时会被当 D5 回归去追)。**探测(`qt/saturation_probe.py`,可复跑工具非一次性脚本):D4 的 materializer 在真实评估面上跑不了**——995 票中 **84 票**首根 1min bar ≥ emit_start ⇒ pooled 饱和**永远无法提前终止、必打到 floor**(D4 已披露的代价在全规模是**构造性**兑现);磁盘 8.18/16.43 GB,名义内存 52.7/122.2 GB,而 **frame:峰值RSS 实测 2.2–2.45×**(`minute_bars` 逐票读完 `pd.concat`,parts 与结果同时在内存)⇒ 评估窗真实峰值 **≈115 GB vs 可用 56 GB**;**不止 pooled**——bounded 路径同样整 universe 单帧(`materialize.py:262`),光评估窗就超可用内存约一倍。**三条更便宜的出路全部证否**:按票分批会因 `service._ensure_coverage` 的缺口判定**只按日期不按 (date,symbol)** 而**静默丢名**(I5a 红线);按时间分块只救 3 个 bounded 因子;缩短窗口不动 pooled 加载左端(锚在 floor)。**关门的是 `intraday_amp_cut`**(**同时 pooled × 截面**)——按票分批毁其截面、按时间分块管不住其深度,两轴都绕不开。切口位置已实测:纯因子逐票 ≡ 整 universe **逐位相同**(728/1524 个可比 cell `max|diff|=0.0`),`intraday_amp_cut` 逐票 **1860 finite → 0** ⇒ **切口必须落在截面 combine 之前**。**暴露的设计层缺口(照实记)**:§八只给**决策热路径**(20 日尾窗)定过规模预算,**从未给评估路径定规模**,所以「整 universe 单帧」在设计评审里没人拦;而旧 runner docstring 白纸黑字写着 "the multi-year all-symbol minute panel is NEVER materialized"——**D4 的加载几何相对被替换对象是回归**,只是 D4 验收跑在 40 票 smoke 上看不见。lead 提的「复用 `panel_freeze.py` 的加载形态代替 D4b」**已证否**:它没有自己的加载形态,是 import 11 个 runner 调其私有 `_load_*_panel`——「复用」等于保留决策③要杀的第二条取数路径;可复用的是**形状**不是调用路径。⇒ **插入迁移步 D4b(per-symbol 流式物化)**,设计文档记为实施期修订 A1;C3–C6 刻意未开始(修 materializer 是改取值路径,须自带四腿验收,混进 D5 当「让 run 跑起来」正是本项目反复抓到的形态)。**评审两轮**:首轮 BLOCK 1 HIGH——被文档称作「幂等」的再冻结命令**静默销毁 provenance**(未改动树上跑,输出 `copied: 0 / already ok: 77` 报纯成功,git 里却清空 `source_note` 并把 `frozen_at_git_head` 改指向重跑者 = **主动的假声明**,而 **16 个测试全程绿灯**)→ 改为 provenance 继承 + 内容不变则一个字节不写 + **恒跑断言**(`source_note` 非空 / head ^[0-9a-f]{40}$ / sha256 合法 hex(原只验长度)/ `size_bytes`>0),评审逐条 mutation 四条全红;另修 2 MEDIUM(**本 PR 自己 suite 里的空 mutation**——那条 git-tracking 测试全程不碰 git,注释掉 `.gitignore` 仍通过 → 改查 **git 索引** `git ls-files -- `;**C6 爆炸半径漏编目 3 个 runner importer**,含**生产 D1 冻结基线的 `panel_freeze.py` 本身**,其重跑流程是「旧 SHA + 当前分支文件」的混合式、两种 C6 处置下都会失效)。**方法论(三个空 mutation,全部照实记)**:实现方两次(tamper 测试替换了文件里**不存在**的字节串;git 索引 mutation 用 `git add -f` 被 symlink 拒绝执行 → 什么也没改、测试**为错误的理由通过**),评审一次(它建议的 `git ls-files --error-unmatch` 对「未跟踪」与「路径不存在」**返回相同 rc=1**,据此的断言会在**最需要它的机器上空过**)——**三次都不是被测试抓住的,而是被「与预期矛盾的观察」抓住的;评审建议本身也需要 mutation 证据**。**顺带更正一条长期误诊**:「本机 pytest 摘要行被环境吞掉」是假的——`pyproject.toml:53` 已有 `addopts="-q"`,我们再传 `-q` 就是 `-qq`;去掉即出现 `N passed` 摘要行(点计数仍是有用的交叉校验,本轮就抓到 2113 vs 2114 之差,但它从来不是因为摘要不可得才必须存在)。gates:**2117 collected**(2116 passed + 1 skipped——跳的是字节绑定测试,其字节 gitignored;manifest 自洽测试**无 skipif 恒跑**)/ ruff / 31 configs / phase0 锚不变 / secret 0 / `--verify` 77/77 且 head 仍 `45c14aa` / 冻结面板 mtime 未变。 - ✅ 质量门(**当前 `main` @ `f432dc5` 实测**:`python -m pytest -p no:warnings` **1776 passed**、`ruff` clean、`validate-config` **31/31 配置逐个 OK**、`run-phase0`(demo)**ic 0.9600 / annual 0.8408 不变**)。构成对得上:`aa19968` 实测 **1740** → #78 加 2(含钉住破折号闭合的那条)= **1742** → #79 加 34(两个新测试文件,0 个既有测试被挤掉)= **1776**。新增测试分组(`--collect-only` 实数,`aa19968` 口径):**因子评估契约层 contract=337 + standard=113 + figures=7 / 十一因子(factor + eval runner,21 文件)=421 / PR#75 exec-vwap-basis=46 / D3 market quality 15→21(含 #77 `decreasing_adj_factor` 及其相对-vs-绝对尺度 mutation 测试)**。历史分组(旧 793 基线):`pytest` **793 passed**(P0=97 / P1=78 / P2-1=22 / P2-2=22 / P2-3=14 / P2-4=8 / P3-1=10 / P3-2=18 / P3-3=16 / P3-4=15 / P3-5=22 / P3-6=27 / P3-7=25+1 throttle / P3-8=8 / P4-1=28 / P4-2=17 / **intraday I1 schema=14 + feed=9 / I2 cache=10 / I3 aggregate=13 / I4 execution=10 / P4-3 cache=10 + updater=7 / P-I5a event-backtest=19 / P-I5b exec-feasibility=16 / P-I5c mmp-minute=18 / P-I5d mmp-quintile=19 / P-I5e 仅 config(无新测试,`test_cache_config` 的 config glob 自动 +1)/ P-I5f intraday-liquidity=17(+ `test_cache_config` config glob 自动 +1)/ D1 token-dedup index-feed +2 / D2 cache-modularization +5 / D3 data-quality market=15 + intraday=12 + report=14 / D3b data-update-quality=18 / D4 coverage-ledger-scaling=13 / D5 scheduler=9 + concurrency=12 / schema-registry-guard=62 / all-A-incremental=12 / all-A-backfill=22**);当时 `ruff` clean、`validate-config` 20 配置(data_update + phase_i5a…phase_i5f)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 自 P0 起从未变过**)。 - ⚠️ 剩余(已显式披露):日线 only、demo 路径非真数据、旧三因子无信号(P3-3/P3-4 实证;但其组合在 2024-2026 holdout 上 SSE50/CSI300/CSI500 全正、CSI500 高达 +17.8%——小样本/regime 翻转的持续例证);value/低波信号获得**独立样本符号级确认**(P3-7 SSE50/CSI300 量级衰减;P3-8 CSI500 泛化成立且更强),组合级盈利能力仍未确立(排名跨 cell 翻转);subset 报告文件名已可配置(P3-8 起不再互覆盖)。**分钟因子侧新增披露**:十一个复现因子全部 EXPLORATORY、**封顶 Watch,无一到 Adopt**,1× 费率下净多空为正的只有 2 个(PR-F/PR-L,且 PR-L 扛不住 2×)——**IC 强 ≠ 可交易**;MMP 的唯一正面证据(I5d)在修正引擎上退化、I5e 负结果加强;I5f 的容量结论已按**真实 100 万名义**重写(1000 万口径的"约半数不足"作废);**日频除权审计已完成**(GENUINE、无 vintage 接缝、评估池暴露 1/603,258,不重述任何因子结果),**分钟路径的复权缺陷已在 PR #75 修**;exec-to-exec 改基准已随 **PR #79 合并**,close-to-close 与 exec 两套 artifact 并存;⚠️ **#79 的 code review 未返回、靠自查合并**,其"未独立核"清单(五条 mutation 声称 / 十一个 runner 改动是否机械等同 / `execution_capacity` 透传)仍待后续检查——若查出问题,重述 exec 基准数字而非 close-to-close;schema 守卫**仍未接** live `data-update` 暖跑路径;HTML compendium(`artifacts/reports/factor_compendium.html`)**还读 v0.8 结果,待按最终结果修订**。 - 路线图下一步:**MMP 暂缓推进——理由在修正引擎上比过去更强,不是不变**(I5e 独立 universe CSI300 同窗口机器冻结复跑 → 单调性 **FAILS/反转** 且**在修正引擎上更负**:Spearman **−0.5000 不变**、Q5 高 MMP 仍最差、合成 Q5−Q1 累计 **−26.77% → −31.82%**;而 I5d 的 CSI500 完美单调性在修正引擎上**退化**(Spearman **+1.0000 → +0.9000**、Q5−Q1 **+17.15% → +8.65%**、Q5 让位 Q4),四档归因实测**归到复权修正本身**——原结论实质是"把除权下跌记成亏损"的产物 → **在出现 disjoint 窗口 / 第三 universe 的正向证据前,不把 MMP 当稳健或可交易信号推进**;新 intraday 因子候选只作显式 EXPLORATORY 工作);**I5f 已落地 → I5g(可选,须单独显式 goal)**(I5f 已加 report-only 执行流动性/容量诊断;**按用户真实规模 100 万 RMB / 5% 参与率重测:below-1.0x 由 20 笔变 0 笔、最紧 1.22×——单分钟容量在该 universe/窗口不构成约束**;此前"10M RMB 下约半数不足"的说法**已作废**,它描述的组合比本项目会跑的大一个数量级;**强制 partial-fill / volume-cap(真正约束成交)= 可能的 I5g,仅在单独显式 goal 后启动**,本阶段未做,不声称已实现);**盘后全A auto-fetch**(数据正确性审计 PASS——D3 质量层实测 80GB 真实缓存结构干净、ann_date PIT 轴 100%、跨 shard schema 无漂移;PR #59 = PR-1 全A 增量 auto-warm + systemd @21:00 default-off 已落地;**PR #61 = PR-2 全A 历史回填**——分块/断点续跑/分钟全窗口 + per-symbol 失败隔离 + `start>today` 守卫,已落地。**建设侧完成,剩 live rollout = 用户 Stage-1**:先 `data-backfill` 补全A 历史(可续跑)→ 手动跑增量 warm 观察 → enable systemd timer);**P4-3 follow-up**(fina 按 ann_date 建披露日历 ledger 以去掉启发式 tail / data-update summary 落 cache-stats artifact);**数据层 D6**(D1+D2+D3+D3b+D4+D5 已 merge:契约文档化 + token 解析收敛 + `TushareCache` specs/parsers 拆分 + report-only `data/quality/` 质量层 + default-off `data-update` 质量报告钩子 + coverage ledger `record_many` 批量写 + 进程内查找缓存 + opt-in 有界并发 + 全局限频器 + **schema 注册表/default-off drift 守卫(PR #57)**;剩余数据层 follow-up:schema 守卫接 live `data-update` 暖跑路径(当前仅接 pipeline/回测) + 分钟 schema 守卫;**D6**=`PanelStore` append/partition / 可选物化派生面板存储,**仅当因子研究需要可复用派生面板时才启动**——均尚未实现);**因子层收尾**(① `feat/exec-to-exec-rebasis` 两基准对照已跑完并随 **PR #79 合并**——22 格中 20 格不变、2 格朝更保守走;**补一次 #79 的 code review**(原评审未返回,未独立核的三项见上);② HTML compendium 按最终结果修订;③ 十一因子**无一到 Adopt、净多空几乎全负** → 下一步优先做**换手/成本敏感**的组合层验证与更长 holdout,而不是继续堆新因子);研究侧:更长 holdout 滚动复检 / 成本模型细化。