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

1010 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# A股个人量化选股与回测平台架构
> 版本:v1.0
> 定位:个人开发、A股、中低频选股/回测、AI Agent 二次开发
> 数据源优先级:Tushare > 新浪财经
> 当前数据库:SQLite
> 未来数据库:MySQL
> 核心量化引擎:Qlib
> 前端:React / Next.js
> 后端:FastAPI + Python
---
## 1. 项目目标
本项目不是简单给 Qlib 套一个 Web UI,而是构建一个独立的个人量化研究平台:
```text
Web 前端
↓
FastAPI
↓
Research Specification
↓
业务服务层
├── 数据服务
├── 股票池服务
├── 因子服务
├── 选股服务
├── 模型服务
├── 回测服务
└── 实验服务
↓
Qlib / ML
↓
标准化研究结果
↓
SQLite / Parquet
↓
Web 前端
```
AI Agent 作为独立能力层,通过受控 Tool 调用上述服务,而不是直接操作数据库或随意修改 Qlib 内部代码。
---
# 2. 总体架构
```text
┌──────────────────────┐
│ 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 不作为业务系统唯一数据存储。
系统数据分为:
```text
业务数据 → SQLite
历史/分析型大数据 → Parquet
Qlib计算数据 → Qlib Dataset
实验结果 → SQLite
```
## 3.2 前端不能直接调用 Qlib
必须经过:
```text
Frontend
↓
FastAPI
↓
Application Service
↓
Qlib Adapter
↓
Qlib
```
这样未来可以替换 Qlib,而不影响前端。
## 3.3 DAO 必须与数据库实现解耦
业务代码禁止直接:
```python
sqlite3.connect(...)
```
也禁止在 Service 中写 SQL。
必须:
```text
Service
↓
Repository / DAO Interface
↓
SQLite Repository
```
未来:
```text
Service
↓
Repository Interface
├── SQLite Repository
└── MySQL Repository
```
业务层不感知底层数据库。
---
# 4. 数据源架构
## 4.1 数据源优先级
```text
Data Service
│
┌────────┴────────┐
▼ ▼
Tushare Sina
Primary Secondary
│ │
└────────┬────────┘
▼
Normalization
│
Validation
│
Storage
```
### 第一优先级:Tushare
用于:
- 股票基本信息
- 日线行情
- 复权因子
- 指数
- 财务数据
- 分红送转
- 停复牌
- 行业/概念
- 其他可用数据
### 第二优先级:新浪财经
主要作为:
- Tushare 数据缺失补充
- 行情数据校验
- 特定实时/准实时数据补充
新浪数据必须经过统一 Adapter,禁止业务代码直接调用新浪接口。
---
# 5. 数据采集流水线
```text
Scheduler
↓
Data Source Adapter
↓
Raw Response
↓
Schema Validation
↓
Normalization
↓
Deduplication
↓
Business Validation
↓
DAO
↓
SQLite
↓
Parquet Export
↓
Qlib Dataset
```
每个数据源都必须有独立 Adapter:
```text
data/
├── sources/
│ ├── base.py
│ ├── tushare.py
│ └── sina.py
├── normalizers/
├── validators/
└── service.py
```
业务层只依赖:
```python
MarketDataProvider
```
而不是:
```python
TushareClient
```
---
# 6. 数据库设计
## 6.1 SQLite 定位
SQLite 用于:
- 股票基础信息
- 数据源状态
- 数据同步记录
- 因子定义
- 策略定义
- 回测配置
- Experiment metadata
- Job
- 用户配置
- 系统配置
SQLite 不建议长期承载超大规模原始行情明细。
历史行情和大量 Feature 优先使用 Parquet。
---
# 7. DAO / Repository 设计
推荐使用:
```text
SQLAlchemy 2.x
+
Repository Pattern
+
Pydantic DTO
```
目录:
```text
backend/
├── domain/
│ ├── entities/
│ └── repositories/
│
├── infrastructure/
│ └── persistence/
│ ├── sqlalchemy/
│ │ ├── models/
│ │ ├── repositories/
│ │ └── session.py
│ └── migrations/
│
└── application/
└── services/
```
Repository 接口示例:
```python
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:
```python
class SqlAlchemyStockRepository(StockRepository):
...
```
未来 MySQL:
```python
class MySqlStockRepository(StockRepository):
...
```
推荐实际上让两者都基于 SQLAlchemy,而不是分别维护两套 SQL。
这样数据库切换主要通过:
```text
DATABASE_URL
```
完成。
例如:
```text
SQLite:
sqlite:///./data/quant.db
MySQL:
mysql+pymysql://user:password@host/quant
```
业务 Service 不需要修改。
---
# 8. 建议的核心数据库表
第一阶段至少包括:
```text
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` 等大量时序数据如果规模变大,应逐渐迁移到:
```text
Parquet
```
SQLite 保留元数据和索引。
---
# 9. 时间与未来函数防护
所有研究数据必须明确:
```text
trade_date
report_date
announce_date
effective_date
```
财务数据必须按照 `announce_date` 控制可见性。
禁止:
```text
使用未来公告的财务数据回测过去
```
所有数据查询必须明确:
```text
as_of_date
```
例如:
```python
get_financial_data(
symbol="600519.SH",
as_of_date="2024-06-30"
)
```
只允许返回当时市场已经知道的数据。
---
# 10. Domain 层
建议核心领域对象:
```text
Stock
Universe
Factor
FactorTest
Model
Strategy
Portfolio
Backtest
Experiment
Job
```
例如:
```text
Universe
↓
Factor
↓
Model
↓
Strategy
↓
Backtest
↓
Experiment
```
---
# 11. Research Specification
前端、AI Agent 和后端统一使用自己的研究描述对象。
示例:
```json
{
"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"
}
}
```
然后:
```text
Research Specification
↓
Validator
↓
Strategy Builder
↓
Qlib Adapter
```
---
# 12. 前端结构
第一阶段:
```text
Dashboard
股票池
因子研究
选股
回测
Experiment
```
第二阶段:
```text
模型研究
Portfolio
AI Research
数据管理
```
---
# 13. 前端输入
## 股票池
支持:
- 市场
- 股票类型
- 行业
- 市值
- 流动性
- 上市时间
- ST
- 停牌
- 指数成分
## 因子
支持:
- 内置因子
- 自定义表达式
- 因子组合
- 权重
- 标准化
- 中性化
## 选股
支持:
- Top N
- Top %
- Score
- 等权
- Score 加权
- 行业约束
- 单股权重上限
## 回测
支持:
- 起止日期
- 调仓频率
- 初始资金
- 手续费
- 印花税
- 滑点
- 涨跌停限制
- 停牌限制
---
# 14. 前端输出
回测结果统一转换为:
```text
BacktestResult
├── summary
├── equity_curve
├── drawdown
├── monthly_returns
├── yearly_returns
├── positions
├── trades
├── turnover
├── risk_metrics
└── factor_exposure
```
这样前端完全不需要理解 Qlib 内部对象。
---
# 15. 异步 Job
所有耗时任务必须异步:
```text
POST /api/backtests
↓
Job Created
↓
Worker
↓
Qlib
↓
Result
```
前端通过:
```text
SSE
```
接收:
```text
queued
running
factor_calculation
model_training
backtesting
analysis
completed
failed
```
第一阶段可以使用:
```text
FastAPI BackgroundTasks
```
或简单本地 Worker。
系统复杂后再引入:
```text
Redis + Celery/RQ
```
不要第一版过度工程化。
---
# 16. Qlib Adapter
Qlib 必须被封装:
```text
quant/
├── qlib_adapter/
│ ├── dataset.py
│ ├── feature.py
│ ├── model.py
│ ├── backtest.py
│ └── provider.py
```
业务代码:
```python
backtest_service.run(spec)
```
而不是:
```python
qlib.init(...)
qlib.workflow(...)
```
散落在项目各处。
---
# 17. AI Agent 架构
Agent 只能调用 Tool:
```text
Agent
├── search_stocks
├── inspect_factor
├── test_factor
├── create_strategy
├── run_backtest
├── compare_experiments
├── get_backtest_result
└── create_experiment
```
Agent 禁止:
```text
直接 SQL
直接修改数据库
直接删除数据
直接执行任意 shell
直接修改生产策略
```
Agent:
```text
自然语言
↓
Research Plan
↓
Tool Calls
↓
Research Specification
↓
执行
↓
Experiment
↓
分析
```
---
# 18. AI Research 示例
用户:
> 帮我寻找适合A股月度调仓的低频选股因子。
Agent:
```text
1. 获取A股股票池
2. 创建候选因子
3. IC测试
4. RankIC测试
5. 分层测试
6. 相关性分析
7. 删除冗余因子
8. 组合因子
9. Walk Forward
10. 回测
11. 保存 Experiment
12. 输出结论
```
Agent 不能因为一次回测表现好就直接认为策略有效。
必须关注:
```text
样本外
Walk Forward
不同市场阶段
交易成本
换手率
因子稳定性
```
---
# 19. 推荐的开发目录
```text
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:数据
```text
Tushare
↓
标准化
↓
SQLite
↓
Parquet
```
完成:
- 股票列表
- 交易日历
- 日线
- 复权因子
- 基本财务指标
### Phase 2:Qlib
```text
Parquet
↓
Qlib Dataset
↓
Alpha158 / 自定义因子
↓
LightGBM
↓
Backtest
```
### Phase 3:Web
完成:
```text
股票池
因子
选股
回测
结果
```
### Phase 4:Experiment
所有研究自动保存。
### Phase 5:AI Agent
最后再接:
```text
自然语言
↓
Research Plan
↓
Tool
↓
Experiment
```
---
# 21. 数据流总图
```text
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 股量化研究平台。**