diff --git a/docs/DEV_PLAN_v2.md b/docs/DEV_PLAN_v2.md index 63a4922..605ae4f 100644 --- a/docs/DEV_PLAN_v2.md +++ b/docs/DEV_PLAN_v2.md @@ -1,8 +1,10 @@ -# 下阶段开发计划(架构 v2 落地 · 2026-09) +# 下阶段开发计划(架构 v2 落地 · 2026-09 · 选股系统为主线) > 依据:[ARCHITECTURE_v2.md](./ARCHITECTURE_v2.md)(新架构 v2)、[AGENT.md](../AGENT.md)(开发约束)、 > 两份 2026-09 只读调研(后端研究/量化层、前端/Agent/数据层)与 docs/ROADMAP.md 的 M0–M5 记录。 > 本文件回答:**M5(AI Agent Phase 5)之后,下一阶段做什么、按什么顺序做。** +> 2026-09 更新(用户定调):**下一阶段以「选股系统」为独立主线并提前执行** +> (原"研究层落地"后移为 M7 支撑),先交付可用的选股 MVP,再补因子层增强。 --- @@ -10,25 +12,22 @@ **已完成(M0–M5)**:数据层(Tushare 首选 + 新浪兜底 + 审计)→ ResearchSpec → 本地研究引擎 (9 个行情因子 / IC·分层评估 / 低频 TopN 等权回测)→ Job/Experiment 异步归档 → Web 六页 → -AI Agent(6 个受控 Tool)。**数据库已于 2026-09 从 SQLite 全量迁移至 MySQL**(见 §5)。 +AI Agent(6 个受控 Tool)。**数据库已于 2026-09 从 SQLite 全量迁移至 MySQL**(见 §1)。 **对照 v2 的核心差距**(调研结论): -1. **研究是一条"单行道"**:ResearchSpec → 取数 → 因子 → TopN 回测 一次性跑完; - v2 强调的 Factor Research / **Composite Factor / Selection / Signal / Portfolio 分层**尚未拆分, - "选股"只是回测器内部逻辑,无法单独回答 v2 §8 的两个问题: +1. **选股没有独立成系统**:v2 强调 Factor Research / Composite Factor / **Selection** / Signal / + Portfolio 分层;当前"选股"只是回测器内部 TopN 逻辑,无法单独回答 v2 §8 的两个核心问题: 「2023-08-15 为什么选这只股票」「2026-09-08 当前有哪些股票满足策略」。 -2. **因子定义 / 策略等研究元数据未入库**:DB 只有 8 张表 - (stock / stock_daily / adjust_factor / financial_indicator / trading_calendar / sync_log / job / experiment), - v2 §8 期望的 factor_definition / factor_test / factor_composite / universe / selection_rule / - signal_rule / strategy / portfolio 等全缺;factor_test 与回测结果只以 Experiment 的 result_json 快照存在。 +2. **因子定义 / 策略等研究元数据未入库**:DB 只有 8 张表(stock / stock_daily / adjust_factor / + financial_indicator / trading_calendar / sync_log / job / experiment);v2 §8 期望的 + factor_definition / universe / selection_rule / selection_result / signal_rule / strategy 等全缺。 3. **口径与数据完整性风险待修**:研究链路不消费复权因子(stock_daily 混合 tushare 不复权与新浪前复权行); universe 用"当前名称含 ST"近似、无历史成分/停牌;Job.stage 从未赋值、SSE 是查库轮询。 -4. **前端/Agent 待做实**:Selection/Signal 页面不存在;因子组合页无持久化实体;回测结果字段大量未渲染; - Agent 工具仅 6 个,v2 §24 期望的 screen_stocks / explain_selection / generate_signals / - create_strategy / create_composite_factor 等依赖尚未存在的引擎。 +4. **前端/Agent 待做实**:Selection/Signal 页面不存在;Agent 工具仅 6 个, + v2 §24 期望的 screen_stocks / explain_selection 等依赖尚未存在的选股引擎。 -**阶段命名延续 ROADMAP**:M6 研究层落地 → M7 引擎分层 → M8 平台化与 Agent 增强。 +**阶段命名**:**M6 选股系统(主线)→ M7 因子层落地(支撑)→ M8 引擎延伸与平台化**。 数据库专项单独记 M-DB。 --- @@ -40,13 +39,14 @@ AI Agent(6 个受控 Tool)。**数据库已于 2026-09 从 SQLite 全量迁 - MySQL(192.168.1.10:3306,MariaDB 10.11,库 `qlib`,utf8mb4)建 8 张业务表 + alembic_version, 全部经 `alembic upgrade head`(迁移 e4d18825…53113c80…91c4e27a…d3f6c9a2),结构由既有 ORM 模型保证。 - `scripts/migrate_sqlite_to_mysql.py`:一次性工具 —— sqlite 直连 + pymysql chunk 多值 INSERT + - keyset 分页续传 + 幂等(已迁则跳过)+ `--verify-only` 逐表 COUNT 与抽样比对;支持 `--only <表>` 并行大表。 + keyset 分页续传 + 幂等(已迁则跳过)+ `--verify-only` 逐表 COUNT 与抽样比对;支持 `--only <表>` 并行大表、 + `--throttle-sec` 低配服务器节流。 - 配置:`config.yaml → database.mysql`(host/port/db/user/charset 明文),密码经 `.env` 的 `MYSQL_PASSWORD`(AGENT.md §33:密钥不进 config/git);URL 优先级 `DATABASE_URL 环境变量 > config.yaml database.mysql > sqlite:///./data/quant.db 兜底`; 实现集中在 `backend/app/core/config.py::_build_mysql_url`,业务层零改动(DAO/Repository 隔离兑现)。 - 测试隔离:`backend/tests/conftest.py` 强制每进程 `/tmp/qlib-pytest-.db` SQLite(测试绝不触 MySQL)。 -- 驱动:`pymysql>=1.1` 已入 `backend/pyproject.toml`。 +- 驱动:`pymysql>=1.1` 已入 `backend/pyproject.toml`。迁移数据量 16,057,265 行,`--verify-only` 校验全部一致。 **遗留收尾(小任务,可随时做)**: @@ -63,129 +63,132 @@ AI Agent(6 个受控 Tool)。**数据库已于 2026-09 从 SQLite 全量迁 ## 2. 下阶段总路线 ```text -M6 研究层落地 因子元数据入库 + 复合因子模块 + 口径修复 +M6 选股系统(主线) Universe 选股范围 + Selection Engine(A条件/B评分) + │ + 结果落库/API + 回测共用引擎 + Web 选股页 ↓ -M7 引擎分层 Selection Engine → Signal Engine → Portfolio Engine +M7 因子层落地 因子定义入库 + Composite 模块化 + 研究口径修复(支撑选股增强) ↓ -M8 平台化 Strategy 模型 + /api/strategies + Agent 增强 + 页面做实 +M8 引擎延伸与平台化 Signal Engine → Portfolio Engine → Strategy / Agent / Qlib 模型选股 ``` -设计红线(贯穿):v2 §25「历史回测与当前选股用同一套 Engine」、§26 Experiment 可复现、 -AGENT.md「简单优先 / 每阶段可运行 / 一个功能一个 commit / 先 Domain 后 UI / 带测试」。 +设计红线(贯穿):v2 §25「历史回测与当前选股用同一套 Engine」、v2 §9 时间与未来函数防护、 +v2 §26 Experiment 可复现、AGENT.md「简单优先 / 每阶段可运行 / 一个功能一个 commit / +先 Domain 后 UI / 带测试」。 --- -## 3. M6:研究层落地(因子目录、复合因子、口径) +## 3. M6:选股系统(下一阶段主线) -> 目标:把"因子"从代码注册表变成**可入库、可版本化、可组合**的研究资产,并修掉混合口径风险。 -> 本阶段只做研究和评估能力,不引入选股/信号新概念 —— 避免一次改动跨太多层。 +> 目标:交付一个**独立、可解释、支持当前与历史日期**的选股系统(v2 §14 Selection Engine), +> 让回测器与"现在该选什么"共用同一套引擎(v2 §25 一致性红线)。 +> MVP 全部复用**现有数据与因子能力**(stock / financial_indicator / stock_daily + 9 个内置行情因子 + +> composite_score),不依赖 M7 因子层,因此可最先做、尽快见到"选股结果"。 -### 3.1 因子定义入库 + 版本化目录 +### 3.0 选股输入输出契约(先定 Domain / DTO) -- Domain:`FactorDefinition`(name/description/formula/input_data/frequency/lookback/direction/ - normalization/neutralization/availability_rule/version/requires…);`FactorDefinitionRepository`(Protocol)。 -- Infra:Model `factor_definition` → Alembic → Repo;注册表 seeding:把 `quant/factors.py` 现有 9 个 - 内置因子的元数据灌库(一次性 seed 脚本或 `sync factors` CLI 子命令),代码仅保留计算函数映射 - (name → compute)。 -- API:`GET /api/factors` 改读库;`POST/PUT /api/factors`(管理员自定义因子元数据,计算待 M6.3 表达式引擎)。 -- 验收:迁移测试通过;`/api/factors` 展示入库元数据;未知因子抛 `FactorError`; - 现有因子研究 Job 结果与改动前一致(回归)。 +- Domain `SelectionSpec`(v2 §14.2):`universe 范围 + filters(条件) + scoring(因子/复合因子/权重) + + ranking(TopN / Top%) + as_of_date`;沿用并扩展现有 `ResearchSpec` 的 universe/factors/selection 结构, + 新增 `as_of_date`(缺省 = 最近交易日)。 +- Domain `SelectionResult`(v2 §14.3/§21.1):`as_of_date, universe, candidates[{symbol, rank, score, + factor_values, filter_status, selection_reason}], statistics` —— 作为前后端/Agent 统一 DTO。 +- 核心用例:`selection_service.select(spec, as_of=...) -> SelectionResult`(历史/当前日期都可执行)。 +- 验收:SelectionResult 进入 `frontend/web/lib/types.ts` 与后端 entity 一一对应。 -### 3.2 Composite Factor Engine 模块化 +### 3.1 Universe:选股范围(MVP 规则化) -- 现状:`composite_score` 内联在 local_engine(截面 zscore × 方向 × 权重 求和)。 -- 目标:抽出独立模块 `quant/composite.py`:`CompositeSpec{components[{name,weight,direction}], method}` - → 输出 score 面板(先固定权重 + zscore;Rank/Z/IC 加权留接口,不提前实现)。 -- Model 表 `factor_composite(+factor_composite_component)` 落库(供保存/复用)。 -- 回测/因子测试改调同一 `composite_score` 函数。 -- 验收:与现有默认 spec 的回测结果**逐项一致**的回归测试;API `GET/POST /api/composites` CRUD。 +- 把 `ResearchService.filter_stocks` 的过滤逻辑(market / exclude_st / min_listing_days / + delist_date < as_of / 可选 symbol 白名单)抽成可复用的 `UniverseFilter` 执行器, + 输入结构化条件(Pydantic),输出 as_of 时点下的股票范围。 +- MVP 不建 universe 大表:条件随 `SelectionSpec` 一起存入 `selection_snapshot`(快照 JSON, + 可复现);`universe / universe_rule / index_constituent_history` 表推迟到 M8 需要历史成分时再落。 +- 明确近似并写进结果:ST 按当前名称快照判定;停牌/退市边界显式标注(unimplemented 或近似说明)。 +- 验收:同一组条件在"当前日"与"历史日"分别得到正确范围(含历史日上市/退市过滤); + 现有回测 universe 语义不变(回归)。 -### 3.3 研究读取口径修复(横切前置,建议最先做) +### 3.2 Selection Engine:A 条件选股 + B 因子评分 -- 决策:研究行情统一为**不复权 close 为主口径**,凡需除权处理处显式声明; - 或在 Repository 读路径按 `source/adjust` 过滤/提供 qfq 查询(利用 adjust_factor 前复权)。 -- ResearchSpec 增加 `price_adjustment` 字段并在 API/结果 config_snapshot 显式记录口径。 -- 验收:同一只含新浪补缺行的股票,回测口径一致且 config_snapshot 可溯源; - 文档声明口径;对现有结果差异给出解释(如有)。 +- **A. 条件选股**:结构化条件过滤(示例:`roe > 15 且 pe… 且 close > ma60`), + 条件作用于现有字段/派生指标: + - 静态/财务:`market / industry / eps / roe / total_revenue / net_profit / gross_margin…` + (财务值按 `announce_date ≤ as_of` 可见,防未来函数); + - 行情/技术:`close > ma20 / ma60、momentum_20>0、volume_ratio…`(复用 factors.py 的 `compute_factor`)。 + - MVP 条件用**结构化 JSON**(字段 + 比较符 + 值,可 and/or 嵌套),不做自由表达式 parser(避免提前造轮子)。 +- **B. 因子评分选股**:`score = composite_score(截面 zscore × 方向 × 权重)`(抽取 local_engine 现逻辑), + 按 score 排序取 `top_n` / `top_pct`;同时支持阈值过滤。 +- **C. 模型预测选股**(Qlib/LightGBM)留 M8.3,引擎接口先留 mode 字段占位。 +- 每条候选输出 `selection_reason`(命中的条件 / 分数来源),支撑 v2「为什么选这只股票」。 +- 验收:同 spec 下 A/B 模式输出与人工核对一致;条件/评分模式均可对历史 as_of 执行。 -### 3.4 因子测试结果结构化(可选,如时间紧可并入 M8) +### 3.3 结果持久化与 API -- Model `factor_test`(结果结构化落库,替代只存 result_json);factor_test 多因子 spec 不再静默只测第一个。 +- Model(→ Alembic → Repo,全部走 Model→Migration→Test): + - `selection_result`(v2 §8:selection_id / strategy_id 占位 / as_of_date / symbol / rank / score / + factor_values / filter_status / selection_reason / created_at); + - `selection_snapshot`(spec 与 universe/条件快照 JSON,供复现与"历史某日选了什么"查询)。 + - `selection_rule`(可选的命名规则持久化,MVP 允许后置:snapshot 已含完整 spec)。 +- API(业务对象导向,AGENT.md §17):`POST /api/selections`(提交 spec+as_of,同步或 Job 计算并落库)、 + `GET /api/selections/{id}`、`GET /api/selections?as_of=&strategy_id=`(历史选股查询)。 +- 验收:提交一次选股 → 结果落库可查;重建同 spec+as_of 得到相同结果(可复现)。 + +### 3.4 回测一致性改造(v2 §25 红线) + +- `TopKBacktestRunner._rebalance` 改为**调用 Selection Engine**(同 spec、同 as_of)得到候选 + 再进入成交/仓位逻辑——保证"当前选股 = 历史回测每期选股"用同一套代码。 +- 默认配置下回测数值与改造前**逐项一致**(回归测试锁住)。 +- 验收(v2 §27):`select(strategy, 历史调仓日)` 与回测当日持仓选股逐 symbol 一致。 + +### 3.5 Web 选股页(可后端就绪后并行) + +- 新路由 `/selection`(v2 §19/§21.1):选股条件面板(范围 + A 条件 + B 评分/权重/TopN)+ + as_of 日期(当前/历史)→ SelectionResult 表格(rank/score/因子值/理由)→「一键以该 spec 发起回测」。 +- `lib/types.ts` 增加 SelectionSpec / SelectionResult;nav(app-shell)加入"股票筛选"入口。 +- 验收:页面完成"选范围 → 配条件/评分 → 当前/历史 TopN 结果 → 跳回测"闭环;tsc --noEmit 通过。 + +### 3.6 M6 验收(里程碑完成判定) + +- [ ] `select(spec, as_of=历史日)` 与回测该日调仓选股逐 symbol 一致(自动化测试) +- [ ] A/B 两模式都可对"当前日 / 历史日"执行并落库,`/api/selections` 可查 +- [ ] 选股结果带 factor_values 与 selection_reason(可解释) +- [ ] Web 选股页闭环可用;SelectionResult DTO 前后端一致 +- [ ] 全量 pytest 通过;相关迁移测试覆盖新表 --- -## 4. M7:引擎分层(Selection → Signal → Portfolio) +## 4. M7:因子层落地(支撑选股增强,紧随 M6) -> 目标:把回测器里的"选股/买卖/仓位"逻辑拆成 v2 定义的独立引擎, -> 让**当前选股与历史回测共用同一套代码**(v2 §25 一致性红线)。 +> 目标:把"因子"从代码注册表变成**可入库、可版本化、可组合**的研究资产,并修掉混合口径风险, +> 为选股 B 模式(更多/自定义因子)、因子研究做实提供基础。 -### 4.1 Selection Engine(先做) - -- Domain:`SelectionResult{as_of_date, symbol, rank, score, factor_values, filter_status, selection_reason}` - 与用例 `select(spec, as_of)`(可对任意历史/当前日期执行)。 -- 三种模式中先落地 A(条件选股:ROE/PE/涨跌幅等条件表达式)+ B(因子评分 TopN/Top%); - 模式 C(模型预测)留待 Qlib 模型链路(M8.3)。 -- `TopKBacktestRunner._rebalance` 改为**消费 Selection 结果**(同一引擎)。 -- Model:`selection_result / selection_snapshot`(as_of、spec 快照、结果)。API:`POST /api/selections` - (提交即算)与 `GET /api/selections/{id}`。 -- 验收(v2 §27):`select(as_of=历史日)` 与该日回测调仓选股**逐 symbol 一致**的测试; - API 可查"任意日 TopN 与理由";SelectionResult 成为前后端标准化 DTO。 - -### 4.2 Signal Engine(规则型) - -- Domain:`SignalRule / SignalEvent{signal_date, symbol, signal_type(BUY/SELL/HOLD/WATCH), - trigger_reason, score, price}`;规则引擎执行"分数阈值 + 技术条件 + 市场状态"组合。 -- Model:`signal_rule / signal_event`;回测与选股都能产事件并落库。 -- API:`POST /api/signals`、`GET /api/signals/history`。 -- 验收:能回答「某策略 2023-08-15 为什么对这只股票给 BUY/SELL」;与回测 signal_history 同引擎(一致性测试)。 - -### 4.3 Portfolio Engine - -- 把回测器 `_rebalance` 的资金/仓位逻辑抽为 portfolio 模块:weighting(等权起步)、 - 单股/行业上限、现金管理;约束默认关闭并在结果 unimplemented 如实标注。 -- Model:`portfolio / portfolio_position`(可选,先服务回测即可,不提前建表)。 -- 验收:默认配置下回测数值与现实现一致;新约束开关正确进入 config_snapshot/unimplemented。 - -### 4.4 Universe 规则化(横切,可与 4.1 并行) - -- Model `universe / universe_rule` + 规则执行器(把 filter_stocks 的 exclude_st/min_listing_days/ - market 规则化入库并补 exclude_suspended 的显式处理或 unimplemented); - 预留 `index_constituent_history`(历史成分,防幸存者偏差)。 -- 验收:universe 可持久化、被 Spec 引用后结果与现有一致;文档声明 ST 快照近似。 +- **4.1 因子定义入库 + 版本化目录**:Model `factor_definition` + seed 现有 9 因子元数据; + `GET /api/factors` 改读库;自定义因子元数据 CRUD(计算仍走代码注册表)。 +- **4.2 Composite Factor Engine 模块化**:抽出 `quant/composite.py` + (`CompositeSpec{components[name,weight,direction], method}` → score 面板); + `factor_composite(+component)` 表;选股 B 模式与回测共用同一实现。验收:默认 spec 回测结果与现一致。 +- **4.3 研究读取口径修复(横切)**:Repository 读路径按 `source/adjust` 过滤或提供 qfq 查询; + ResearchSpec/SelectionSpec 增加 `price_adjustment` 字段并写入结果 config_snapshot。 + 验收:含新浪补缺行的股票回测/选股口径一致且可溯源。 +- **4.4 因子测试结果结构化(可选)**:Model `factor_test`,多因子 spec 不再静默只测第一个。 --- -## 5. M8:平台化与增强(Strategy / Agent / Web / 基础设施) +## 5. M8:引擎延伸与平台化(Signal / Portfolio / Strategy / Agent / 模型选股) -### 5.1 Strategy 模型与 /api/strategies - -- Domain:Strategy 聚合 universe + factors/composite + selection + signal + portfolio + rebalance; - ResearchSpec 可由 strategy 展开。Model `strategy(+子表或 JSON 明细)`;API CRUD。 -- Experiment 归档时记录 strategy_version;Agent 增加 `create_strategy` Tool(受控白名单)。 -- 验收:Agent「建立策略 X」→ 策略入库 → 回测 → Experiment 带 strategy_version 可复跑一致。 - -### 5.2 Web 页面做实(前端主线,与 M6–M8 后端里程碑并行推进) - -- 优先:**回测页做实**(零新后端 API):渲染 trades 明细/分年度收益/持仓演化/成本参数表单/config_snapshot, - `lib/types.ts` 补全 Trade entry/exit_price、FactorTestReport.factor_name 等缺失字段, - Experiment 类型收编进 lib/types.ts(result 改联合类型)。 -- **因子研究做实**:IC 时序折线、因子横向对比(数据来自既有 DTO 扩展)。 -- **Selection 页(新路由)**:M7.1 后端就绪后,选当前/历史日 → SelectionResult 表 + 一键跳回测。 -- **Signal 页(新路由)**:M7.2 后端就绪后,信号时间线与理由、风险标志。 -- Job 进度 UI 切换 SSE(需先给执行器补 stage 上报,见 §6)。 -- 每页验收:tsc --noEmit 通过、无未渲染的标准字段、无 SQLite 字样残留。 - -### 5.3 Qlib 模型链路(模型选股 Selection 模式 C 的前置,按需) - -- `qlib_adapter/feature.py` Alpha158 特征 + `model.py` LightGBM walk-forward(seed 固定); - 输出预测分 → Selection 模式 C。作为可选增强,不阻塞 M6–M8 主干。 - -### 5.4 AI Agent 工具补齐(依赖 M6/M7/M8.1 引擎) - -- 在引擎就绪后逐个补齐 v2 §24 工具:`inspect_factor / create_composite_factor / screen_stocks / - explain_selection / generate_signals / create_strategy / get_backtest_result / create_experiment`; - 每个工具经白名单 + Job/Experiment 链路(不直接写库)。 -- 前端加一个最小 AI 对话入口(后端 /api/agent/chat 已有)—— 可与 M8.2 任意页面里程碑合并。 +- **5.1 Signal Engine(规则型)**:`signal_rule / signal_event{signal_date, symbol, signal_type, + trigger_reason, score, price}`;回测与选股都能产事件并落库;API `POST /api/signals`、历史查询。 + 验收:能回答「某策略某日为什么对这只股票给 BUY/SELL」。 +- **5.2 Portfolio Engine**:把回测器 `_rebalance` 资金/仓位逻辑抽为 portfolio 模块 + (等权起步 + 单股/行业上限/现金可选约束,约束默认关闭并如实标注 unimplemented)。 + 验收:默认配置回测数值与现一致。 +- **5.3 Strategy 模型与 /api/strategies**:聚合 universe + selection(spec) + signal + portfolio + + rebalance;Experiment 归档 strategy_version;Agent 增加 `create_strategy`。 +- **5.4 Qlib 模型链路 = 选股模式 C**(按需):Alpha158 特征 + LightGBM walk-forward → + 预测分 → Selection 模式 C。 +- **5.5 AI Agent 工具补齐**(依赖上述引擎):`inspect_factor / create_composite_factor / + screen_stocks / explain_selection / generate_signals / create_strategy / get_backtest_result / + create_experiment`,全部经白名单 + Job/Experiment 链路;前端加最小 AI 对话入口。 +- **5.6 Web 页面做实**(前端主线,随后端里程碑推进):回测页做实(trades/年度收益/持仓演化/成本参数/ + config_snapshot,零新 API)、因子研究做实(IC 时序/对比)、Signal 页、Job SSE 进度 UI + (需先补 executor stage 上报,见 §6)。 --- @@ -198,9 +201,9 @@ v2 §22 与 AGENT.md §19/§38 的原则是"第一版不引复杂队列;复杂 | 触发场景 | Redis 用途 | 何时启用 | |---|---|---| -| Job 并发/排队:subprocess 双并发上限开始频繁打满、丢任务需可恢复队列 | RQ/普通队列替代 FastAPI BackgroundTasks 调度 | M8 之后 / 出现排队丢失问题 | -| Job 细粒度 stage + SSE 长连:executor 每阶段写 stage 后广播 | Redis pub/sub 做 SSE 事件总线(替代 0.4s 查库轮询) | M8.2 前端切 SSE 时(可先行) | -| 行情/因子查询热点:全市场研究重复预热 | 因子结果 / 最新交易日缓存(key 带 as_of 失效) | 研究链路稳定后按 profile 决定 | +| Job 并发/排队:subprocess 双并发上限打满、丢任务需可恢复队列 | RQ/普通队列替代 FastAPI BackgroundTasks 调度 | M8 之后 / 出现排队丢失问题 | +| Job 细粒度 stage + SSE 长连:executor 每阶段写 stage 后广播 | Redis pub/sub 做 SSE 事件总线(替代 0.4s 查库轮询) | M8.6 前端切 SSE 时(可先行) | +| 行情/因子查询热点:全市场选股重复预热 | 因子结果 / 最新交易日缓存(key 带 as_of 失效) | M6 选股高频查询后按 profile 决定 | 近期只需做一件准备工作:`config.yaml` 预留 `redis.url_env: "REDIS_URL"` + 可选 `redis.url: "redis://127.0.0.1:6379/0"` 配置段,代码不改;真正启用时再落基础设施代码。 @@ -212,19 +215,21 @@ v2 §22 与 AGENT.md §19/§38 的原则是"第一版不引复杂队列;复杂 ## 7. 建议的执行顺序(前 6 个 commit 序列) -按 AGENT.md「最小修改、每阶段可跑、一功能一 commit」,给 M6 起步的推荐顺序: +按 AGENT.md「最小修改、每阶段可跑、一功能一 commit」,以选股 MVP 为起点的推荐顺序: -1. **M6.3 口径修复**(横切前置,改动小收益大):Repository 读路径按 source/adjust 过滤 + - ResearchSpec 口径字段 + 文档。验收:混合行场景回测口径一致。 -2. **M6.1 因子定义入库**:Model+迁移+seed+`GET /api/factors` 读库。验收:迁移测试 + 回归。 -3. **M6.2 Composite Engine 模块化**:`quant/composite.py` + 回测改调 + `factor_composite` 表 CRUD。 - 验收:默认 spec 回测结果逐项一致的回归测试。 -4. **M7.4 Universe 规则化**:`universe/universe_rule` 表 + 执行器(结果与现有一致)。可与 2/3 并行。 -5. **M7.1 Selection Engine**:`select(spec, as_of)` + TopK 回测改消费 Selection + - `selection_result/snapshot` 表 + API。验收:v2 §27 历史日一致测试。 -6. **M7.2 Signal Engine**:规则 + `signal_event` 落库 + API(回测/选股同引擎)。 +1. **M6.0 选股契约**:Domain `SelectionSpec / SelectionResult` + `selection_service.select(spec, as_of)` + 骨架(先同步执行、复用 ResearchService 数据装配)。验收:对最近交易日返回 TopN 候选 + 理由。 +2. **M6.1 Universe 过滤执行器**:抽 `UniverseFilter`(复用 filter_stocks 语义)。 + 验收:当前/历史日范围正确、回测回归不变。 +3. **M6.2 Selection Engine A + B**:条件选股(结构化条件 JSON)+ 因子评分 TopN(复用因子与 + composite_score)。验收:A/B 模式可执行、结果含 factor_values/reason。 +4. **M6.3 落库与 API**:`selection_result / selection_snapshot` 表 + Repo + `POST/GET /api/selections`。 + 验收:迁移测试 + 提交可查、重建一致。 +5. **M6.4 回测共用 Selection**:`TopKBacktestRunner` 改调 Selection Engine。 + 验收:默认 spec 回测结果逐项一致 + 历史日一致性测试。 +6. **M6.5 Web 选股页**:`/selection` 路由 + SelectionResult 表 + 一键跳回测。 -之后进入 M8(Strategy 模型 → Web 页面做实 → Agent 工具补齐)与 §6 基础设施专项。 +之后进入 M7(因子层落地)与 M8(Signal/Portfolio/Strategy/Agent/模型选股)与 §6 基础设施专项。 每步都遵循:Domain → Repository Protocol → Infra(Model→Migration→Repo) → Service → API → 前端 → 测试(相关模块)→ 更新文档;新增表一律 Model→Alembic→测试。 @@ -233,9 +238,11 @@ v2 §22 与 AGENT.md §19/§38 的原则是"第一版不引复杂队列;复杂 ## 8. 风险清单(开发中持续检查) -- **历史一致性**:Selection/Backtest 拆分后默认结果必须与拆分前一致(用回归测试锁住,别让重构悄悄改策略语义)。 -- **未来函数 / 幸存者偏差**:universe 的 ST/行业/成分历史口径补齐前,回测文档须明示近似; - 财务数据始终按 announce_date 可见(已有表键支持)。 +- **历史一致性**:回测改用 Selection Engine 后默认结果必须与改造前一致(回归测试锁住,别让重构悄悄改策略语义)。 +- **未来函数 / 幸存者偏差**:财务条件按 `announce_date ≤ as_of` 过滤;universe 的 ST/行业/成分历史 + 口径补齐前,结果须明示近似(ST 当前名称快照等)。 +- **数据口径**:选股/回测所用行情口径(不复权 vs 前复权)必须一致并可溯源(M7.3 收口)。 +- **范围控制**:M6 阶段不做自由表达式 parser / 不做模型选股(C 模式)/ 不建 universe 大表; + 均留到后续里程碑,避免一次性跨层堆量。 - **MySQL 行为差异**:TEXT 上限、批量 upsert 锁等待、pymysql 流式读取 —— 见 §1 遗留收尾表。 -- **不要提前堆量**:M6 阶段不引入模型选股/ML;M7 不做多因子合成优化;M8 的 Qlib 模型链路按需推进。 - **前端契约**:SelectionResult/SignalResult 先定 DTO(后端 entity)再画页面,避免前后端口径漂移。 diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 4348707..425dd97 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -3,7 +3,8 @@ > 依据:[AGENT.md](./AGENT.md)(开发约束)、[docs/ARCHITECTURE.md](./ARCHITECTURE.md)(架构) > 引擎:Qlib 只做计算引擎 · 数据源:Tushare 第一、Sina 备用 · 数据库:SQLite 起步、SQLAlchemy 保证 MySQL 可切换 > 现处:**M5 已完成(AI Agent Phase 5)**;**M6 起的下一阶段见 [docs/DEV_PLAN_v2.md](./DEV_PLAN_v2.md)** -> (架构 v2 落地:因子元数据入库 → 复合因子 → Selection/Signal/Portfolio 引擎分层 → Strategy 平台化) +> (选股系统为主线:Universe 选股范围 + Selection Engine A条件/B评分 + 结果落库/API + +> 回测共用引擎 + Web 选股页 → M7 因子层 → M8 Signal/Portfolio/Strategy/Agent) > 2026-09 增补:数据库已切 MySQL(见 M-DB 行),本文件 M0–M5 为历史记录,新计划以 DEV_PLAN_v2 为准。 ---