Skip to content

量化研究项目设计文档

  • 日期: 2026-06-11
  • 作者: someu
  • 状态: 已批准设计,待生成实现计划

1. 目标

搭建一个个人 A股日频因子/策略研究项目骨架。重点是研究迭代速度与可复现性:能快速验证因子/策略想法,做 IC/分层分析,并用 qlib 做回测;暂不接实盘。

2. 范围与非目标

范围(In scope)

  • A股(沪深)日频数据的采集、清洗、存储
  • 因子计算、因子评价(IC / RankIC / ICIR / 分层 / 相关性)
  • 基于 qlib 的模型训练(因子合成,可选)与回测
  • 配置驱动的可复现实验 + Notebook 探索
  • 报告与可视化(净值、回撤、IC 衰减、分层)

非目标(Out of scope,本期不做)

  • 实盘交易、下单执行、券商对接
  • 分钟/Tick 等更高频数据(架构预留,不实现)
  • 多市场(港股/美股/期货/crypto)——架构上 adapter 可扩展,本期只做 A股
  • 多人协作的中心化数据库(本期本地文件即可)

3. 技术选型

维度选型理由
语言Python量化研究生态成熟
数据存储本地 Parquet/CSV + pandas中小数据量,轻量免运维
数据源tushare + 已有本地数据tushare 质量好;本地数据走统一适配
回测/模型引擎qlib(微软)专为 A股 ML 因子研究设计,数据+因子+模型+回测全家桶
工作流Notebook 探索 + src/ 库 + 配置驱动 pipeline兼顾探索灵活度与可复现性

关键约束:qlib 使用自有二进制格式(.bin)和 workflow 范式(yaml + recorder),不直接读 parquet。因此需要一个 parquet → qlib .bin 的转换层;同一份 parquet 数据湖同时服务 pandas 探索与 qlib 回测。

4. 架构:分层设计(方案 B)

qlib 作为回测/模型引擎,藏在薄接口之后。src/quant/ 包按职责显式分七层,每层通过定义良好的接口通信、可独立理解与测试:

  1. data/ 采集层 — adapter 模式封装数据源(tushare/local),统一接口;交易日历、股票池(剔 ST/停牌/次新)。
  2. storage/ 存储层 — parquet 数据湖读写;parquet → qlib .bin 转换。
  3. factors/ 因子层Factor 抽象(compute(df) -> Series)、因子库、注册表、预处理(去极值/标准化/中性化)。
  4. research/ 因子评价层 — pandas 侧的 IC/分层/相关性分析。
  5. models/ 模型层(可选) — 封装 qlib 模型(LightGBM/线性)做因子合成。
  6. backtest/ 回测策略层 — 封装 qlib 引擎;选股/调仓策略;A股交易成本。
  7. reports/ 报告层 — 绩效指标与绘图。

qlib 隔离原则:qlib 仅出现在 storage/qlib_dump.pybacktest/engine.pymodels/trainer.py 三处,其余层零依赖 qlib,便于测试与将来替换引擎。

5. 目录结构

text
quant/
├── README.md
├── pyproject.toml                # 依赖 + 把 src/quant 装成可 import 的包
├── .gitignore
├── .env.example                  # tushare token(不入库)
├── Makefile                      # make data / factor / backtest 快捷入口

├── configs/                      # 配置驱动 → 可复现实验
│   ├── data.yaml                 #   数据源、股票池、时间区间
│   ├── factors/momentum_20d.yaml
│   ├── qlib_workflow/lgb_alpha158.yaml
│   └── backtest/topk_dropout.yaml

├── src/quant/                    # 核心库(pip install -e .)
│   ├── config.py                 #   配置加载/校验(pydantic)
│   ├── data/                     # ① 采集层(adapter 模式)
│   │   ├── sources/
│   │   │   ├── base.py           #     DataSource 抽象基类
│   │   │   ├── tushare_source.py
│   │   │   └── local_source.py
│   │   ├── download.py           #     拉取 → 原始 parquet(按交易日增量)
│   │   ├── calendar.py           #     交易日历
│   │   └── universe.py           #     股票池(剔 ST/停牌/次新)
│   ├── storage/                  # ② 存储层
│   │   ├── parquet_store.py      #     parquet 数据湖读写
│   │   └── qlib_dump.py          #     parquet → qlib .bin 转换
│   ├── factors/                  # ③ 因子层
│   │   ├── base.py               #     Factor 抽象 compute(df)->Series
│   │   ├── library/{momentum,value,volatility}.py
│   │   ├── registry.py           #     因子注册表,按名取用
│   │   └── preprocess.py         #     去极值/标准化/中性化
│   ├── research/                 # ④ 因子评价(pandas 侧)
│   │   ├── ic.py                 #     IC / RankIC / ICIR
│   │   ├── layering.py           #     分层回测 / 单调性
│   │   └── correlation.py        #     因子相关性 / 拥挤度
│   ├── models/                   # ⑤ 模型层(封装 qlib 模型,可选)
│   │   └── trainer.py            #     LightGBM/线性,因子合成
│   ├── backtest/                 # ⑥ 回测/策略层(封装 qlib 引擎)
│   │   ├── engine.py             #     薄封装:调 qlib workflow
│   │   ├── strategy.py           #     选股/调仓策略
│   │   └── cost.py               #     A股成本:印花税/佣金/滑点/涨跌停
│   ├── reports/                  # ⑦ 报告层
│   │   ├── metrics.py            #     年化/夏普/回撤/换手
│   │   └── plots.py              #     净值/IC衰减/分层图
│   └── utils/{logging,io}.py

├── pipelines/                    # 可复现入口(配置驱动,串各层)
│   ├── run_download.py           #   configs/data.yaml → 原始 parquet
│   ├── run_dump_qlib.py          #   parquet → qlib .bin
│   ├── run_factor.py             #   算因子 → 落盘
│   ├── run_research.py           #   因子评价(IC/分层)→ 报告
│   └── run_backtest.py           #   qlib 回测 → 报告

├── notebooks/                    # 探索(import quant 复用 src)
│   ├── 00_data_explore.ipynb
│   ├── 01_factor_idea.ipynb
│   └── 02_strategy_review.ipynb

├── data/                         # .gitignore
│   ├── raw/                      #   原始下载
│   ├── processed/                #   清洗后 parquet 数据湖
│   ├── qlib_cn_data/             #   qlib 二进制
│   └── factors/                  #   因子值落盘

├── results/{reports,figures}/    # 实验产出
├── mlruns/                       # qlib recorder(.gitignore)
└── tests/                        # 关键单测
    ├── test_factors.py
    ├── test_cost.py
    └── test_universe.py

6. 数据流(端到端)

text
tushare / 本地
   │  run_download.py   (configs/data.yaml)

data/raw  ──清洗──▶ data/processed (parquet 数据湖)
   │                      │
   │ run_dump_qlib.py     ├─(pandas) factors/library ─▶ data/factors
   ▼                      │              │
data/qlib_cn_data(.bin)   │              ▼ research/ (IC/分层) ─▶ results/reports
   │                      │
   └──────┬───────────────┘
          ▼  configs/qlib_workflow
   models/trainer (因子合成, 可选) ─▶ backtest/engine (qlib) ─▶ results + mlruns ─▶ reports/plots

7. 关键设计决策

  1. 因子双轨Factor.compute(df) -> Series 同一份实现,既供 research/ 用 pandas 算 IC/分层,也能注册成 qlib 特征进回测——避免一个因子写两遍、两边口径不一致。
  2. qlib 隔离:见第 4 节,qlib 仅限三处文件,其余层零依赖。
  3. 配置驱动可复现:每个 pipelines/run_*.py 只接受一个 config 路径,用 pydantic 校验;configs/ 入库,data/ results/ mlruns/.gitignore。实验 = 一份配置 + 一条命令。
  4. A股特殊规则集中处理:交易日历、涨跌停(涨跌停价位不可成交)、停牌/ST 过滤、复权、印花税单边、T+1 限制——集中在 data/universe.py + backtest/cost.py,不散落各处。
  5. 数据与代码分离:原始/中间/产出数据全部本地化并 .gitignore;唯有 configs/ 与代码入库,保证仓库轻量且实验可复现。

8. 错误处理与边界

  • 数据源适配DataSource 基类统一异常类型;tushare 限频 → 重试 + 退避。
  • 增量更新run_download 按交易日增量拉取,避免重复全量请求。
  • 数据校验:落盘前校验缺失值、重复行、字段类型;显式防护前视偏差(因子只用 T 日及之前信息)。
  • 配置校验:pydantic 在 pipeline 入口处对 config 做强校验,早失败。

9. 测试策略

不追求覆盖率,只锁关键正确性:

  • 成本模型 test_cost.py:涨跌停价位不可成交、印花税单边、佣金/滑点计算。
  • 因子计算 test_factors.py:用构造的小样本对拍预期值;防前视偏差。
  • 股票池 test_universe.py:ST/停牌/次新正确剔除。

10. 依赖(初步)

python>=3.10pandaspyarrownumpypyqlibtusharepydanticpyyamlmatplotlibpytestlightgbm(模型层)。具体版本在实现计划阶段锁定。

11. 后续扩展(架构已预留,非本期)

  • 接 alphaear-stock skill 作为一个额外 DataSource adapter。
  • 扩展到分钟频/多市场(新增 source adapter + 存储分区)。
  • 接入实盘信号/执行层(在 backtest/ 之外新增 live/ 层)。