Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)均已 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)均已 merge 到 `main`**。commit 用 conventional 格式,**无 attribution**(不加 Co-Authored-By)。
- **不过度设计**:按路线图 MVP 先打通一条端到端链路,再加层(architecture.html §11,Phase 0→3)。
- **secrets** 一律走外部 `.config.json`;repo `.gitignore` 已排除数据产物(`*.parquet`等)、缓存、`tmp/`(仅留架构文档)。
- 文件小而专(<800 行),immutable 优先。
Expand Down Expand Up @@ -185,12 +185,20 @@ data → universe → factors(特征) → alpha(合成/预测) → portfolio(+ri
- **I2(feat cache)** stk_mins 1min read-through cache:`data/cache/intraday_coverage.py`(**timestamp-interval ledger**,`raw_freq/start_time/end_time`,不复用日频 date 语义;ok/empty 算覆盖 failed 不算)+ `intraday_parquet_store.py`(**月分区** `stk_mins_1min/freq=1min/symbol_prefix/symbol/year/month.parquet`,原子幂等 upsert by `(symbol,freq,bar_end)`,只存 raw)+ `intraday_cache.py`(`TushareIntradayCache.stk_mins_1min`:交易日 gap 规划复用 `intervals.py`,≤23 日窗分页 <8000 行 cap,1min-only guard)。接入 `TushareIntradayFeed` 可选 cache path(直抓路径字节级不变)。**冷写/暖零调用/partial 只补缺口/empty 记录/failed 重试/cached==direct 规范化后逐字节等价** 全测试锁定;**日频 `TushareCache` 零改动**(独立类)。
- **I3(feat data)** 分钟→日频 PIT 聚合:`data/clean/intraday_aggregate.py::asof_daily_features`(默认 `decision_time=14:50:00`;**先 `available_time<=cutoff` 逐 bar 过滤再按日 groupby**,分钟时间戳绝不先归零进日频)。cutoff 编码列名 `intraday_ret_0930_1450`/`intraday_realized_vol_0930_1450`/`intraday_vwap_0930_1450`/`intraday_last30m_ret_1420_1450`。`resample_intraday_bars` 派生粗 bar `available_time=max(source_1min.available_time)`。泄漏测试(扰动 14:50 后 bar → 特征不变)+ 可见性排除测试锁定。
- **I4(feat runtime)** 尾盘调仓 execution 骨架:`runtime/intraday_execution.py::simulate_tail_rebalance`(`next_minute_close` 模型:14:51 或窗口内最早 bar 成交;持有期收益 `exec(T)→exec(T_next)` 非收盘;缺 bar/NaN/无窗口 bar → 可解释 blocked,**不静默用日收盘替代**;只读分钟 bar 无 EOD 泄漏)。**独立函数,未接 config/pipeline**;日频 `close_to_next_period` 不变。`tail_vwap`/`closing_call_proxy` config 层拒绝(注明 future,后者需 `stk_auction_*` 权限当前无)。
- **下一步 I5**:把 1~2 个 EXPLORATORY 分钟因子端到端接 I2→I3→I4(opt-in config,报告披露 cutoff/lag/execution_model/window),日频回归不破。
- **下一步 I5b**(I5a 架构已就位见下):把 1~2 个 EXPLORATORY 分钟因子作为真实 opt-in alpha 端到端接 I2→I3→I4→event engine(报告披露 cutoff/lag/execution_model/window),日频回归不破。
- ✅ **P4-3 因子支撑端点缓存 + 21:00 data updater**(**PR #31 已 merge 到 `main`**,daily_basic + fina_indicator + index_member_all 进既有日频 `TushareCache`;新增独立 `data-update` CLI 增量暖跑,**不跑 factor/alpha/portfolio/backtest、不写 PanelStore**,日频回测仍自走 read-through 补缺口)。本地验收:`tmp/context/intraday_pit_checkpoints/stage_p4_3_data_updater_acceptance.md` + `tmp/context/session_handoff_20260613/p4_3_codex_acceptance.md`(codex 复核 PASS)。
- **daily_basic**(dense,pe/pb/total_mv,一次缓存调用喂 market_cap+value_ratios);**index_member_all**(per-symbol SW in/out 维度,staleness 刷新)。
- **fina_indicator 字段集无关**(codex acceptance blocker 修复):cache **永远存 canonical `FINA_FIELDS` superset**(roe/netprofit_yoy/grossprofit_margin),feed 读时选子集——一个配置 warm 不会阻塞另一配置(光加 fields_hash 会在 upsert 时互相覆盖);drift 测试守 `FINA_FIELDS ⊇ financial.SUPPORTED_FIELDS`;coverage 仍按 report-period end_date + 长 trailing tail 抓晚披露,ann_date 作 raw 不当覆盖轴。
- **not_ready pending window**:今日(`not_ready_days`)空返回记 `not_ready`(非 coverage) 次跑重试,跨界 gap 拆分;`not_ready_days=0`(默认) 行为逐字不变。per-endpoint trailing tail + summary 计数。
- cached==direct 实证(market_cap/value_ratios/pit_sw/fina-as-of);`cache=None`→direct 逐字不变;缓存只存 raw(无 qfq/因子/token);日频/分钟各自 ledger/store。**日频回测数学/factor/alpha/portfolio/runtime 零改动,Phase 0/2/3 不变**。
- ✅ 质量门:`pytest` **502 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**);`ruff` clean;`validate-config`(全部 13 配置含 data_update)+ `run-phase0`(demo)均 OK(**ic 0.9600 / annual 0.8408 不变**)。
- ✅ **P-I5a 事件驱动回测架构重构 + opt-in 分钟尾盘 event model**(**PR #33 已 merge 到 `main`**,架构/框架 PR,非研究结果;含 review 两修复):把回测层重构成**共享事件驱动核心**,日频 close-to-close 与分钟尾盘成为**同一 achieved-book ledger 上的两个 event model**,零重复 fill/cash/settle。本地验收:`tmp/context/session_handoff_20260615/stage_i5a_acceptance.md`。
- **核心**(`runtime/backtest/`):`events.py`(`HoldingPeriod` 显式时间基 + 共享月度日历)/ `engine.py`(`BacktestEngine` 单循环:universe→scores→构建→可行成交 via `SimExecution`/`simulate_fills`→settle→NAV/feasibility/holdings/**event** 日志)/ `event_models.py`(`DailyCloseEventModel` 逐字节复刻日频 + `IntradayTailEventModel` 14:50 决策/14:51 成交/exec-to-exec,复用 `intraday_execution.build_execution_prices`)。`BacktestDriver` 改为 engine+DailyCloseEventModel 的**薄 wrapper**(−237/+167),`pipeline`/`oos`/`phase2` 三 runner 一行未改。
- **config**:opt-in `intraday`(enabled/decision_time/data_lag/session_open/execution_model/execution_window/require_cache_coverage/missing_execution)+ `backtest.event_order` Literal;`intraday_tail_rebalance` 必须 `intraday.enabled=true`(root validator),旧配置全 validate,非法 model/window 可读报错。
- **分钟尾盘语义**:决策只用 `available_time ≤ 14:50` 的 bar;成交取执行窗口 `[14:51,14:56:59]` 内最早 1min 收盘;持有期收益 `exec(T_next)/exec(T)−1`(**绝非 close-to-close**);**缺/NaN 执行 bar = 显式 block,绝不退回日收盘**;turnover/cost/holdings 按 achieved book;闲置现金 `cash_return`。事件时间戳全程可审计。
- **新 CLI `run-phase-i5a-intraday`** + `config/phase_i5a_intraday_tail_framework.yaml`(SSE50 SH/SZ smoke):日频面板/universe 走既有 P4 缓存;分钟 bar **只读既有 intraday 缓存**(缺即 hard blocker,绝不静默暖跑 → **零 `stk_mins` live call**);PIT-safe 分数 = I3 `intraday_ret_0930_1450` 特征(纯框架验证,非业绩声明)。
- **真实 smoke(SSE50,2026-03-03→06-12,~180s)**:`periods=3 / covered=58/58 / stk_mins_live_calls=0 / blocked_fills=0`;event 表显示 14:50 决策 / 14:51 执行 / **actual exec bar 范围** / 真实 exit 执行锚;secret scan 0。
- **review 两修复**:① `require_cache_coverage=true` 下**任一** symbol 缺即 loud fail(原仅全缺才失败 → 静默丢名引入样本覆盖偏差);② `HoldingPeriod.exit_execution_ts` 显式化,event_log + 报告显示 **planned vs ACTUAL 执行 bar 时间**(14:51 缺、14:52 成交可见),末期不再 NaT。
- **不变量守住**:daily close-to-close 行为不漂移(engine==driver 黄金测试 + phase0 `ic 0.9600/annual 0.8408` 不变);无重复 ledger;缺 bar 绝不日收盘兜底;turnover/cost 按 achieved。
- ✅ 质量门:`pytest` **521 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**);`ruff` clean;`validate-config`(全部 14 配置含 data_update + phase_i5a)+ `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 起不再互覆盖)。
- 路线图下一步:**分钟级轨道 I5**(EXPLORATORY 分钟因子端到端接 I2→I3→I4,opt-in config,报告披露 cutoff/lag/execution_model/window,日频回归不破);**P4-3 follow-up**(fina 按 ann_date 建披露日历 ledger 以去掉启发式 tail / updater 加 stk_mins 历史回填 / data-update summary 落 cache-stats artifact);研究侧:更长 holdout 滚动复检 / 中证1000 / 成本模型细化。
- 路线图下一步:**分钟级轨道 I5b**(I5a 事件框架已就位 → 把 1~2 个 EXPLORATORY 分钟因子作为真实 opt-in alpha 端到端接 decision feature→alpha→portfolio→event engine,报告披露 cutoff/lag/execution_model/window,日频回归不破;可选把执行期 feasibility 扩到 raw `stk_limit` vs 执行分钟收盘——P-I5a 已披露的 deferred 限制);**P4-3 follow-up**(fina 按 ann_date 建披露日历 ledger 以去掉启发式 tail / updater 加 stk_mins 历史回填 / data-update summary 落 cache-stats artifact);研究侧:更长 holdout 滚动复检 / 中证1000 / 成本模型细化。