Files
qlib/docs/ARCHITECTURE_v2.md

1739 lines
27 KiB
Markdown
Raw Permalink 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股个人量化选股与回测平台架构
> 版本:v2.0
> 定位:个人开发、A股、中低频选股/回测、AI Agent 二次开发
> 数据源优先级:Tushare > 新浪财经
> 当前数据库:SQLite
> 未来数据库:MySQL
> 核心量化引擎:Qlib
> 前端:React / Next.js
> 后端:FastAPI + Python
---
## 1. 项目目标
本项目不是简单给 Qlib 套一个 Web UI,而是构建一个独立的个人 A 股量化研究平台。
核心目标是形成完整的:
```text
数据
↓
因子
↓
因子研究
↓
复合因子 / 模型
↓
股票筛选
↓
交易信号
↓
组合构建
↓
回测
↓
Experiment
↓
实盘前候选与信号
```
总体业务架构:
```text
Web / AI Agent
↓
Research Specification
↓
Application Services
├── Data Service
├── Universe Service
├── Factor Service
├── Factor Research Service
├── Selection Service
├── Signal Service
├── Portfolio Service
├── Model Service
├── Backtest Service
└── Experiment Service
↓
Quant Engine
├── Qlib
└── ML
↓
Standardized Results
↓
SQLite / Parquet / Qlib Dataset
```
AI Agent 作为独立能力层,通过受控 Tool 调用上述服务,而不是直接操作数据库或随意修改 Qlib 内部代码。
---
## 2. 总体架构
```text
┌──────────────────────────┐
│ React / Next │
│ │
│ Dashboard │
│ 股票池 │
│ 因子研究 │
│ 复合因子 │
│ 股票筛选 │
│ 交易信号 │
│ 组合管理 │
│ 回测 │
│ Experiment │
│ AI Research │
└────────────┬─────────────┘
│ REST / SSE
▼
┌──────────────────────────┐
│ FastAPI │
│ │
│ API / DTO / Validation │
│ Job / Research Spec │
└────────────┬─────────────┘
│
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
Data Services Research Services Agent Service
│ │ │
│ ┌───────────┼────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ ▼
│ Factor Selection Signal Agent Tools
│ Research Engine Engine
│ │ │ │
│ └───────────┼────────────┘
│ ▼
│ Portfolio Engine
│ │
│ ▼
│ Backtest Engine
│ │
│ ▼
│ Qlib / ML
│
▼
DAO / Repository
│
├── SQLite
├── Parquet
└── Qlib Dataset
```
---
## 3. 核心设计原则
### 3.1 Qlib 是量化计算引擎,不是整个业务系统
Qlib 主要负责:
- Feature / Dataset
- 模型训练
- Prediction
- 部分 Portfolio
- Backtest
- 分析工具
本系统自己的业务层负责:
- 股票池
- 因子定义
- 因子研究
- 复合因子
- 股票筛选
- 交易信号
- 组合构建
- 策略版本
- Experiment
- AI Agent
因此:
```text
Qlib
=
Quant Engine
本项目
=
Quant Research Platform
```
### 3.2 因子研究、股票筛选、交易信号必须分离
这是本架构的核心设计原则。
**Factor Research** 回答:
> 这个因子有没有预测能力?
**Selection Engine** 回答:
> 在某一个历史/当前时点,哪些股票符合策略条件?
**Signal Engine** 回答:
> 什么时候应该买、卖或继续持有?
**Portfolio Engine** 回答:
> 买哪些股票、买多少、什么时候调仓?
完整关系:
```text
Factor
↓
Factor Research
↓
Composite Factor / Model
↓
Selection Engine
↓
Candidate Stocks
↓
Signal Engine
↓
BUY / SELL / HOLD
↓
Portfolio Engine
↓
Backtest
```
---
## 4. 数据源架构
```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
```
目录:
```text
data/
├── sources/
│ ├── base.py
│ ├── tushare.py
│ └── sina.py
├── normalizers/
├── validators/
└── service.py
```
业务层只依赖:
```python
MarketDataProvider
```
而不是:
```python
TushareClient
```
---
## 6. 数据存储架构
```text
业务元数据
↓
SQLite
历史/分析型大数据
↓
Parquet
Qlib 计算数据
↓
Qlib Dataset
实验/策略/任务元数据
↓
SQLite
```
SQLite 用于:
- 股票基础信息
- 数据源状态
- 数据同步记录
- 因子定义
- 因子研究记录
- 策略定义
- 选股规则
- 信号规则
- 组合配置
- 回测配置
- Experiment metadata
- Job
- 用户配置
- 系统配置
SQLite 不建议长期承载超大规模原始行情明细。
---
## 7. DAO / Repository 设计
推荐:
```text
SQLAlchemy 2.x
+
Repository Pattern
+
Pydantic DTO
```
业务层禁止直接:
```python
sqlite3.connect(...)
```
也禁止在 Service 中直接写 SQL。
必须:
```text
Service
↓
Repository / DAO Interface
↓
SQLite Repository
```
未来:
```text
Service
↓
Repository Interface
├── SQLite Repository
└── MySQL Repository
```
数据库切换主要通过:
```text
DATABASE_URL
```
例如:
```text
SQLite:
sqlite:///./data/quant.db
MySQL:
mysql+pymysql://user:password@host/quant
```
---
## 8. 核心数据库表
```text
stock
stock_daily
stock_adjust_factor
industry
stock_industry
index
index_daily
index_constituent_history
trading_calendar
suspend_data
stock_st_data
financial_indicator
income_statement
balance_sheet
cashflow_statement
factor_definition
factor_test
factor_composite
factor_composite_component
universe
universe_rule
selection_rule
selection_result
selection_snapshot
signal_rule
signal_event
strategy
strategy_factor
strategy_selection
strategy_signal
strategy_portfolio
portfolio
portfolio_position
backtest
backtest_trade
backtest_position
backtest_metric
experiment
experiment_artifact
experiment_factor_result
experiment_selection_result
experiment_signal_result
job
data_sync_log
```
`selection_result` 保存某个研究时点的选股结果:
```text
selection_id
strategy_id
as_of_date
symbol
rank
score
selection_reason
```
`signal_event` 保存交易信号:
```text
signal_id
strategy_id
symbol
signal_date
signal_type
score
trigger_reason
price
```
这样系统不仅能回答:
> 这次回测赚了多少钱?
还能够回答:
> 2023-08-15 为什么选择这只股票?
以及:
> 2026-09-08 当前有哪些股票满足策略?
---
## 9. 时间与未来函数防护
所有研究数据必须明确:
```text
trade_date
report_date
announce_date
effective_date
as_of_date
```
财务数据必须按照 `announce_date` 控制可见性。
禁止:
```text
使用未来公告的财务数据回测过去
```
所有研究数据查询必须明确:
```text
as_of_date
```
只允许返回当时市场已经知道的数据。
同样,历史指数成分必须使用:
```text
index_constituent_history
```
禁止直接使用今天的指数成分股回测过去。
---
## 10. Domain 层
核心领域对象:
```text
Stock
Universe
Factor
FactorTest
CompositeFactor
Model
SelectionRule
SelectionResult
SignalRule
SignalEvent
Strategy
Portfolio
Backtest
Experiment
Job
```
核心关系:
```text
Universe
↓
Factor
↓
FactorTest
↓
CompositeFactor / Model
↓
SelectionRule
↓
SelectionResult
↓
SignalRule
↓
SignalEvent
↓
Portfolio
↓
Strategy
↓
Backtest
↓
Experiment
```
---
## 11. Factor Engine
Factor Engine 负责:
```text
原始数据
↓
因子计算
↓
标准化
↓
中性化
↓
因子值
```
支持:
- 内置因子
- 技术因子
- 财务因子
- 估值因子
- 成长因子
- 质量因子
- 动量因子
- 波动率因子
- 自定义表达式
每个因子必须具有:
```text
name
description
formula
input_data
frequency
lookback
direction
normalization
neutralization
availability_rule
version
```
---
## 12. Factor Research Service
因子研究不是直接选股,而是评估因子的预测能力。
支持:
```text
IC
RankIC
ICIR
分层收益
多空组合
累计收益
因子稳定性
因子相关性
行业暴露
市值暴露
换手率
不同市场阶段
```
典型流程:
```text
Candidate Factors
↓
Data Validation
↓
IC / RankIC
↓
Layered Backtest
↓
Correlation
↓
Redundancy Removal
↓
Factor Combination
↓
Out-of-Sample Test
```
---
## 13. Composite Factor Engine
复合因子负责把多个单因子组合成一个可用于选股的 Score。
例如:
```text
CompositeScore =
0.25 × ROE
+ 0.20 × RevenueGrowth
+ 0.30 × Momentum60
+ 0.10 × PE
+ 0.15 × Quality
```
支持:
- 固定权重
- Rank 加权
- Z-Score 加权
- IC 加权
- ICIR 加权
- 手工权重
- ML 模型输出
- 因子方向控制
- 标准化
- 行业中性化
- 市值中性化
注意:
```text
Composite Factor
≠
Strategy
```
Composite Factor 只是生成:
```text
Stock → Score
```
真正决定买卖的仍然是 Selection + Signal + Portfolio。
---
## 14. Selection Engine:股票筛选引擎
Selection Engine 是连接“研究”和“实际选股”的核心模块。
### 14.1 三种选股模式
**A. 条件选股**
```text
ROE > 15%
AND
PE < 30
AND
Revenue Growth > 20%
AND
Close > MA60
```
**B. 因子评分选股**
```text
Composite Score
↓
Rank
↓
Top N
```
**C. 模型预测选股**
```text
Historical Data
↓
Features
↓
LightGBM / Qlib Model
↓
Predicted Return
↓
Rank
↓
Top N
```
### 14.2 Selection 输入
```text
Universe
+
Filters
+
Factor / Composite Factor / Model
+
Ranking
+
Top N / Top %
+
Constraints
```
### 14.3 Selection 输出
```text
SelectionResult
├── as_of_date
├── symbol
├── rank
├── score
├── factor_values
├── filter_status
├── selection_reason
└── metadata
```
Selection Engine 必须支持历史日期执行:
```text
select(
strategy_id,
as_of_date="2024-06-30"
)
```
因此:
> 当前选股和历史回测选股必须使用同一套 Selection Engine。
---
## 15. Signal Engine:交易信号引擎
Selection 解决:
> 哪些股票值得关注?
Signal 解决:
> 什么时候交易?
典型输入:
```text
SelectionResult
+
Price
+
Technical Indicators
+
Market Regime
+
Existing Position
+
Risk Rules
```
输出:
```text
BUY
SELL
HOLD
WATCH
```
例如:
```text
Selection Rank <= 20
AND
Close > MA60
AND
Momentum20 > 0
AND
Market Regime = Bull
→ BUY
```
卖出:
```text
Rank > 50
OR
Close < MA60
OR
Risk Rule Triggered
→ SELL
```
SignalEvent 必须记录:
```text
signal_date
symbol
signal_type
trigger_reason
score
price
strategy_id
```
这样可以解释:
> 为什么这一天产生买入信号?
---
## 16. Portfolio Engine:组合构建
Signal 产生以后,不直接进入回测,而是进入 Portfolio Engine。
Portfolio Engine 负责:
- 股票数量
- 仓位
- 权重
- 行业约束
- 单股上限
- 最大回撤控制
- 换手约束
- 调仓
- 现金管理
支持:
```text
Equal Weight
Score Weight
Risk Weight
Custom Weight
```
例如:
```text
Top 20
↓
过滤 BUY 信号
↓
剩余 12 只
↓
单股最大 10%
↓
行业最大 25%
↓
组合最终持仓
```
---
## 17. Strategy:完整策略定义
Strategy 不再只是 Factor + Model + Backtest,而是:
```text
Strategy
├── Universe
├── Filters
├── Factors
├── Composite Factor
├── Model
├── Selection Rule
├── Signal Rule
├── Portfolio Rule
├── Rebalance Rule
└── Risk Rule
```
示例:
```yaml
strategy:
name: "质量成长动量策略"
universe:
type: "CSI300"
filters:
- market_cap > 10000000000
- is_st = false
- suspended = false
factors:
- name: roe_ttm
weight: 0.25
- name: revenue_growth
weight: 0.20
- name: momentum_60
weight: 0.30
- name: pe
weight: 0.10
- name: quality
weight: 0.15
selection:
method: composite_score
top_n: 20
signal:
buy:
- score_rank <= 20
- close > ma60
sell:
- score_rank > 50
- close < ma60
portfolio:
weighting: equal
max_position: 0.10
max_industry_weight: 0.25
rebalance:
frequency: weekly
```
---
## 18. Research Specification
前端、AI Agent 和后端统一使用自己的研究描述对象。
Research Specification 是系统最重要的业务契约之一。
处理流程:
```text
Research Specification
↓
Validator
↓
Strategy Builder
↓
Selection Builder
↓
Signal Builder
↓
Portfolio Builder
↓
Qlib / ML Adapter
↓
Backtest
```
前端和 Agent 不允许直接生成任意 Qlib 配置绕过这一层。
---
## 19. 前端结构
第一阶段:
```text
Dashboard
股票池
因子研究
复合因子
股票筛选
交易信号
回测
Experiment
```
第二阶段:
```text
模型研究
Portfolio
AI Research
数据管理
```
---
## 20. 前端输入
### 股票池
支持:
- 市场
- 股票类型
- 行业
- 市值
- 流动性
- 上市时间
- ST
- 停牌
- 指数成分
- 历史指数成分
### 因子
支持:
- 内置因子
- 自定义表达式
- 因子组合
- 权重
- 标准化
- 中性化
### 股票筛选
支持:
- 条件筛选
- Top N
- Top %
- Score
- Score Threshold
- 等权
- Score 加权
- 行业约束
- 市值约束
- 流动性约束
- 单股权重上限
### 交易信号
支持:
- 买入条件
- 卖出条件
- 持有条件
- 趋势条件
- 技术指标
- 市场环境
- 风险条件
### 回测
支持:
- 起止日期
- 调仓频率
- 初始资金
- 手续费
- 印花税
- 滑点
- 涨跌停限制
- 停牌限制
- 成交约束
---
## 21. 前端输出
### 21.1 选股结果
```text
SelectionResult
├── as_of_date
├── universe
├── candidates
│ ├── symbol
│ ├── rank
│ ├── score
│ ├── factor_values
│ └── selection_reason
└── statistics
```
### 21.2 信号结果
```text
SignalResult
├── symbol
├── signal
├── score
├── trigger_reason
├── price
└── risk_flags
```
### 21.3 回测结果
```text
BacktestResult
├── summary
├── equity_curve
├── drawdown
├── monthly_returns
├── yearly_returns
├── positions
├── trades
├── turnover
├── risk_metrics
├── factor_exposure
├── selection_history
└── signal_history
```
前端完全不需要理解 Qlib 内部对象。
---
## 22. 异步 Job
所有耗时任务必须异步:
```text
POST /api/backtests
↓
Job Created
↓
Worker
↓
Selection
↓
Signal
↓
Portfolio
↓
Qlib
↓
Result
```
前端通过 SSE 接收:
```text
queued
running
data_loading
factor_calculation
factor_research
selection
signal_generation
portfolio_construction
model_training
backtesting
analysis
completed
failed
```
第一阶段:
```text
FastAPI BackgroundTasks
```
复杂后再引入:
```text
Redis + Celery/RQ
```
不要第一版过度工程化。
---
## 23. 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(...)
```
散落在项目各处。
---
## 24. AI Agent 架构
Agent 只能调用受控 Tool:
```text
Agent
├── search_stocks
├── inspect_factor
├── test_factor
├── create_composite_factor
├── screen_stocks
├── explain_selection
├── generate_signals
├── create_strategy
├── run_backtest
├── compare_experiments
├── get_backtest_result
└── create_experiment
```
Agent 禁止:
```text
直接 SQL
直接修改数据库
直接删除数据
直接执行任意 shell
直接修改生产策略
直接调用 Qlib 内部 API 绕过业务层
```
---
## 25. 研究与回测一致性
这是本平台必须保证的关键原则:
> **历史回测使用的选股、信号和组合逻辑,与当前实际选股使用的逻辑必须完全相同。**
正确方式:
```text
Strategy Specification
│
┌───────────┼───────────┐
▼ ▼ ▼
Historical Current Future
Backtest Screen Signal
│ │ │
└───────────┼───────────┘
▼
Same Engine
```
这样可以避免:
```text
回测一套逻辑
实际运行另一套逻辑
```
---
## 26. Experiment 可复现性
每次研究必须记录:
```text
experiment_id
data_version
code_version
strategy_version
universe
factor_version
model_version
selection_rule
signal_rule
portfolio_rule
backtest_config
start_date
end_date
result
```
最好记录:
```text
git commit
```
目标:
```text
同一个 Experiment
+
同一个数据版本
+
同一个代码版本
+
同一个 Strategy Version
=
可以重新得到相同研究结果
```
---
## 27. 测试要求
必须测试:
```text
Data Adapter
DAO
Repository
Research Specification
Future-data Protection
Factor
Factor Research
Composite Factor
Selection Engine
Signal Engine
Portfolio Engine
Backtest
API
Experiment
```
特别需要测试:
### Future Function
```text
announce_date > as_of_date
→ 不得进入研究数据
```
### Survivorship Bias
```text
历史成分股
≠
当前成分股
```
### Selection / Backtest Consistency
```text
历史某日 Selection
=
Backtest 当日 Selection
```
### Signal Consistency
```text
历史某日 Signal
=
Strategy Engine 在同一条件下重新计算的 Signal
```
---
## 28. 开发目录
```text
quant-platform/
│
├── frontend/
│ └── web/
│
├── backend/
│ ├── app/
│ │ ├── api/
│ │ ├── application/
│ │ │ └── services/
│ │ │ ├── data_service.py
│ │ │ ├── universe_service.py
│ │ │ ├── factor_service.py
│ │ │ ├── factor_research_service.py
│ │ │ ├── composite_factor_service.py
│ │ │ ├── selection_service.py
│ │ │ ├── signal_service.py
│ │ │ ├── portfolio_service.py
│ │ │ ├── model_service.py
│ │ │ ├── backtest_service.py
│ │ │ └── experiment_service.py
│ │ ├── domain/
│ │ │ ├── entities/
│ │ │ └── repositories/
│ │ ├── infrastructure/
│ │ ├── quant/
│ │ │ └── qlib_adapter/
│ │ ├── agent/
│ │ └── core/
│ │
│ └── tests/
│
├── data/
│ ├── raw/
│ ├── normalized/
│ ├── parquet/
│ └── qlib/
│
├── experiments/
├── scripts/
├── docker/
├── docs/
├── ARCHITECTURE.md
├── AGENT.md
└── README.md
```
---
## 29. MVP 开发阶段
### Phase 1:数据
```text
Tushare
↓
标准化
↓
SQLite
↓
Parquet
```
完成:
- 股票列表
- 交易日历
- 日线
- 复权因子
- 基本财务指标
- 历史指数成分
### Phase 2:因子
```text
Parquet
↓
Qlib Dataset
↓
自定义因子
↓
Factor Research
```
完成:
- 因子计算
- IC
- RankIC
- 分层
- 因子相关性
### Phase 3:股票筛选
```text
Factor
↓
Composite Factor
↓
Selection Engine
↓
Top N
```
完成:
- 条件选股
- 多因子评分
- 复合因子
- Top N
- 历史选股
- 当前选股
### Phase 4:交易信号
```text
Selection
↓
Signal Engine
↓
BUY / SELL / HOLD
```
完成:
- 买入条件
- 卖出条件
- 技术指标
- 趋势条件
- 信号历史
### Phase 5:组合与回测
```text
Selection
↓
Signal
↓
Portfolio
↓
Qlib Backtest
```
完成:
- 仓位
- 调仓
- 交易成本
- 涨跌停
- 停牌
- 回撤
- Sharpe
- 换手率
### Phase 6:Web
```text
Dashboard
股票池
因子研究
复合因子
股票筛选
交易信号
回测
Experiment
```
### Phase 7:AI Agent
```text
自然语言
↓
Research Plan
↓
Tool
↓
Strategy
↓
Selection
↓
Signal
↓
Backtest
↓
Experiment
```
---
## 30. 数据流总图
```text
Tushare
│
▼
Tushare Adapter
│
失败/缺失
▼
Sina Adapter
│
▼
Raw Data
│
▼
Data Validator
│
▼
Normalization
│
┌───────┴────────┐
▼ ▼
SQLite Parquet
│ │
│ ▼
│ Qlib Dataset
│ │
│ ┌───────┴────────┐
│ ▼ ▼
│ Factor Model
│ │ │
│ └───────┬────────┘
│ ▼
│ Composite Factor
│ │
│ ▼
│ Selection Engine
│ │
│ Candidates
│ │
│ ▼
│ Signal Engine
│ │
│ BUY/SELL
│ │
│ ▼
│ Portfolio Engine
│ │
│ ▼
│ Backtest Engine
│ │
└────────────────┤
▼
Experiment
│
┌─────────┴─────────┐
▼ ▼
Web Output AI Analysis
```
---
## 31. 最终核心原则
这个系统必须坚持:
1. **Tushare 第一,新浪第二**
2. **数据源通过 Adapter 隔离**
3. **DAO / Repository 隔离数据库**
4. **SQLite 当前使用,SQLAlchemy 保证未来 MySQL 可切换**
5. **大量历史时序数据逐渐转 Parquet**
6. **Qlib 是计算引擎,不是整个系统**
7. **因子研究、股票筛选、交易信号、组合构建必须分层**
8. **Selection Engine 必须支持历史日期和当前日期**
9. **回测与实际选股必须使用同一套 Strategy Engine**
10. **前端只面对自己的 Domain API**
11. **前后端通过 Research Specification 解耦**
12. **所有耗时任务异步化**
13. **所有研究产生 Experiment**
14. **严格防止未来函数**
15. **严格防止幸存者偏差**
16. **AI Agent 只能通过 Tool 使用研究能力**
17. **第一阶段不做实盘**
18. **第一阶段不做复杂分布式架构**
19. **每个核心模块都必须可以被单元测试**
20. **系统最终输出不仅是回测收益,还必须能够解释“为什么选这只股票、为什么产生这个交易信号”。**
最终目标不是:
> Qlib + Web
而是:
> **一个以 Qlib 为量化计算引擎、以 Tushare 为主要数据源、以 Composite Factor + Selection + Signal + Portfolio 为策略核心、具备严格历史一致性和 AI Agent 接口的个人 A 股量化研究平台。**