From b542082bcd9dd1975c73e8f0666daa0ac56746a8 Mon Sep 17 00:00:00 2001 From: shaofl <2899218482@qq.com> Date: Tue, 21 Jul 2026 13:45:09 -0700 Subject: [PATCH 1/2] docs: record PR #62-#77, the factor evaluation contract layer, and the corrected-engine re-runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLAUDE.md's progress section stopped at PR #61. Fourteen merged PRs were unrecorded, including the entire factor-evaluation contract layer (analytics/eval/) and eleven reproduced minute factors, so a future session would have re-derived them or acted on superseded conclusions. Added entries (every number traceable to tmp/design/RESULTS_post_pr75_2026-07-21.md, tmp/design/FINDING_adj_factor_seam_2026-07-21.md, tmp/design/HANDOFF_2026-07-21.md, tmp/Quantitative_Research_Report/factors/ledger.md, or gh pr view): - factor evaluation contract layer + eleven minute factors (#63-#73) - evaluation contract v0.8 + v0.9, and the post-merge eleven-factor reconciliation, including the reconciliation script that could not fail - VWAP fills + corporate-action-adjusted intraday holding returns (#75) - report disclosure fix + I5f re-measured at the real notional (#76), with the still-open #78 follow-up - decreasing-adj_factor quality check, threshold 1% from the cache sweep (#77) - daily ex-dividend correctness audit: no vintage seam, 1 exposed pair in 603,258 - I5d / I5e / I5f re-run on the corrected engine - eleven factors re-based on the 14:51 VWAP exec-to-exec return (PR not yet open) Every NAV in the re-runs rose because of the ex-dividend bug fix, not because performance improved; the VWAP fill basis is itself slightly unfavourable. Both are stated as such. The MMP stance is updated to reflect that its only positive evidence degraded while the negative result strengthened. Updated existing lines: the PR list, the quality-gate line (pytest 1740 passed, 31/31 configs, phase0 0.9600/0.8408 — all measured on this tree), the disclosed remainder, and the roadmap. --- CLAUDE.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 9465f32..d31f38e 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`,分块/续跑/失败隔离)均已 merge 到 `main`**。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` 下降质量检查)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)、**#78**(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -267,6 +267,87 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - **`start > today` 守卫**:逆序窗口本会被 `subtract_intervals` 当"零缺口=已覆盖"→ 未来 start typo 静默 no-op;故加 loud `ValueError`(仿 `DataCfg._check_date_order`)。config `data_update.backfill: {start, chunk_size, include_minute}`(全默认 → 现存配置照常 validate);`config/data_update_all_a.yaml` 加 `backfill:` 块 + 诚实成本注(冷全A 分钟回填数小时~多日,可续跑)。ops doc 加"历史回填"节(先回填再 enable 夜间 timer)。 - **不变量**:增量 `run_data_update` 路径**字节级不变**——唯一共享改动是 `_build_scheduler`/`_build_caches` verbatim 抽取(same kwargs/顺序);49 个既有 data_update 测试原样过(main-vs-branch pytest 对照 **771→793 恰好 +22、0 既有测试被动**)。phase0 `0.9600/0.8408` 不变;缓存仍 raw-only;无 token。 - **review 两轮**(cc 接替外部 reviewer 验收):security CLEAN(失败/进度日志只 counts+异常类型);code-review 无 CRIT/HIGH(共享重构 verbatim 验证),修 2 MEDIUM(`start>today` 静默 no-op 守卫 + 失败×续跑联合测)+ LOW(summary 显并发模式)。独立重跑 **793 passed / ruff / 20 配置 / phase0 0.9600·0.8408**。**建设侧完成;live rollout(先 `data-backfill` 补史 → 手动增量 warm → enable timer)= 用户 Stage-1 driver**。 -- ✅ 质量门:`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_i5b + phase_i5c + phase_i5d + phase_i5e + phase_i5f)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 不变**)。 -- ⚠️ 剩余(已显式披露):日线 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 起不再互覆盖)。 -- 路线图下一步:**MMP 暂缓推进(I5e 负结果)**(I5e 已在独立 universe CSI300 同窗口机器冻结复跑 → 单调性 **FAILS/反转**(Spearman −0.5,Q5 高 MMP 最差,合成 Q5−Q1 累计 −26.77%);I5d 的 CSI500 单调性疑 universe/regime 特异、**非稳健** → **在出现 disjoint 窗口 / 第三 universe 的正向证据前,不把 MMP 当稳健或可交易信号推进**;新 intraday 因子候选只作显式 EXPLORATORY 工作);**I5f 已落地 → I5g(可选,须单独显式 goal)**(I5f 已加 report-only 执行流动性/容量诊断,实测 10M RMB/5% 参与率下约半数 SSE50 单分钟 desired trade 容量不足;**强制 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 / 可选物化派生面板存储,**仅当因子研究需要可复用派生面板时才启动**——均尚未实现);研究侧:更长 holdout 滚动复检 / 成本模型细化。 +- ✅ **因子评估契约层 `analytics/eval/` + 十一个分钟因子复现**(**PR #63–#73 已 merge 到 `main`**,**EXPLORATORY,非业绩声明**):研报 → 复现循环(10/10 收官)与支撑它的判定契约层。全部因子同一数据面:CSI500 `000905.SH` 2021-07-01→2026-06-30 日频、cache-only(`stk_mins_live_calls=0`)、每因子 no_book / with_book 两跑(因子簿 = 已确认的 value_ep + value_bp + volatility_20)。 + - **契约层(PR #63,v0.1→v0.7 迭代后 frozen)**:`FactorSpec`(Factor 必带 classattr、**预注册 `expected_ic_sign`**、PIT 契约、intraday 块校验)+ `FactorEvaluator` ABC(8 个必填 section,缺一即 raise)+ `FactorEvalReport`(确定性 md/json,secret-redacting renderer)+ **三轴判决 Predictive × Incremental × Tradable → Adopt / Watch / Reject / INSUFFICIENT-DATA**。三条判定纪律:**非对称门**(hard Reject 先于样本量门)、**unknown never convicts**(判不了绝不定罪)、**PASS 一律读 N_eff 置信区间下界**(`N_eff = N/(1+2Σρ)`,Geyer 扩展;点估计不得买 PASS)。v0.7:增量轴独立门 `min_incremental_abs_icir=0.15`(正交化收缩残差尺度,沿用原始 0.30 是类别错误)+ 单调性作**方向门**(默认 0.0,非强度门)。exploratory 因子**封顶 Watch**(Tradable 轴全程 NOT_ASSESSED)。一次向量化 IR 喂全部 section(与朴素逐期循环等价性测试锁定)+ 单 PNG dashboard,带**强制 FACTOR DEFINITION 带**——不说明怎么算就不许展示因子。 + - **十一因子(下表 verdict 为当前 v0.9 close-to-close 口径,非各 PR 当时口径;出处 `tmp/design/RESULTS_post_pr75_2026-07-21.md` 参照表 + `tmp/Quantitative_Research_Report/factors/ledger.md`)**: + + | PR | 因子 | 家族 | sign | IC | ICIR | 换手 | 净1× | no_book / with_book | + |---|---|---|---|---|---|---|---|---| + | #63 | `jump_amount_corr` | 跳跃×成交额相关 | −1 | −0.0298 | −0.401 | 0.415 | −0.000834 | Watch / Watch | + | #64 | `minute_ideal_amplitude` | 振幅 | −1 | −0.0291 | −0.464 | 0.990 | −0.001981 | Watch / Watch | + | #65 | `amp_marginal_anomaly_vol` | 振幅波动 | **+1** | −0.0412 | −0.425 | 0.285 | −0.000504 | Reject / Reject(documented negative:预注册 +1 未迁移,**实测负 IC ≠ sign=−1**) | + | #66 | `volume_peak_count` | 计数 | +1 | +0.0177 | +0.210 | 0.304 | **+0.000071** | Reject / Reject(符号迁移成功但 ICIR 下界 0.151 < 0.30 预注册门) | + | #67 | `intraday_amp_cut` | 振幅 | −1 | −0.0347 | −0.435 | 0.578 | −0.000260 | **INSUFFICIENT-DATA** / Watch | + | #68 | `peak_interval_kurtosis` | 时序 | +1 | +0.0002 | +0.006 | 0.576 | −0.000463 | Reject / Reject(诚实空结果;研报称 RankIC +7.19%/ICIR 4.63 → 本循环最大复现落差) | + | #69 | `valley_relative_vwap` | 价格比值 | +1 | +0.0327 | **+0.506** | 0.473 | −0.000085 | Watch / Watch | + | #70 | `valley_ridge_vwap_ratio` | 价格比值 | +1 | +0.0339 | +0.425 | **2.101** | −0.001705 | Watch / Watch(对齐单调 CI 下界仅 **+0.0010**,全表最薄) | + | #71 | `ridge_minute_return` | 收益 | −1 | −0.0312 | −0.381 | **2.108** | −0.001983 | **INSUFFICIENT-DATA** / Reject(增量轴与因子簿冗余) | + | #72 | `valley_price_quantile` | 价格位置 | +1 | +0.0265 | +0.414 | 0.679 | **+0.000048** | Watch / Watch(按日单调 +0.1064 全表最高) | + | #73 | `peak_ridge_amount_ratio` | 成交额 | +1 | **+0.0401** | +0.488 | **2.127** | −0.001402 | Watch / Watch(IC 全场最高,零价格含量) | + + - **三条循环级结论**:① **家族图谱**——计数弱正 / 时序归零 / 收益 Reject / **价格比值×2 + 价格位置 + 成交额 = 四个双轴 PASS**;峰岭谷行为学划分本身有效,且 **不止价格信息有效**(PR-M 零价格含量却 IC 最高)。② **IC 强 ≠ 可交易(贯穿证据)**——11 个因子里只有 PR-F(+0.71bp)与 PR-L(+0.48bp)在 1× 费率下净多空为正,且 PR-L 扛不住 2×;毛价差常相近,差距**几乎全部来自换手**(PR-I/L 的 0.47/0.68 vs PR-J/K/M 的 2.1+)。③ **假说证伪记录(不得作为已确立规律引用)**——"秩IC/Pearson 背离比预测单调性"被 PR-M 证伪(3.86×→0.60 与 PR-J 4.22×→0.90 交叉),仅两个极端处有不确定关联。 + - **方法论(本轮建立,已作常设规则)**:① **不可能失败的测试**——三个实例:PR-L 的旗舰反泄漏测试(全截面统一扰动是带截距 OLS 残差不可见的仿射变换)、`compare_postmerge.py`(拿新结果和自己比,见下条 #74 重跑对账)、I5b fixture 给每根 bar 定价使 **VWAP ≡ close**(对"闸门读哪个"结构性失明)。**任何不变性测试都必须有实际跑过的 mutation 证据,且 mutation 要打中所主张的那个具体性质**。② **行为变了而措辞没变**——见 #76/#78:一个主张若在 N 处散文里重复,要**断言不存在第 N+1 处**,而不是枚举你知道的那几处。 +- ✅ **因子评估契约 v0.8 + v0.9**(**PR #74 已 merge 到 `main`**,`1ae555e`):十一个因子在 `analytics/eval/` **严格 no-touch** 下跑完后暴露的两项 frozen 缺陷,本 PR 是**对该 frozen 契约的首次授权修改**。 + - **缺陷一:对齐净价差把成本加了回去(判定门缺陷,非仅展示)**。四处写成 `sign * net`(`net` 已扣成本),`sign=−1` 下展开为 **`−gross + cost`**——因子付的手续费被当利润返还。正确语义 `aligned = sign*gross − cost`(先按假设翻腿、再永远扣成本)。**其中两处在 `verdict.py`(`_base_spread` / `_all_spreads_negative`),直接喂 Tradable 轴 PASS 条件**,历来未触发仅因该轴全程 NOT_ASSESSED。手算实证:`gross 0.000125 / net 1× −0.001983 → cost 0.002108 → aligned −0.002233`(缺陷式给 **+0.001983**)。`sign=+1` 逐比特不变。年化展示值修正:jump_amount_corr **+23.14%→−0.01%**、minute_ideal_amplitude **+64.07%→−0.27%**、intraday_amp_cut **+6.30%→−20.52%**、ridge_minute_return **+64.28%→−43.25%**(**旧值全是虚高**)。 + - **缺陷二:用量级敏感的池化统计量给秩基轴把门**。`monotonicity_spearman` 是"桶序号 vs 跨日等权算术均值"的相关,无界,少数极端收益日集中于某桶即可翻号,而每日封顶的秩 IC 几乎不动。新增 `monotonicity_spearman_by_date`(逐日 Spearman,先封顶 [−1,1] 再平均,与秩 IC 同构)并把门移过去;池化版保留为报告字段 + 回退披露。 + - **v0.9:新统计量被日内噪声衰减,裸 0.0 门落在噪声带内**。实测分位阶梯完美的因子按日只有 **0.045–0.106**,门却仍在裸 0.0 且无离散度估计,两个因子相差 0.021 就分生死。改为读该按日序列的 **N_eff 置信区间**(复用既有 `mean_ci`),三值:对齐 CI 下界 > bar → **HOLDS**;对齐 CI 上界 < 0 → **CONTRADICTED**(FAIL);跨零 → **UNKNOWN**(既不定罪也不放行)。实测 CI 半宽 **0.0291–0.0448** → 裸 0.0 实为一道约 0.035 的隐式门槛。**最要害的路由规则:UNKNOWN 绝不救本就不合格的因子**——单调性已从点信号布尔链中摘出(三值事实塞进 `and` 链必然坍缩),ICIR / NW-t / win / OOS 任一不清关仍走 FAIL,UNKNOWN 只在其余全清关时把预测轴落到 INSUFFICIENT_DATA。 + - **3 处 verdict 变化**(全部归因于门的变化,并如此陈述):`intraday_amp_cut`(no_book) Reject→INSUFFICIENT-DATA(对齐 CI [−0.0353,+0.0343] 跨零)、`intraday_amp_cut`(with_book) **Reject→Watch**(同上 + 增量轴本就 PASS)、`ridge_minute_return`(no_book) Watch→INSUFFICIENT-DATA(对齐 CI [−0.0151,+0.0558] 跨零)。`ridge_minute_return` 跨三版本轨迹 **v0.7 Reject → v0.8 Watch → v0.9 INSUFFICIENT-DATA**:前两次都是在噪声上判决、只是方向不同,第三次才承认判不了。 + - **不变量**:IC / ICIR / NW-t / win / 增量 ICIR / 两个单调点值 **全部逐比特不变**(修复未泄漏到 IC 路径与增量路径)。**路由自检**:`amp_marginal_anomaly_vol`(OOS 符号翻转,第一步即 FAIL)与 `peak_interval_kurtosis`(OOS 不一致 + ICIR 0.006)单调方向均为 UNKNOWN 但仍 Reject,无渗漏。 + - **合并后十一因子干净全量重跑(`main` @ `1ae555e`,11/11 rc=0,~87min)**:`repro_reconcile.py` 11 因子 × 20 字段 = 220 项,**容差 0.0**(精确浮点相等,不用 `isclose`、不留 epsilon —— 1e-6 是"可能动"的下限,用恰好为零来测才能让任何 ≥ 该下限的变化浮出来)→ **0 处差异**;`repro_compare.py` 对 22 个 JSON artifact 做展平叶子深比 → **5,756 叶、0 处不同**,外加 **22/22 Markdown 逐字节相同**。防空过:22 个 JSON 确实被重写(mtime 落在各自 run 窗口 09:24:33→10:43:54)、前后 HEAD 都是 `1ae555e`、11 个 rc=0、全程 `stk_mins_live_calls=0`。 + - ⚠️ **记一次自己的失误:写了一个不可能失败的对账脚本**。第三个脚本 `scratchpad/compare_postmerge.py` 曾被跑并报出结论,**但它是空的,其输出什么也不证明**:它执行 `_baseline_table.py` 取新值,而那个脚本第 123 行**会写** `baseline_rows.json`,随后"旧值"读的正是刚被覆盖的同一个文件 → `old == new` 由构造成立,哪怕 artifact 错得离谱也会打印"11 个全部精确复现"(已在沙箱里用 baseline `ic=1.0` vs fresh `ic=999.0` 复现该假通过)。它还顺带毁掉了 `baseline_rows.json`。**这正是整轮重跑要消灭的失效模式,而我们亲手造了一个**(同 P2-3「曾误以为是粒度」、P3-4「过拟合签名」,照实记录)。上面的结论只站在不碰该文件的两个脚本上(其中一个跑在覆盖之前)。**权威基线是 `scratchpad/baseline_reports/`(22 文件,冻结于 run 前);复核必须比它,不是 `baseline_rows.json`。** +- ✅ **尾盘执行价改 VWAP + 分钟持有期收益复权**(**PR #75 已 merge 到 `main`**):两项改动都源于"14:50 就知道的信号为什么按 15:00 形成的价格计分"。 + - **改动 1:成交价 = 执行 bar 的 VWAP**(`amount/volume`,整分钟成交量加权均价)而非收盘 tick。`IntradayCfg.execution_price_basis: "bar_vwap"|"bar_close"`,默认 `bar_vwap`;`bar_close` **逐比特复现旧行为**——用独立 worktree 跑 main 版本、**字节比对价格矩阵与完整 fills 日志**(含 `exec_time` 与 block `reason`)验证,非断言。VWAP 未定义(volume≤0 / amount≤0 / 非有限)→ 走**显式阻挡**路径,**绝不退回 bar 收盘价、更不退回日收盘**。 + - **闸门改比实际成交价**:涨停分钟只有两种形态——**LOCKED 封死**(全部成交在涨停价 → VWAP = 涨停价)与 **OPENED 盘中打开**(有成交低于涨停 → VWAP < 涨停价),恰好对应"能不能买到";按收盘价判两头都错。这是**有意的行为变化,且被计数不被静默**:`opened_limit_up_minutes()` / `opened_limit_down_minutes()` 报出与收盘价闸门的每一处分歧。真实数据取证:`601858.SH 2023-05-15 14:51`,close = up_limit 46.13、VWAP 46.048583(差 0.18%,远高于舍入量级)。 + - **容差保持 `1e-6`**:实测 13,699 根 14:51 bar(149 根收在限价),LOCKED 偏离 ≤0.0021%、OPENED 0.013–0.017%(两总体不重叠)。1e-6 下 100% 的 OPENED 正确放行,代价是 2.1% 的 LOCKED 被误判为打开(≈全样本 0.02%)。**残差偏乐观且有界**,已写入 docstring。0.001 在本样本双向为 0%,但那是在 149 个观测上重标定阈值 = 后验调参,不为 0.02% 的效应破例。 + - **改动 2:分钟持有期收益复权(先前缺陷)**。`holding_returns` 原在 **raw 未复权价**上算 `exec(exit)/exec(entry)−1`,而日频模型用 qfq 面板 → 两条路径不对称,除权除息的机械性下跌被读成亏损。改为 `(raw_exit·af_exit)/(raw_entry·af_entry)−1`(qfq 锚在比值中相消,无需另存复权序列)。缺 `adj_factor` **不静默按 1.0**(那会把刚去掉的除权偏差放回来),走既有丢弃路径 + `missing_adj_factor_pairs()` 计数。复权**不渗进 I5b 限价闸门**(保持 raw-vs-raw),有专测钉住。 + - **实测发生率(月频调仓)**:I5d CSI500 52,923 个 (symbol, 持有期) 对中 **4,450 (8.41%)** 跨 `adj_factor` 变化,修正均值/中位 **+3.92% / +1.07%**,92.9% 为正;I5e CSI300 26,314 对中 **2,566 (9.75%)**,**+3.74% / +1.31%**,94.5% 为正。均值远高于中位 = 右尾**送转股**(af 翻倍 → raw 价腰斩 → 未复权读成 −50% 假亏损)。 +- ✅ **报告披露修正 + I5f 名义按真实规模重测**(**PR #76 已 merge 到 `main`**,`runtime/` 行为未变):**报告曾谎报自己做的检查**——PR #75 把闸门从 bar 收盘价移到实际成交价,却漏改了两个 report writer 里**描述闸门本身**的那句,此后每次跑出的报告都在描述一个它没有执行的检查。在"绝不静默降级"是常设红线的项目里,报告写错自己的方法比不出报告更糟。 + - **三个一直在算却被丢弃的计数器进报告**:`opened_limit_up_minutes` / `opened_limit_down_minutes`(本闸门与收盘价闸门的**全部分歧集合**——什么能不能成交变了,绝不许静默)、`missing_adj_factor_pairs`(因锚点 `adj_factor` 不可用而丢掉的持有期;非零即已测覆盖率短少)。尾盘报告另行声明收益是复权的并给出恒等式("exec-to-exec"一词已不足以描述它们)。 + - 措辞抽成 `limit_basis_lines()` 并由三个测试钉住;**mutation evidence 实跑**:把措辞改回收盘口径 → 2 个测试 FAIL;从分组表里删掉新计数器 → 第 3 个 FAIL。**旧 I5b 测试为何没抓到**:其 fixture 给每根执行 bar `volume=1.0, amount=close` → **VWAP ≡ close**,使所有断言在两个基准上都成立,对"闸门读哪个"结构性失明;已写进 module docstring 防止重建同一盲点。 + - ⚠️ **follow-up(PR #78 OPEN,未合并)**:#76 的扫描式正则守卫被 review 用**七种自然改写实测全部逃逸**证否——正则守不住语义主张。#78 把闸门描述改成**单一来源** `limit_basis_phrase()`(三处组合它而非各写各的),正则守卫保留但把 docstring 缩到它真能做的事(抓字面 revert);**渲染输出逐字节不变**。 +- ✅ **`adj_factor` 下降质量检查**(**PR #77 已 merge 到 `main`**,D3 层新检查,WARNING、report-only):`data/quality/market.py::check_decreasing_adj_factor` 接进 `run_adj_factor_checks`。tushare 的累计复权因子随每次公司行为**只增不减**,`front_adjust` 拿它乘 raw 价,一个发布出来的下降会直穿到每一个下游收益;而真实实例是**手工**发现的(见下条审计)。 + - **阈值 1%(相对,非绝对)由全缓存扫描定**(扫全部 5562 只已缓存票的每一个负步进:7898 个事件、涉及 4479 只票): + + | 阈值 | 触发事件数 | 触发的**非已知缺陷**票数 | + |---|---|---| + | 0.01% | 3653 | 2429(纯浮点噪声) | + | 0.10% | 179 | 2 | + | 0.50% | 178 | 1(`603081.SH`) | + | **1.00%** | **177** | **0** | + | 2.00% | 176 | 0 | + + 低于 1% 会点名状态**判不了**的票:`603081.SH` 最坏步 −0.776%,对应 raw close −1.810%,而真实公司行为需要 +0.782%——有缺陷的**形状**,但在该量级上普通日波动淹没隐含值,价格检验没有功效,结论不可解释。高于 1% 则漏掉一个真事件(1% 触发 177、2% 只触发 176,多出的那个属已知缺陷票)。1% 同时让最小的**已确认**缺陷(`000998.SZ` −2.636%)站在门槛的 2.6× 而非 1.3×——report-only 层宁可误报(代价一行 WARNING)也不可漏报(代价是被污染的价格静默通过)。 + - **相对而非绝对**(factor 跨缓存 ~1…~500):mutation 实证 `pct_change()`→`diff()` 让原六个测试**全部通过**(fixture 都落在 factor ~1–11 两种切法重合处),补两个别的尺度才有牙(`0.200→0.195` 是真 −2.5% 断裂而绝对门看成 −0.005 放行;`500.0→499.97` 是 −0.006% 舍入而绝对门 −0.03 误报)。 + - **本条 WARNING 的语义与 `check_extreme_returns` 不同**:本模块所有 HARD 检查都是零参数的代数不可能(重复键 / 非正 OHLC / high50% 的收盘跳变确实可能是拆股或复牌,而累计复权因子**没有任何合法的变小方式**。severity 反映的是阈值标定风险,不是对主张本身的怀疑。 +- ✅ **日频除权正确性审计**(用户点名最高优先级;调查记录 `tmp/design/FINDING_adj_factor_seam_2026-07-21.md`,全程只读 `artifacts/cache/tushare/v1`,无独立 PR):**结论 GENUINE——日频 qfq 路径本来就是对的,没有 vintage 接缝**;十一因子的 close-to-close 前瞻收益一直是除权正确的。 + - **接缝假设被证否**(双向检验:重述接缝既可能是降也可能是升):CSI500 池 996 票、979 票的 `adj_factor` 来自 >1 次 fetch、960 对相邻交易日跨 vintage 边界,其中因子**真的变化的只有 12 对**——全部为正、全部落在同一个边界(2026-05-29→06-01,A股年度除权高峰首个交易日,12/996 = 1.2% 属正常季节性),且大的都伴随 raw 价格的对应跳变(`002837.SZ` Δaf +30.24% / raw close −27.41% / 隐含 −23.22%)。**任何 fetch 边界上都不存在负向因子变化。** + - **`−57.27%` 是北交所占位符,不是分布尾部**:`920627.BJ` 一只票占全部 −2% 以下 176 行中的 171 行,因子在 `2.3404 ↔ 1.0000` 之间反复跳(175 行正好等于 `1.0000` = "无调整"占位符),其数据来自**单次 fetch**(一次 API 响应内不可能有跨 vintage 接缝),且**连一行 `market_daily` 收盘都没有**(永远进不了价格面板)。`1/(1−0.572723)−1 = +134.04%` —— 最初报的 `+134%` 上尾与 `−57.3%` 下尾是**同一只票的一正一负**。 + - **评估池内暴露:603,258 个 (symbol, date) 对里 1 对**(`000998.SZ` 2023-06-01,PIT 确认的 CSI500 成分:af −2.636% 而 raw close **+1.228%**、当日**开盘 −0.41% 没有任何机械缺口** → 判 **AMBIGUOUS**,倾向 tushare 自身发布缺陷而非缓存 artifact);**CSI300 零**。传播后:单日分位桶均值畸变 0.0208pp、摊到 1,211 个评估日 **0.0000172pp**、多空价差 ≤0.0000344pp——比任何能动 verdict 的量级低四个数量级,**不重述任何因子结果**,只作披露。 + - **污染的均值 vs 干净的均值(独立复测)**:全 CSI500 评估窗口日频 1,154,642 对中 6,906(**0.5981%**)跨因子变化,均值修正 **+2.28%**、中位 **+0.52%**、82% 为正,摊到全样本 **+1.37bp/日 ≈ +3.4%/年**(正是 A股股息率量级)。与最初被污染的测量对照:**发生率(0.604% vs 0.5981%)与中位(+0.45% vs +0.52%)一直是对的,错的只有均值(+4.38% vs +2.28%)与尾部(+134%)**——单个极端污染样本的典型签名(中位稳健、均值不稳健)。**经验:当均值与其中位差一个数量级,先去找那一行坏数据,别先给分布编故事。** + - 与 PR #75 的关系:**那是另一个 bug**——*分钟* `exec_to_exec` 路径用未复权价算持有期收益,日频路径从来不受影响。BSE `920xxx.BJ` 的 `adj_factor` 一律按不可信处理(零成本:无研究 universe 含它们,且它们没有日线价格行)。 +- ✅ **I5d / I5e / I5f 在修正引擎上重跑**(出处 `tmp/design/RESULTS_post_pr75_2026-07-21.md`;**EXPLORATORY,非业绩声明**)。⚠️ **读数前提(不许混谈)**:三个 run 的 NAV 全线上移**全部来自 bug 修复**(把除权除息还回去),**不是业绩改善**;VWAP 成交基准本身是**略微不利**的(−0.18pp)。 + - **I5f 四档归因**(SSE50 2026-03-03→06-12,3 期,`covered=58/58`,`stk_mins_live_calls=0`,每档同窗口实跑、确定性): + + | 引擎配置 | final NAV | delta | + |---|---|---| + | 已验收 I5b/I5f:`bar_close` 成交 + **未复权**收益 | `0.976448` | — | + | `bar_close` 成交 + **复权**收益 | `1.021137` | **+4.47pp** | + | `bar_vwap` 成交 + 复权收益(**新默认**) | `1.019318` | **−0.18pp** | + + 复权修正 ≈ 全部位移(该窗口正跨 A股年度除权高峰,暴露处于季节最大值);**更诚实的成交价反而差 0.18pp**(单根收盘 tick 比整分钟成交量加权价"更走运",方向符合预期)。闸门没有放松任何东西:`opened_limit_up_minutes`=**0**、`opened_limit_down_minutes`=**0**(这正是本闸门与收盘价闸门可能分歧的**全集**,本窗口为空),涨停挡买仍 1 笔、跌停挡卖 0 笔;限价覆盖 174/174;`missing_adj_factor_pairs`=**0**(修正测在全样本上)。 + - **I5f 容量按真实规模重测**:`portfolio_notional` 10,000,000 → **1,000,000 RMB**(用户明示资金上限),`max_participation_rate` 0.05 不变。43 笔 desired trade / 1 笔已被既有 feasibility 挡 / 42 笔有可用 ratio:**below 1.0x 由 20 笔变 0 笔**,ratio min/p10/median/p90 由 `0.122/0.222/1.104/2.730` 变 **`1.217/2.219/11.037/27.296`**。**此前"约半数单分钟 desired trade 容量不足"描述的是一个比本项目会跑的任何组合大一个数量级的规模**;真实规模下单分钟容量在该 universe/窗口**不构成约束**(最紧 1.22×)。这**不取消** partial-fill / volume-cap(可能的 I5g),只是重新界定其动机;仍是诊断,**非可交易性/业绩声明**,不外推到其他 universe / 名义 / 窗口。 + - **I5d(CSI500 五分位,2021-06→2026-05,59 期):原结论不成立**。Q1→Q5 终值 `0.9822/1.0423/1.0495/1.1275/1.1577` → **`1.1758/1.2310/1.2313/1.3090/1.2712`**;**单调 Spearman +1.0000 → +0.9000**、合成 Q5−Q1 累计 **+17.15% → +8.65%**(腰斩)、**Q5 不再是最优组**(Q4 1.3090 > Q5 1.2712)——I5d 的全部主张就是那条完美的 Q1→Q5 排序,它断了。分钟覆盖 892/995 → 900/995;`stk_mins_live_calls=0`;限价覆盖 52836/52836;各组 `returns dropped: no adj_factor` 均为 **0**。 + **四档归因(四件事同时变,实跑中间配置而非猜)**:① 老引擎 + **新缓存**(900 票)Spearman 仍 **+1.0000** → **样本变化被排除**;② `bar_close` 成交 + 闸门不变、**只把分红除回去**即已 Spearman **+0.9000**、价差 **+8.83%** → **复权修正是全部效应**;③ 再换 `bar_vwap` Spearman 不变、价差 −0.18pp → **VWAP 基准近乎惰性**。**即 I5d 的完美单调性实质上是"把除权下跌记成亏损"的产物**:高 MMP 的 Q5 篮子除权暴露低于 Q4,错扣分红反而抬高了 Q5 相对 Q4;把账算对,Q4 就超过它。74 个 (date,symbol) 对收在限价却盘中打开、现在获准成交(opened limit-up 22/14/10/10/18、limit-down 3/2/1/2/4),真实且已披露,但按 ②→③ 不是移动结果的原因。 + - **I5e(CSI300 独立泛化):负结果不变且更强**。Q1→Q5 `0.8809/0.7377/0.9418/0.7573/0.6665` → `1.0919/0.8777/1.1575/0.9223/`**`0.7850`**;**Spearman −0.5000 完全不变**,合成 Q5−Q1 累计 **−26.77% → −31.82%**(更负);Q5 仍是最差组(年化 −4.81%、maxDD −47.79%);覆盖 448→450/481;opened limit-up 21 对(远小于 I5d 的 74)。**这正是该问的问题:若光靠复权修正就能翻转 I5e,那个负结果就有一部分是"把分红记成亏损"的假象。它没翻——泛化失败是因子的属性,不是执行假设的产物。** + - **MMP 合并读数**:唯一的正面证据在修正引擎上**退化**,独立 universe 上的负面证据**加强** → **暂缓 MMP 的理由比过去更强,而不是不变**。 +- 🔄 **十一因子改用 14:51 VWAP 的 exec-to-exec 基准**(分支 `feat/exec-to-exec-rebasis`,**PR 尚未开**——写作时 #78 已被上面那个披露 follow-up 占用,编号待定;数字出处 `tmp/design/RESULTS_post_pr75_2026-07-21.md`):每个因子**只算一次、在两个基准上各评估一次**;既有 `{stem}_{no,with}_book` artifact 原样不动,新增的是 `{stem}_exec_{no,with}_book`。 + - **回归先行**:rebasis 分支的 `close_to_close` artifact vs 已验证的主树版本 **5,756 个叶子、0 处不同** → 本次是**加了一个基准,不是移动了一个**(两个目录由两次独立文件读取比对,不经任何共享中间产物——正是上面那次空对账的教训)。 + - **9/11 verdict 不变;变的两格都朝"更没把握"走**: + - `valley_ridge_vwap_ratio`(no_book)Watch → **INSUFFICIENT-DATA**:对齐按日单调 CI `[+0.00100,+0.07110]` → `[−0.00535,+0.06804]`。它的 Watch 本就建立在 +0.0010 这个全表最薄的下界上(**跑之前就已在参照表里标注**),CI 稍宽即跨零 → 方向 UNKNOWN → 预测轴 INSUFFICIENT_DATA。其 with_book 仍是 Watch,但**改由增量轴独扛**(正交 ICIR 下界 +0.232 > 0.15)——同一个标签靠的是不同证据,reasons 里写明。 + - `ridge_minute_return`(with_book)Reject → **INSUFFICIENT-DATA**:close 基准上增量轴 FAIL(正交 ICIR −0.141≈0,与因子簿冗余);exec 基准上点估计 −0.151 方向仍对,但对齐下界 +0.084 够不到 0.15 门 → 既不通过也不否证。**这是把握变弱,不是翻案**:INSUFFICIENT-DATA 的语义是"既没证明也没证否",且它到不了正面主张。 + - **机制只有一个**:点估计几乎全面**变强**(|ICIR| 11 个里 10 个上升;唯一例外 `peak_interval_kurtosis` 0.0058→0.0008,本就是空因子),但 **N_eff 11 个里 9 个下降**(1187.7→1116.0、1009.5→933.3、1122.9→1055.8)——exec-to-exec 的 IC 序列比 close-to-close 带更多自相关,于是每个 CI 都变宽。**更强的点估计落在更宽的区间里**,恰是 v0.9 那道门被造出来裁的情形,而它裁得保守。 + - **新基准的诚实代价**:1,734 个 (date, symbol) 对根本没有执行 bar(0.15%);VWAP 定价比收盘基准**多挡 1,541 对**(0.133%),因为那一分钟没有成交量——**这部分排除与流动性相关、非随机**(被排掉的正是最不流动的分钟),**量小不等于随机,不许当随机报**。N_eff 在 9/11 上缩水是更真实基准付出的统计功效代价。 + - **VWAP 与 bar close 在无条件分布层面几乎同一序列**:均值差 **+1.0e-07**(SE 1.3e-06,t = 0.074)、中位差 0、逐日相关中位 **0.998** → 改基准买到的是**执行锚点的真实性,不是另一个信号**,与 I5d 归因(VWAP 什么都没动、复权动了全部)一致。**close-to-close 结果保留作并排对照**,exec_to_exec 为操作基准。 +- ✅ 质量门(**当前 `main` @ `aa19968` 实测**:`python -m pytest -p no:warnings` **1740 passed**、`ruff` clean、`validate-config` **31/31 配置逐个 OK**、`run-phase0`(demo)**ic 0.9600 / annual 0.8408 不变**)。新增测试分组(`--collect-only` 实数):**因子评估契约层 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**,close-to-close 与 exec 两套 artifact 并存;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 待开**——9/11 verdict 不变、两格朝更保守走;② HTML compendium 按最终结果修订;③ 十一因子**无一到 Adopt、净多空几乎全负** → 下一步优先做**换手/成本敏感**的组合层验证与更长 holdout,而不是继续堆新因子);研究侧:更长 holdout 滚动复检 / 成本模型细化。 From b4f630031b6ba2703b6a8ea8051638e24d25a016 Mon Sep 17 00:00:00 2001 From: shaofl <2899218482@qq.com> Date: Tue, 21 Jul 2026 13:51:06 -0700 Subject: [PATCH 2/2] docs: record the single-source gate description (#78) and confirm the rebasis PR number (#79) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both follow-ups now have real numbers, read from gh pr list rather than assumed: #78 is fix/limit-basis-single-source and #79 is feat/exec-to-exec-rebasis, both OPEN. The rebasis entry no longer says "PR not yet open". - New entry for #78: #76's regex guard claimed no further copy of the wrong gate description could ship, and review disproved it by running seven plausible rewordings through the actual regex — all seven escape. The fix is structural: limit_basis_phrase() is the one authored sentence and three sites compose it; rendered text is unchanged; the regex stays with its scope corrected to catching a literal revert. - Sharpened the second defect-class rule accordingly: the rule is not "assert no (N+1)th copy exists" — that is precisely what the regex failed to do — it is author the claim once and have every other site compose it. A regex cannot assert that no other sentence makes a claim; having no other sentence can. - #79 entry gains its number, the reason for the rebasis (a minute factor is fixed at 14:50 and the only modellable fill is the 14:51 bar, so close-to-close credits a closing auction this project cannot simulate), the two coverage denominators kept apart as the PR keeps them, and the correctness acceptance. Sources: gh pr view 78, gh pr view 79, RESULTS_post_pr75_2026-07-21.md. --- CLAUDE.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d31f38e..d0f0e9d 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` 下降质量检查)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)、**#78**(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)。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` 下降质量检查)均已 merge 到 `main`**;**OPEN 未合并:#38**(见 P-I5d 处置,未获授权关闭)、**#78**(#76 的 follow-up:扫描式正则守卫被七种改写实测证否 → 闸门描述改单一来源)、**#79**(十一因子改 14:51 VWAP exec-to-exec 基准)。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -286,7 +286,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri | #73 | `peak_ridge_amount_ratio` | 成交额 | +1 | **+0.0401** | +0.488 | **2.127** | −0.001402 | Watch / Watch(IC 全场最高,零价格含量) | - **三条循环级结论**:① **家族图谱**——计数弱正 / 时序归零 / 收益 Reject / **价格比值×2 + 价格位置 + 成交额 = 四个双轴 PASS**;峰岭谷行为学划分本身有效,且 **不止价格信息有效**(PR-M 零价格含量却 IC 最高)。② **IC 强 ≠ 可交易(贯穿证据)**——11 个因子里只有 PR-F(+0.71bp)与 PR-L(+0.48bp)在 1× 费率下净多空为正,且 PR-L 扛不住 2×;毛价差常相近,差距**几乎全部来自换手**(PR-I/L 的 0.47/0.68 vs PR-J/K/M 的 2.1+)。③ **假说证伪记录(不得作为已确立规律引用)**——"秩IC/Pearson 背离比预测单调性"被 PR-M 证伪(3.86×→0.60 与 PR-J 4.22×→0.90 交叉),仅两个极端处有不确定关联。 - - **方法论(本轮建立,已作常设规则)**:① **不可能失败的测试**——三个实例:PR-L 的旗舰反泄漏测试(全截面统一扰动是带截距 OLS 残差不可见的仿射变换)、`compare_postmerge.py`(拿新结果和自己比,见下条 #74 重跑对账)、I5b fixture 给每根 bar 定价使 **VWAP ≡ close**(对"闸门读哪个"结构性失明)。**任何不变性测试都必须有实际跑过的 mutation 证据,且 mutation 要打中所主张的那个具体性质**。② **行为变了而措辞没变**——见 #76/#78:一个主张若在 N 处散文里重复,要**断言不存在第 N+1 处**,而不是枚举你知道的那几处。 + - **方法论(本轮建立,已作常设规则)**:① **不可能失败的测试**——三个实例:PR-L 的旗舰反泄漏测试(全截面统一扰动是带截距 OLS 残差不可见的仿射变换)、`compare_postmerge.py`(拿新结果和自己比,见下条 #74 重跑对账)、I5b fixture 给每根 bar 定价使 **VWAP ≡ close**(对"闸门读哪个"结构性失明)。**任何不变性测试都必须有实际跑过的 mutation 证据,且 mutation 要打中所主张的那个具体性质**。② **行为变了而措辞没变**(#76/#78 实证)——正确的修法**不是**"断言不存在第 N+1 处副本"(#76 就是这么做的,用扫描式正则,被七种改写全部绕过),而是 **把主张只写一遍、其余每一处都去组合它**:**正则断言不了"没有别的句子这么说",而"根本没有别的句子"可以**。 - ✅ **因子评估契约 v0.8 + v0.9**(**PR #74 已 merge 到 `main`**,`1ae555e`):十一个因子在 `analytics/eval/` **严格 no-touch** 下跑完后暴露的两项 frozen 缺陷,本 PR 是**对该 frozen 契约的首次授权修改**。 - **缺陷一:对齐净价差把成本加了回去(判定门缺陷,非仅展示)**。四处写成 `sign * net`(`net` 已扣成本),`sign=−1` 下展开为 **`−gross + cost`**——因子付的手续费被当利润返还。正确语义 `aligned = sign*gross − cost`(先按假设翻腿、再永远扣成本)。**其中两处在 `verdict.py`(`_base_spread` / `_all_spreads_negative`),直接喂 Tradable 轴 PASS 条件**,历来未触发仅因该轴全程 NOT_ASSESSED。手算实证:`gross 0.000125 / net 1× −0.001983 → cost 0.002108 → aligned −0.002233`(缺陷式给 **+0.001983**)。`sign=+1` 逐比特不变。年化展示值修正:jump_amount_corr **+23.14%→−0.01%**、minute_ideal_amplitude **+64.07%→−0.27%**、intraday_amp_cut **+6.30%→−20.52%**、ridge_minute_return **+64.28%→−43.25%**(**旧值全是虚高**)。 - **缺陷二:用量级敏感的池化统计量给秩基轴把门**。`monotonicity_spearman` 是"桶序号 vs 跨日等权算术均值"的相关,无界,少数极端收益日集中于某桶即可翻号,而每日封顶的秩 IC 几乎不动。新增 `monotonicity_spearman_by_date`(逐日 Spearman,先封顶 [−1,1] 再平均,与秩 IC 同构)并把门移过去;池化版保留为报告字段 + 回退披露。 @@ -304,7 +304,7 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - ✅ **报告披露修正 + I5f 名义按真实规模重测**(**PR #76 已 merge 到 `main`**,`runtime/` 行为未变):**报告曾谎报自己做的检查**——PR #75 把闸门从 bar 收盘价移到实际成交价,却漏改了两个 report writer 里**描述闸门本身**的那句,此后每次跑出的报告都在描述一个它没有执行的检查。在"绝不静默降级"是常设红线的项目里,报告写错自己的方法比不出报告更糟。 - **三个一直在算却被丢弃的计数器进报告**:`opened_limit_up_minutes` / `opened_limit_down_minutes`(本闸门与收盘价闸门的**全部分歧集合**——什么能不能成交变了,绝不许静默)、`missing_adj_factor_pairs`(因锚点 `adj_factor` 不可用而丢掉的持有期;非零即已测覆盖率短少)。尾盘报告另行声明收益是复权的并给出恒等式("exec-to-exec"一词已不足以描述它们)。 - 措辞抽成 `limit_basis_lines()` 并由三个测试钉住;**mutation evidence 实跑**:把措辞改回收盘口径 → 2 个测试 FAIL;从分组表里删掉新计数器 → 第 3 个 FAIL。**旧 I5b 测试为何没抓到**:其 fixture 给每根执行 bar `volume=1.0, amount=close` → **VWAP ≡ close**,使所有断言在两个基准上都成立,对"闸门读哪个"结构性失明;已写进 module docstring 防止重建同一盲点。 - - ⚠️ **follow-up(PR #78 OPEN,未合并)**:#76 的扫描式正则守卫被 review 用**七种自然改写实测全部逃逸**证否——正则守不住语义主张。#78 把闸门描述改成**单一来源** `limit_basis_phrase()`(三处组合它而非各写各的),正则守卫保留但把 docstring 缩到它真能做的事(抓字面 revert);**渲染输出逐字节不变**。 + - ⚠️ 本 PR 的守卫办法**随后被证明不够**——见下条 **PR #78**。 - ✅ **`adj_factor` 下降质量检查**(**PR #77 已 merge 到 `main`**,D3 层新检查,WARNING、report-only):`data/quality/market.py::check_decreasing_adj_factor` 接进 `run_adj_factor_checks`。tushare 的累计复权因子随每次公司行为**只增不减**,`front_adjust` 拿它乘 raw 价,一个发布出来的下降会直穿到每一个下游收益;而真实实例是**手工**发现的(见下条审计)。 - **阈值 1%(相对,非绝对)由全缓存扫描定**(扫全部 5562 只已缓存票的每一个负步进:7898 个事件、涉及 4479 只票): @@ -319,6 +319,10 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri 低于 1% 会点名状态**判不了**的票:`603081.SH` 最坏步 −0.776%,对应 raw close −1.810%,而真实公司行为需要 +0.782%——有缺陷的**形状**,但在该量级上普通日波动淹没隐含值,价格检验没有功效,结论不可解释。高于 1% 则漏掉一个真事件(1% 触发 177、2% 只触发 176,多出的那个属已知缺陷票)。1% 同时让最小的**已确认**缺陷(`000998.SZ` −2.636%)站在门槛的 2.6× 而非 1.3×——report-only 层宁可误报(代价一行 WARNING)也不可漏报(代价是被污染的价格静默通过)。 - **相对而非绝对**(factor 跨缓存 ~1…~500):mutation 实证 `pct_change()`→`diff()` 让原六个测试**全部通过**(fixture 都落在 factor ~1–11 两种切法重合处),补两个别的尺度才有牙(`0.200→0.195` 是真 −2.5% 断裂而绝对门看成 −0.005 放行;`500.0→499.97` 是 −0.006% 舍入而绝对门 −0.03 误报)。 - **本条 WARNING 的语义与 `check_extreme_returns` 不同**:本模块所有 HARD 检查都是零参数的代数不可能(重复键 / 非正 OHLC / high50% 的收盘跳变确实可能是拆股或复牌,而累计复权因子**没有任何合法的变小方式**。severity 反映的是阈值标定风险,不是对主张本身的怀疑。 +- 🔄 **闸门描述改单一来源**(**PR #78 OPEN,未合并**,`refactor(qt)`;#76 的结构性 follow-up):#76 加了一道扫描式正则守卫,并在 commit message 里声称"再多一处错误描述就会失败而不是发出去"。**review 用实测证否了这个声称**:写了七种自然改写("its last print"、"the final tick"、"1-minute" 代替 "1min" 等)跑真正的正则,**七种全部逃逸**——这是拿词法守卫去守语义主张的普遍下场。 + - **修法是结构性的,不是再加一条正则**:`limit_basis_phrase()` 成为**唯一被撰写的那句话**,feasibility 段、分组报告、报告的 Limitations 条目三处**组合它**而非各写各的;`_load_price_limits` 的 docstring 改为指向它而不再复述。**渲染出的报告文本逐字节不变**——本 PR 只改"有多少处可以各自出错"。正则守卫**保留**,但 docstring 缩到它真能做的事:抓**字面 revert**(坏 merge / rebase 把旧句子带回来),而这正是真实发生过的那次失效。 + - **可带走的规则(已写进上面的方法论 ②)**:**正则断言不了"没有别的句子这么说",而"根本没有别的句子"可以。** mutation 证据用的正是 review 自己那批能逃逸的措辞——它们**通过**正则守卫、**失败**于结构性测试(Limitations 条目改写成"the execution minute's final tick"、分组报告改写成"the selected bar's last print",两者都被结构测试判死)。 + - gates(PR 正文):`pytest` **1741 passed**、`ruff` clean、phase0 `0.9600/0.8408` 不变、secret scan 0。 - ✅ **日频除权正确性审计**(用户点名最高优先级;调查记录 `tmp/design/FINDING_adj_factor_seam_2026-07-21.md`,全程只读 `artifacts/cache/tushare/v1`,无独立 PR):**结论 GENUINE——日频 qfq 路径本来就是对的,没有 vintage 接缝**;十一因子的 close-to-close 前瞻收益一直是除权正确的。 - **接缝假设被证否**(双向检验:重述接缝既可能是降也可能是升):CSI500 池 996 票、979 票的 `adj_factor` 来自 >1 次 fetch、960 对相邻交易日跨 vintage 边界,其中因子**真的变化的只有 12 对**——全部为正、全部落在同一个边界(2026-05-29→06-01,A股年度除权高峰首个交易日,12/996 = 1.2% 属正常季节性),且大的都伴随 raw 价格的对应跳变(`002837.SZ` Δaf +30.24% / raw close −27.41% / 隐含 −23.22%)。**任何 fetch 边界上都不存在负向因子变化。** - **`−57.27%` 是北交所占位符,不是分布尾部**:`920627.BJ` 一只票占全部 −2% 以下 176 行中的 171 行,因子在 `2.3404 ↔ 1.0000` 之间反复跳(175 行正好等于 `1.0000` = "无调整"占位符),其数据来自**单次 fetch**(一次 API 响应内不可能有跨 vintage 接缝),且**连一行 `market_daily` 收盘都没有**(永远进不了价格面板)。`1/(1−0.572723)−1 = +134.04%` —— 最初报的 `+134%` 上尾与 `−57.3%` 下尾是**同一只票的一正一负**。 @@ -340,14 +344,15 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri **四档归因(四件事同时变,实跑中间配置而非猜)**:① 老引擎 + **新缓存**(900 票)Spearman 仍 **+1.0000** → **样本变化被排除**;② `bar_close` 成交 + 闸门不变、**只把分红除回去**即已 Spearman **+0.9000**、价差 **+8.83%** → **复权修正是全部效应**;③ 再换 `bar_vwap` Spearman 不变、价差 −0.18pp → **VWAP 基准近乎惰性**。**即 I5d 的完美单调性实质上是"把除权下跌记成亏损"的产物**:高 MMP 的 Q5 篮子除权暴露低于 Q4,错扣分红反而抬高了 Q5 相对 Q4;把账算对,Q4 就超过它。74 个 (date,symbol) 对收在限价却盘中打开、现在获准成交(opened limit-up 22/14/10/10/18、limit-down 3/2/1/2/4),真实且已披露,但按 ②→③ 不是移动结果的原因。 - **I5e(CSI300 独立泛化):负结果不变且更强**。Q1→Q5 `0.8809/0.7377/0.9418/0.7573/0.6665` → `1.0919/0.8777/1.1575/0.9223/`**`0.7850`**;**Spearman −0.5000 完全不变**,合成 Q5−Q1 累计 **−26.77% → −31.82%**(更负);Q5 仍是最差组(年化 −4.81%、maxDD −47.79%);覆盖 448→450/481;opened limit-up 21 对(远小于 I5d 的 74)。**这正是该问的问题:若光靠复权修正就能翻转 I5e,那个负结果就有一部分是"把分红记成亏损"的假象。它没翻——泛化失败是因子的属性,不是执行假设的产物。** - **MMP 合并读数**:唯一的正面证据在修正引擎上**退化**,独立 universe 上的负面证据**加强** → **暂缓 MMP 的理由比过去更强,而不是不变**。 -- 🔄 **十一因子改用 14:51 VWAP 的 exec-to-exec 基准**(分支 `feat/exec-to-exec-rebasis`,**PR 尚未开**——写作时 #78 已被上面那个披露 follow-up 占用,编号待定;数字出处 `tmp/design/RESULTS_post_pr75_2026-07-21.md`):每个因子**只算一次、在两个基准上各评估一次**;既有 `{stem}_{no,with}_book` artifact 原样不动,新增的是 `{stem}_exec_{no,with}_book`。 +- 🔄 **十一因子改用 14:51 VWAP 的 exec-to-exec 基准**(**PR #79 OPEN,未合并**,分支 `feat/exec-to-exec-rebasis`;数字出处 `tmp/design/RESULTS_post_pr75_2026-07-21.md` + PR #79 正文):每个因子**只算一次、在两个基准上各评估一次**;既有 `{stem}_{no,with}_book` artifact 原样不动,新增的是 `{stem}_exec_{no,with}_book`。**why**:分钟因子在 14:50 截止时就已定死,而本框架**能建模的唯一成交**是 14:51 开始的那根 1min bar;按 `close(t+h)/close(t)` 计分等于把一个**本项目模拟不了的收盘集合竞价**算进因子功劳(`closing_call_proxy` 需要 `stk_auction_*`,数据方案不含)。 - **回归先行**:rebasis 分支的 `close_to_close` artifact vs 已验证的主树版本 **5,756 个叶子、0 处不同** → 本次是**加了一个基准,不是移动了一个**(两个目录由两次独立文件读取比对,不经任何共享中间产物——正是上面那次空对账的教训)。 - - **9/11 verdict 不变;变的两格都朝"更没把握"走**: + - **22 格(11 因子 × no_book/with_book)中 20 格不变;移动的 2 格都朝"更没把握"走**: - `valley_ridge_vwap_ratio`(no_book)Watch → **INSUFFICIENT-DATA**:对齐按日单调 CI `[+0.00100,+0.07110]` → `[−0.00535,+0.06804]`。它的 Watch 本就建立在 +0.0010 这个全表最薄的下界上(**跑之前就已在参照表里标注**),CI 稍宽即跨零 → 方向 UNKNOWN → 预测轴 INSUFFICIENT_DATA。其 with_book 仍是 Watch,但**改由增量轴独扛**(正交 ICIR 下界 +0.232 > 0.15)——同一个标签靠的是不同证据,reasons 里写明。 - `ridge_minute_return`(with_book)Reject → **INSUFFICIENT-DATA**:close 基准上增量轴 FAIL(正交 ICIR −0.141≈0,与因子簿冗余);exec 基准上点估计 −0.151 方向仍对,但对齐下界 +0.084 够不到 0.15 门 → 既不通过也不否证。**这是把握变弱,不是翻案**:INSUFFICIENT-DATA 的语义是"既没证明也没证否",且它到不了正面主张。 - **机制只有一个**:点估计几乎全面**变强**(|ICIR| 11 个里 10 个上升;唯一例外 `peak_interval_kurtosis` 0.0058→0.0008,本就是空因子),但 **N_eff 11 个里 9 个下降**(1187.7→1116.0、1009.5→933.3、1122.9→1055.8)——exec-to-exec 的 IC 序列比 close-to-close 带更多自相关,于是每个 CI 都变宽。**更强的点估计落在更宽的区间里**,恰是 v0.9 那道门被造出来裁的情形,而它裁得保守。 - - **新基准的诚实代价**:1,734 个 (date, symbol) 对根本没有执行 bar(0.15%);VWAP 定价比收盘基准**多挡 1,541 对**(0.133%),因为那一分钟没有成交量——**这部分排除与流动性相关、非随机**(被排掉的正是最不流动的分钟),**量小不等于随机,不许当随机报**。N_eff 在 9/11 上缩水是更真实基准付出的统计功效代价。 + - **新基准的诚实代价(两个分母刻意分开,因为 `1,541` 在两种口径下都会出现)**:**按锚点**(面板网格 1,158,912 个 (date, symbol) 对)——`ok` 1,156,368(99.78%)/ `no_bar` 执行窗口内无 1min bar **1,734(0.150%)**/ `bad_vwap` 有 bar 但 VWAP 未定义 810(0.070%)/ `bad_adj_factor` **0**。**按前瞻收益对**(每因子各自的评估网格)——比 close_to_close 少 3,170–3,274 对(**0.278%–0.283%**),涉及 175–180 只票,`bad_adj_factor` 十一个因子**全为 0**,`stk_mins_live_calls` 全为 0。**VWAP 定价比 bar-close 基准多挡 1,541 对(占收盘基准可测的 1,156,183 的 0.133%),因为那一分钟根本没有成交——这部分排除与流动性相关、有方向、非随机**(被排掉的正是最不流动的分钟):**这是有偏的样本限制,不是舍入损失;百分比小不等于随机,不许当随机报**(每份 exec 报告都带 `coverage_bias_bad_vwap` 原话,且 sanity 报告把这句话放在覆盖率表**之上**,使读者不会先看到百分比;有测试钉住措辞)。N_eff 在 9/11 上缩水是更真实基准**付出的统计功效代价**,是真实借方而非记账层面的假象。 - **VWAP 与 bar close 在无条件分布层面几乎同一序列**:均值差 **+1.0e-07**(SE 1.3e-06,t = 0.074)、中位差 0、逐日相关中位 **0.998** → 改基准买到的是**执行锚点的真实性,不是另一个信号**,与 I5d 归因(VWAP 什么都没动、复权动了全部)一致。**close-to-close 结果保留作并排对照**,exec_to_exec 为操作基准。 + - **正确性验收(CSI500 全规模,996 票 / 1,210 日,cache-only,十个日频/universe gap-fetch 计数器全 0)**:① 与 close_to_close 的逐日截面相关中位 **0.9890**(p10 0.9821 / p90 0.9933,Spearman 中位 0.9814),下限 0.90 → PASS(**低于下限时 builder 直接 raise 而不是继续跑**);② 量级同阶(exec mean 0.000429 / std 0.027718 vs c2c 0.000451 / 0.028050);③ **5 行从 raw 1min parquet 用普通算术手算复核**(不 import 任何执行层 helper,故不会继承其 bug),最坏绝对差 **0.0 精确**;④ 除权持有期两种口径并列(如 `000564.SZ` 2021-12-29→12-31:未复权 −0.598581 → 复权 **−0.045367**)。gates(PR 正文):`pytest` **1774 passed**(= `main` 的 1740 + 34,恰为两个新测试文件、0 个既有测试被挤掉)、`ruff` clean、phase0 `0.9600/0.8408`、31 配置、secret scan 0。 - ✅ 质量门(**当前 `main` @ `aa19968` 实测**:`python -m pytest -p no:warnings` **1740 passed**、`ruff` clean、`validate-config` **31/31 配置逐个 OK**、`run-phase0`(demo)**ic 0.9600 / annual 0.8408 不变**)。新增测试分组(`--collect-only` 实数):**因子评估契约层 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**,close-to-close 与 exec 两套 artifact 并存;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 待开**——9/11 verdict 不变、两格朝更保守走;② HTML compendium 按最终结果修订;③ 十一因子**无一到 Adopt、净多空几乎全负** → 下一步优先做**换手/成本敏感**的组合层验证与更长 holdout,而不是继续堆新因子);研究侧:更长 holdout 滚动复检 / 成本模型细化。 +- ⚠️ 剩余(已显式披露):日线 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 并存;闸门描述单一来源化的 **PR #78 亦未合并**;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 格朝更保守走;同时 **PR #78(闸门描述单一来源)待合并**;② HTML compendium 按最终结果修订;③ 十一因子**无一到 Adopt、净多空几乎全负** → 下一步优先做**换手/成本敏感**的组合层验证与更长 holdout,而不是继续堆新因子);研究侧:更长 holdout 滚动复检 / 成本模型细化。