diff --git a/.gitignore b/.gitignore index 50a148e..3ed152b 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ experiments/* .idea/ .vscode/ *.swp + +# ================= archify 视觉验证副产物(重新生成即可) ================= +docs/diagrams/*.visual-check.* diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..7c52925 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,150 @@ +# 开发计划(Roadmap) + +> 依据:[AGENT.md](./AGENT.md)(开发约束)、[docs/ARCHITECTURE.md](./ARCHITECTURE.md)(架构) +> 引擎:Qlib 只做计算引擎 · 数据源:Tushare 第一、Sina 备用 · 数据库:SQLite 起步、SQLAlchemy 保证 MySQL 可切换 +> 现处:**M0 已完成(工程骨架 + 可运行后端)**,下一步进入 **Phase 1 数据层** + +--- + +## 0. 总览与里程碑 + +| 里程碑 | 内容 | 验收口径 | +|---|---|---| +| M0 ✅ | 工程初始化:uv + FastAPI 骨架、分层包、SQLAlchemy/Alembic、CI 前检查(pytest/ruff) | `/api/health` 可用、测试通过、已推送远端 | +| M1 | Phase 1 数据层:Tushare 拉取 → 标准化 → SQLite/Parquet | 命令行可全量/增量同步,来源可追溯 | +| M2 | Phase 2 Qlib:Qlib Dataset 构建 + 因子 + LightGBM + 回测(Adapter 封装) | Research Specification 能驱动一次完整回测,产出标准结果 | +| M3 | Phase 3 Web:股票池 / 因子 / 选股 / 回测 / 结果可视化 | 浏览器完成「选池→算因子→回测→看图」闭环 | +| M4 | Phase 4 Experiment:研究全量可复现归档 + Job/SSE 异步化 | 任一历史实验可一键复跑 | +| M5 | Phase 5 AI Agent:自然语言 → Research Plan → 受控 Tool → Experiment | Agent 能独立完成一次「因子假设→测试→结论」并留档 | + +每阶段结束时同步更新:README / AGENT.md 相关清单 / 文档;**禁止跨阶段提前堆量**(AGENT.md §38)。 + +--- + +## 1. Phase 1 —— 数据层(M1,当前下一步) + +> 目标:让系统拥有可追溯、可增量、无未来函数风险的 A 股数据资产。 + +### 1.1 Domain / DTO(先定契约) + +- `domain/entities`:`Stock`(symbol/name/industry/listing_date…)、`TradingCalendar`、`StockDaily`(含 adjust 字段)、`AdjustFactor`、`FinancialIndicator`、`SyncLog` +- `domain/repositories`:`StockRepository / TradingCalendarRepository / StockDailyRepository / SyncLogRepository`(Protocol) +- Pydantic DTO:`StockFilter`、`SyncRequest`、`SyncLogQuery` + +### 1.2 Data Provider(接口 + 双实现) + +- `MarketDataProvider`(Protocol):`get_daily / get_stock_basic / get_trade_cal / get_financial / get_adjust_factor`,签名支持 `as_of_date` +- `TushareProvider`:封装 `tushare.pro`,token 从 `.env` 读;请求限流、错误分类(限频/无权限/网络) +- `SinaProvider`:仅补缺失/交叉校验(**备用**,业务代码不得直连新浪实现) +- **Failover + 审计**(AGENT.md §7):每次拉取写 `SyncLog`:`source / request_time / success / failure_reason / row_count / data_date`,禁止静默切换 + +### 1.3 标准化与校验 + +- 字段统一:`symbol`(如 `600519.SH`)、`trade_date`;财务字段区分 `report_date / announce_date` +- 校验器:空值率、量价非负、涨跌幅超限告警、复权因子单调性(日线复权因子不递减) +- 未来函数红线:**财务数据只允许在 `announce_date` 之后可见**(表结构与查询都体现) + +### 1.4 持久化与迁移 + +- SQLAlchemy Model:stock / trading_calendar / stock_daily / adjust_factor / financial_indicator / sync_log / data_source_status +- Alembic:每个 Model 一版迁移;`render_as_batch` 已配置兼容 SQLite +- 规模策略:日线等明细写 SQLite 同时按年导出 Parquet(`data/parquet`),后续切 DuckDB/Qlib 用 Parquet(AGENT.md §13) + +### 1.5 同步调度(第一版从 CLI 起步) + +- `scripts/` 下 CLI:`sync basic|calendar|daily|financial [--start --end --symbols]`,支持断点续传(按 `data_date` 上限续拉) +- 全部耗时操作留 Job 形态(状态机 queued/running/success/failed/cancelled),API 异步化放 M3/M4 + +### 1.6 验收测试 + +- Provider failover:Tushare 抛错 → 自动尝试 Sina → 审计记录正确 +- 未来函数:财务在 announce_date 前查询返回空 +- Repository:DAO 层 CRUD + 幂等 upsert(`(symbol, trade_date)` 唯一) +- 迁移:`alembic upgrade head` 幂等可重放 + +**里程碑 M1 完成的判定**:`python -m scripts.sync daily --start 2024-01-01` 全量跑通,`sync_log` 完整,`data/quant.db` + `data/parquet` 均有产物,测试通过。 + +--- + +## 2. Phase 2 —— Qlib 研究引擎(M2) + +> 目标:不碰 Qlib 源码,用 Research Specification 驱动完整「因子→模型→回测」。 + +### 2.1 Qlib Adapter(`quant/qlib_adapter/`) + +- `provider.py`:把 MarketDataProvider / Parquet 喂给 Qlib(QlibDataset 或 D/1d handler 数据源) +- `dataset.py`:Parquet → Qlib bin 特征集(`data/qlib`),含交易日历/股票池口径 +- `feature.py`:Alpha158 / 自定义因子注册(因子元数据见 §3.1) +- `model.py`:LightGBM 训练/预测封装(参数收敛、seed 固定、可复现) +- `backtest.py`:TopK 低频回测封装,输出标准化 BacktestResult + +### 2.2 Research Specification 驱动 + +- Pydantic Schema:universe / factors(含权重) / selection / rebalance / period / cost 参数 +- Validator:禁止未来函数字段(financial 用 `as_of`)、范围检查、成本非负 +- Strategy Builder:Spec → 具体策略对象(**不直接拼 Qlib YAML**) + +### 2.3 回测真实性(AGENT.md §24) + +手续费/印花税/滑点/涨跌停/停牌/换仓频率逐项落实;未实现项必须在结果中显式标注「未建模」,禁止默认无成本假设。 + +### 2.4 输出标准化(ARCHITECTURE §14) + +统一 `BacktestResult`:summary / equity_curve / drawdown / monthly_returns / yearly_returns / positions / trades / turnover / risk_metrics / factor_exposure,前端只依赖该结构。 + +**M2 判定**:命令行传入一份 Research Specification JSON → 产出标准 BacktestResult + 图表数据;因子 IC/分层测试可跑;Qlib 全部调用位于 qlib_adapter。 + +--- + +## 3. Phase 3 —— Web 前端(M3) + +> 目标:业务导向 UI(股票池/因子/选股/回测/结果),不暴露 Qlib 内部概念。 + +- `frontend/web`:Next.js(TS) + ECharts(按 README 与架构 §12/§13/§26 初始化) +- 页面:Dashboard → 股票池 → 因子研究 → 选股 → 回测 → 结果(Experiment 视角) +- API 对齐业务对象(AGENT.md §17):`/api/stocks /api/universes /api/factors /api/factor-tests /api/strategies /api/backtests /api/experiments /api/jobs` +- 交互:参数清晰、结果可视化;耗时任务显示 job 进度(轮询起步,SSE 视需要) +- DTO 前后端共享 Schema(OpenAPI 生成 TS 类型) + +**M3 判定**:浏览器完成「选池→配因子→回测→看图」闭环,UI 无任何 Qlib/SQL 字样。 + +--- + +## 4. Phase 4 —— Experiment 与异步化(M4) + +- `experiment` 模型落地:experiment_id / data_version / code_version / strategy_version / universe / factors / model / parameters / backtest_config / period / result(含 git commit 记录) +- Job 体系:queued→running→(success|failed|cancelled) + 阶段事件(factor_calculation/model_training/backtesting…),FastAPI BackgroundTasks 起步,不引 Redis/Celery(AGENT.md §15/§38) +- SSE:`/api/jobs/{id}/events` 推送进度 +- 复跑:任意历史 Experiment 可从存档配置重放(数据版本需存在) + +**M4 判定**:一次研究自动落 Experiment;网页可查看历史实验并一键复跑。 + +--- + +## 5. Phase 5 —— AI Research Agent(M5) + +- `agent/tools`:search_stocks / get_market_data / test_factor / create_strategy / run_backtest / get_experiment / compare_experiments(只读 + 沙箱,AGENT.md §28 禁令表) +- Agent 编排:自然语言 → Research Plan → 逐步 Tool 调用 → 产出 Experiment → 结论分析(§29 假设-实验-分析循环) +- 反过拟合纪律:IC/RankIC/ICIR/分层/换手/行业市值暴露/样本外 walk-forward;不得以单次 Sharpe 高宣布有效 +- 接入:先本地(LLM API Key 走 .env),后续可视需要提供 API + +**M5 判定**:对 Agent 说「找适合 A 股月度调仓的低频因子」→ Agent 产出因子测试报告 + Experiment,结论包含稳健性讨论。 + +--- + +## 6. 贯穿全程的硬约束(每次提交自查,AGENT.md §41) + +- [ ] 是否违反 ARCHITECTURE.md / 绕过 DAO / 把 SQLite 写死? +- [ ] 是否直接依赖 Qlib 内部实现(应只在 `quant/qlib_adapter/`)? +- [ ] 是否可能引入未来函数 / 数据泄露(as_of_date、announce_date、历史成分股)? +- [ ] 新表是否走 Model → Migration → Test? +- [ ] API 契约是否变?文档是否同步? +- [ ] 是否有测试(至少相关模块)?是否运行通过? +- [ ] 是否把 secret / 数据库 / 大文件提交进 Git? +- [ ] 是否做了不必要的大规模重构(应最小修改)? + +## 7. 最近三个可执行项(建议顺序) + +1. 定义 Phase 1 的 Domain 实体与 Repository Protocol(纯接口,无数据库依赖) +2. 实现 `TushareProvider` + `SinaProvider` + Failover 审计(先用 .env 配好的 token 实测拉 1 只股票日线) +3. 落 SQLite Model + Alembic 首版迁移 + Repository 实现 + 对应测试 diff --git a/docs/diagrams/qlib-architecture.html b/docs/diagrams/qlib-architecture.html new file mode 100644 index 0000000..c546d34 --- /dev/null +++ b/docs/diagrams/qlib-architecture.html @@ -0,0 +1,13715 @@ + + +
+ + + +Inspecting compiled semantics
+No matching nodes
+ +Choose up to two semantic kinds. One reveals its real traffic; two compare only direct authored relationships.
+ +Choose a kind to inspect its nodes and touching relationships.
+Inspecting compiled semantics
+No matching nodes
+ +Choose up to two semantic kinds. One reveals its real traffic; two compare only direct authored relationships.
+ +Choose a kind to inspect its nodes and touching relationships.
+