From 28345ada732b47a626f36a20f17f91dcb59bc621 Mon Sep 17 00:00:00 2001 From: shaofl <2899218482@qq.com> Date: Fri, 19 Jun 2026 16:59:21 +0800 Subject: [PATCH] docs: record data-layer D3 quality checks progress (PR #45 merged) - docs/data/data_layer_contracts.md: implemented status D1/D2 -> D1/D2/D3; add a concise D3 paragraph (report-only data/quality/ layer that reports findings only and never filters/repairs/mutates or changes cache/feed/backtest semantics; data-update integration deferred to D3b); D4-D6 remain unimplemented. - CLAUDE.md: add PR #45 to the merged PR list; add a D3 progress bullet (package, daily market/adj_factor checks, 1min intraday checks, deterministic bounded renderer, secret-safe redaction fix, D3b deferral, no behavior change); update the quality gate 584 -> 625 passed; roadmap D3+ -> D3b/D4. - AGENTS.md: kept byte-identical to CLAUDE.md. Docs-only; no code behavior change. --- AGENTS.md | 10 +++++++--- CLAUDE.md | 10 +++++++--- docs/data/data_layer_contracts.md | 15 ++++++++++----- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 618e32d..ebd6313 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 拆分)均已 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 数据质量层)均已 merge 到 `main`**。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。 - **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。 - **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。 - 文件小而专(<800 行),immutable 优先。 @@ -220,6 +220,10 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri - ✅ **数据层 D2 — TushareCache endpoint specs/parsers 拆分**(**PR #43 已 merge 到 `main`**,行为保持型内部重构,**公开缓存语义零变更**,非性能/并发/data-quality 层):把 814 行的 `data/cache/tushare_cache.py` 内部拆成小文件,让 endpoint 元数据与 raw 解析器可单独审阅,`TushareCache` 仍是公开门面。 - **拆分**(解析器逐字搬移,行为靠既有 cache 测试锁定):`tushare_specs.py`(89 行,endpoint ids/`ALL_ENDPOINTS`/`_GLOBAL_KEY`/列集+自然键/`FINA_FIELDS`/`_INDEX_WINDOW_DAYS`/rename maps,纯常量)、`tushare_parsers.py`(216 行,10 个 `_parse_*`)、`tushare_planning.py`(22 行,叶子 helper `_fields_hash`/`_compact`);`tushare_cache.py` **814→596 行**,保留 `TushareCache` 门面 + read-through 引擎(gap 规划 / index_weight 90 天分页 / snapshot staleness / `refresh_recent_days`·`recent_tail_overrides`·`not_ready_days`·`force_refresh` / ok·empty·not_ready·failed coverage / 逐自然键 upsert / `stats`·`update_summary`)+ `FetchOne`/`FetchSnapshot`。 - **向后兼容导入保持**:门面 re-export endpoint ids + `FINA_FIELDS` + `ALL_ENDPOINTS`,`from data.cache.tushare_cache import DAILY_BASIC/FINA_FIELDS/INDEX_WEIGHT/...`(被 `tushare_fina.py` + cache 测试用)全照常;新增 5 个窄测试锁定 re-export identity + 模块边界。**公开方法/签名/内部规划/coverage 语义全不变**;phase0 `0.9600/0.8408` 不变。**非目标(D3+)**:schema registry / data-quality / 并发 / `CoverageLedger` 存储 / `PanelStore` append·partition / intraday 缓存重构 / 限频重试,均未做。 -- ✅ 质量门:`pytest` **584 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 / D1 token-dedup index-feed +2 / D2 cache-modularization +5**);`ruff` clean;`validate-config`(全部 17 配置含 data_update + phase_i5a + phase_i5b + phase_i5c + phase_i5d)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 不变**)。 +- ✅ **数据层 D3 — report-only 数据质量层**(**PR #45 已 merge 到 `main`**,含 review 一修复;纯库 + 测试,**report-only 非 cleaning**):新增独立 `data/quality/` 包,在接入处附近**只报告**可疑上游数据,**绝不**过滤行/修复值/改 qfq/改 cache coverage/动 feed·factor·alpha·portfolio·runtime。 + - **包**(纯函数,输入 DataFrame→findings,输入永不被改):`report.py`(`QualityFinding` + `make_finding`(样本限 5、清洗)+ `findings_to_frame`(稳定确定序)+ `render_report`(确定性 Markdown,clean→"No findings")+ secret redaction);`market.py`(日频:dup(date,symbol)/非正 OHLC/high 目的:把 **`cache`(缓存)** 与 **`store`(面板存储)** 的边界写成可提交的契约, > 让后续改动有明确不变量可守。本文件只描述 **当前已实现** 的行为,不预告未实现的阶段。 -已实现:**D1**(边界文档化 + 低风险 token 解析去重)、**D2**(`TushareCache` endpoint specs/parsers 拆分,公开缓存行为不变)。**D3–D6 尚未实现**,本文件不声称其存在。 +已实现:**D1**(边界文档化 + 低风险 token 解析去重)、**D2**(`TushareCache` endpoint specs/parsers 拆分,公开缓存行为不变)、**D3**(report-only `data/quality/` 数据质量层)。**D4–D6 尚未实现**,本文件不声称其存在。 --- @@ -42,7 +42,7 @@ - 它 **不跑 factor / alpha / portfolio / backtest,不写 `PanelStore`**。 - 真实回测仍各自走 read-through,按需补自己的缺口;`data-update` 只是把常用 endpoint 提前填好。 -## 4. D1 / D2 已做什么;D3+ 范围(未实现) +## 4. D1 / D2 / D3 已做什么;D4+ 范围(未实现) **D1**(行为零改动)做两件低风险事:**把上述边界写成本契约文档**,以及 **把 `TushareFeed` / `IndexConstituentsFeed` 里重复的 token 解析收敛到共享的 `data/feed/secret.py::read_token`** @@ -54,9 +54,14 @@ endpoint 常量/specs → `data/cache/tushare_specs.py`、raw endpoint 解析器 公开门面(方法/签名/gap 规划/分页/staleness/coverage 语义全不变),并 re-export endpoint ids + `FINA_FIELDS` 保持向后兼容导入。 -以下明确 **仍未实现**(D3+,本文件 **不声称已实现**): +**D3**(report-only 数据质量层,库 + 测试)新增独立的 `data/quality/` 包,在接入处附近**只报告**可疑的上游 +日频行情 / `adj_factor` / 1min 分钟数据,**绝不**过滤行、修复值、改 qfq、改 cache coverage、或动 feed/factor/ +alpha/portfolio/runtime。纯函数:输入 DataFrame → findings(含 dataset/check 元数据 + bounded 样本),输入永不被 +改;findings/渲染报告携带 redaction guard,不含 token/secret 路径/无界 dump。可选的 `data-update` 集成**推迟到 D3b** +(本阶段仅库 + 测试,零 config/命令行为变更)。 + +以下明确 **仍未实现**(D4+,本文件 **不声称已实现**): -- 数据质量校验(data-quality validator); - 并发 / 线程池 / 异步抓取(concurrency); -- endpoint schema registry(改运行时 dispatch 语义)、`CoverageLedger` 存储格式变更、 +- endpoint schema registry(改运行时 dispatch 语义)、`CoverageLedger` 存储格式变更 / batch 写入、 `PanelStore` 的 append/partition 特性。