Files
qlib/docs/ARCHITECTURE.md
T
Simon 8eb3b4ac2a chore: 项目初始化 — 工程文档、配置与目录骨架
- AGENT.md / docs/ARCHITECTURE.md 约束与架构文档入库(README 覆盖远端模板)
- 根级配置:.gitignore / .env.example / config.yaml(密钥只走 .env,不入库)
- 目录占位:data(parquet/qlib/raw/normalized) / experiments / docker / frontend/web / scripts
2026-09-06 16:09:07 +08:00

16 KiB
Raw Blame History

A股个人量化选股与回测平台架构

版本:v1.0
定位:个人开发、A股、中低频选股/回测、AI Agent 二次开发
数据源优先级:Tushare > 新浪财经
当前数据库:SQLite
未来数据库:MySQL
核心量化引擎:Qlib
前端:React / Next.js
后端:FastAPI + Python


1. 项目目标

本项目不是简单给 Qlib 套一个 Web UI,而是构建一个独立的个人量化研究平台:

Web 前端
   ↓
FastAPI
   ↓
Research Specification
   ↓
业务服务层
   ├── 数据服务
   ├── 股票池服务
   ├── 因子服务
   ├── 选股服务
   ├── 模型服务
   ├── 回测服务
   └── 实验服务
   ↓
Qlib / ML
   ↓
标准化研究结果
   ↓
SQLite / Parquet
   ↓
Web 前端

AI Agent 作为独立能力层,通过受控 Tool 调用上述服务,而不是直接操作数据库或随意修改 Qlib 内部代码。


2. 总体架构

                           ┌──────────────────────┐
                           │      React / Next    │
                           │                      │
                           │ Dashboard            │
                           │ 股票池               │
                           │ 因子研究              │
                           │ 选股                 │
                           │ 回测                 │
                           │ Experiment           │
                           │ AI Research          │
                           └──────────┬───────────┘
                                      │
                                REST / SSE
                                      │
                                      ▼
                           ┌──────────────────────┐
                           │       FastAPI        │
                           │                      │
                           │ API / Auth / DTO     │
                           │ Job / Validation     │
                           └──────────┬───────────┘
                                      │
                         ┌────────────┼────────────┐
                         │            │            │
                         ▼            ▼            ▼
                    Data Service  Research     Agent Service
                         │         Service           │
                         │            │              │
                         ▼            ▼              ▼
                    DAO / Repo     Qlib / ML     Agent Tools
                         │            │              │
                         └────────────┼──────────────┘
                                      ▼
                           ┌──────────────────────┐
                           │     Persistence      │
                           │                      │
                           │ SQLite               │
                           │ Parquet              │
                           │ Qlib Dataset         │
                           └──────────────────────┘

3. 核心设计原则

3.1 Qlib 不是系统数据库

Qlib 负责:

  • Feature / Dataset
  • 模型训练
  • Prediction
  • Portfolio
  • Backtest
  • 部分分析工具

Qlib 不作为业务系统唯一数据存储。

系统数据分为:

业务数据 → SQLite
历史/分析型大数据 → Parquet
Qlib计算数据 → Qlib Dataset
实验结果 → SQLite

3.2 前端不能直接调用 Qlib

必须经过:

Frontend
  ↓
FastAPI
  ↓
Application Service
  ↓
Qlib Adapter
  ↓
Qlib

这样未来可以替换 Qlib,而不影响前端。

3.3 DAO 必须与数据库实现解耦

业务代码禁止直接:

sqlite3.connect(...)

也禁止在 Service 中写 SQL。

必须:

Service
   ↓
Repository / DAO Interface
   ↓
SQLite Repository

未来:

Service
   ↓
Repository Interface
   ├── SQLite Repository
   └── MySQL Repository

业务层不感知底层数据库。


4. 数据源架构

4.1 数据源优先级

                  Data Service
                       │
              ┌────────┴────────┐
              ▼                 ▼
           Tushare           Sina
          Primary          Secondary
              │                 │
              └────────┬────────┘
                       ▼
                 Normalization
                       │
                 Validation
                       │
                    Storage

第一优先级:Tushare

用于:

  • 股票基本信息
  • 日线行情
  • 复权因子
  • 指数
  • 财务数据
  • 分红送转
  • 停复牌
  • 行业/概念
  • 其他可用数据

第二优先级:新浪财经

主要作为:

  • Tushare 数据缺失补充
  • 行情数据校验
  • 特定实时/准实时数据补充

新浪数据必须经过统一 Adapter,禁止业务代码直接调用新浪接口。


5. 数据采集流水线

Scheduler
   ↓
Data Source Adapter
   ↓
Raw Response
   ↓
Schema Validation
   ↓
Normalization
   ↓
Deduplication
   ↓
Business Validation
   ↓
DAO
   ↓
SQLite
   ↓
Parquet Export
   ↓
Qlib Dataset

每个数据源都必须有独立 Adapter:

data/
├── sources/
│   ├── base.py
│   ├── tushare.py
│   └── sina.py
├── normalizers/
├── validators/
└── service.py

业务层只依赖:

MarketDataProvider

而不是:

TushareClient

6. 数据库设计

6.1 SQLite 定位

SQLite 用于:

  • 股票基础信息
  • 数据源状态
  • 数据同步记录
  • 因子定义
  • 策略定义
  • 回测配置
  • Experiment metadata
  • Job
  • 用户配置
  • 系统配置

SQLite 不建议长期承载超大规模原始行情明细。

历史行情和大量 Feature 优先使用 Parquet。


7. DAO / Repository 设计

推荐使用:

SQLAlchemy 2.x
   +
Repository Pattern
   +
Pydantic DTO

目录:

backend/
├── domain/
│   ├── entities/
│   └── repositories/
│
├── infrastructure/
│   └── persistence/
│       ├── sqlalchemy/
│       │   ├── models/
│       │   ├── repositories/
│       │   └── session.py
│       └── migrations/
│
└── application/
    └── services/

Repository 接口示例:

class StockRepository(Protocol):
    def get_by_symbol(self, symbol: str) -> Stock | None: ...
    def list(self, filters: StockFilter) -> list[Stock]: ...
    def save(self, stock: Stock) -> Stock: ...

SQLite:

class SqlAlchemyStockRepository(StockRepository):
    ...

未来 MySQL:

class MySqlStockRepository(StockRepository):
    ...

推荐实际上让两者都基于 SQLAlchemy,而不是分别维护两套 SQL。

这样数据库切换主要通过:

DATABASE_URL

完成。

例如:

SQLite:
sqlite:///./data/quant.db

MySQL:
mysql+pymysql://user:password@host/quant

业务 Service 不需要修改。


8. 建议的核心数据库表

第一阶段至少包括:

stock
stock_daily
stock_adjust_factor

industry
stock_industry

index
index_daily

trading_calendar
suspend_data
stock_st_data

financial_indicator
income_statement
balance_sheet
cashflow_statement

factor_definition
factor_test

strategy
strategy_factor

backtest
backtest_trade
backtest_position
backtest_metric

experiment
experiment_artifact

job
data_sync_log

注意:

stock_daily 等大量时序数据如果规模变大,应逐渐迁移到:

Parquet

SQLite 保留元数据和索引。


9. 时间与未来函数防护

所有研究数据必须明确:

trade_date
report_date
announce_date
effective_date

财务数据必须按照 announce_date 控制可见性。

禁止:

使用未来公告的财务数据回测过去

所有数据查询必须明确:

as_of_date

例如:

get_financial_data(
    symbol="600519.SH",
    as_of_date="2024-06-30"
)

只允许返回当时市场已经知道的数据。


10. Domain 层

建议核心领域对象:

Stock
Universe
Factor
FactorTest
Model
Strategy
Portfolio
Backtest
Experiment
Job

例如:

Universe
    ↓
Factor
    ↓
Model
    ↓
Strategy
    ↓
Backtest
    ↓
Experiment

11. Research Specification

前端、AI Agent 和后端统一使用自己的研究描述对象。

示例:

{
  "type": "backtest",
  "universe": {
    "market": "CN_A",
    "exclude_st": true,
    "exclude_suspended": true,
    "min_listing_days": 250
  },
  "factors": [
    {
      "name": "momentum_60",
      "weight": 0.3
    },
    {
      "name": "roe_ttm",
      "weight": 0.3
    },
    {
      "name": "low_volatility_60",
      "weight": 0.4
    }
  ],
  "selection": {
    "top_n": 30
  },
  "rebalance": "monthly",
  "period": {
    "start": "2015-01-01",
    "end": "2026-08-31"
  }
}

然后:

Research Specification
        ↓
Validator
        ↓
Strategy Builder
        ↓
Qlib Adapter

12. 前端结构

第一阶段:

Dashboard
股票池
因子研究
选股
回测
Experiment

第二阶段:

模型研究
Portfolio
AI Research
数据管理

13. 前端输入

股票池

支持:

  • 市场
  • 股票类型
  • 行业
  • 市值
  • 流动性
  • 上市时间
  • ST
  • 停牌
  • 指数成分

因子

支持:

  • 内置因子
  • 自定义表达式
  • 因子组合
  • 权重
  • 标准化
  • 中性化

选股

支持:

  • Top N
  • Top %
  • Score
  • 等权
  • Score 加权
  • 行业约束
  • 单股权重上限

回测

支持:

  • 起止日期
  • 调仓频率
  • 初始资金
  • 手续费
  • 印花税
  • 滑点
  • 涨跌停限制
  • 停牌限制

14. 前端输出

回测结果统一转换为:

BacktestResult
├── summary
├── equity_curve
├── drawdown
├── monthly_returns
├── yearly_returns
├── positions
├── trades
├── turnover
├── risk_metrics
└── factor_exposure

这样前端完全不需要理解 Qlib 内部对象。


15. 异步 Job

所有耗时任务必须异步:

POST /api/backtests
       ↓
Job Created
       ↓
Worker
       ↓
Qlib
       ↓
Result

前端通过:

SSE

接收:

queued
running
factor_calculation
model_training
backtesting
analysis
completed
failed

第一阶段可以使用:

FastAPI BackgroundTasks

或简单本地 Worker。

系统复杂后再引入:

Redis + Celery/RQ

不要第一版过度工程化。


16. Qlib Adapter

Qlib 必须被封装:

quant/
├── qlib_adapter/
│   ├── dataset.py
│   ├── feature.py
│   ├── model.py
│   ├── backtest.py
│   └── provider.py

业务代码:

backtest_service.run(spec)

而不是:

qlib.init(...)
qlib.workflow(...)

散落在项目各处。


17. AI Agent 架构

Agent 只能调用 Tool:

Agent
 ├── search_stocks
 ├── inspect_factor
 ├── test_factor
 ├── create_strategy
 ├── run_backtest
 ├── compare_experiments
 ├── get_backtest_result
 └── create_experiment

Agent 禁止:

直接 SQL
直接修改数据库
直接删除数据
直接执行任意 shell
直接修改生产策略

Agent:

自然语言
 ↓
Research Plan
 ↓
Tool Calls
 ↓
Research Specification
 ↓
执行
 ↓
Experiment
 ↓
分析

18. AI Research 示例

用户:

帮我寻找适合A股月度调仓的低频选股因子。

Agent:

1. 获取A股股票池
2. 创建候选因子
3. IC测试
4. RankIC测试
5. 分层测试
6. 相关性分析
7. 删除冗余因子
8. 组合因子
9. Walk Forward
10. 回测
11. 保存 Experiment
12. 输出结论

Agent 不能因为一次回测表现好就直接认为策略有效。

必须关注:

样本外
Walk Forward
不同市场阶段
交易成本
换手率
因子稳定性

19. 推荐的开发目录

quant-platform/
│
├── frontend/
│   └── web/
│
├── backend/
│   ├── app/
│   │   ├── api/
│   │   ├── application/
│   │   ├── domain/
│   │   ├── infrastructure/
│   │   ├── quant/
│   │   ├── agent/
│   │   └── core/
│   │
│   └── tests/
│
├── data/
│   ├── raw/
│   ├── normalized/
│   ├── parquet/
│   └── qlib/
│
├── experiments/
│
├── scripts/
│
├── docker/
│
├── docs/
│
├── ARCHITECTURE.md
├── AGENT.md
└── README.md

20. 第一阶段 MVP

不要一开始做所有功能。

Phase 1:数据

Tushare
 ↓
标准化
 ↓
SQLite
 ↓
Parquet

完成:

  • 股票列表
  • 交易日历
  • 日线
  • 复权因子
  • 基本财务指标

Phase 2:Qlib

Parquet
 ↓
Qlib Dataset
 ↓
Alpha158 / 自定义因子
 ↓
LightGBM
 ↓
Backtest

Phase 3:Web

完成:

股票池
因子
选股
回测
结果

Phase 4:Experiment

所有研究自动保存。

Phase 5:AI Agent

最后再接:

自然语言
 ↓
Research Plan
 ↓
Tool
 ↓
Experiment

21. 数据流总图

             Tushare
                │
                ▼
          Tushare Adapter
                │
                │ 失败/缺失
                ▼
             Sina Adapter
                │
                ▼
             Raw Data
                │
                ▼
          Data Validator
                │
                ▼
          Normalization
                │
          ┌─────┴──────┐
          ▼            ▼
       SQLite        Parquet
          │            │
          │            ▼
          │       Qlib Dataset
          │            │
          │      ┌─────┴─────┐
          │      ▼           ▼
          │    Factor       Model
          │      │           │
          │      └─────┬─────┘
          │            ▼
          │         Strategy
          │            │
          │            ▼
          │         Backtest
          │            │
          └────────────┤
                       ▼
                  Experiment
                       │
             ┌─────────┴─────────┐
             ▼                   ▼
         Web Output          AI Analysis

22. 最终原则

这个系统必须坚持:

  1. Tushare 第一,新浪第二
  2. 数据源通过 Adapter 隔离
  3. DAO / Repository 隔离数据库
  4. SQLite 当前使用,SQLAlchemy 保证未来 MySQL 可切换
  5. 大量历史时序数据逐渐转 Parquet
  6. Qlib 是计算引擎,不是整个系统
  7. 前端只面对自己的 Domain API
  8. 前后端通过 Research Specification 解耦
  9. 所有耗时任务异步化
  10. 所有研究产生 Experiment
  11. 严格防止未来函数
  12. AI Agent 只能通过 Tool 使用研究能力
  13. 第一阶段不做实盘
  14. 第一阶段不做复杂分布式架构
  15. 每个模块都必须可以被单元测试

最终目标不是:

Qlib + Web

而是:

一个以 Qlib 为量化研究引擎、以 Tushare 为主要数据源、具备清晰 DAO 抽象和 AI Agent 接口的个人 A 股量化研究平台。