1885 lines
32 KiB
Markdown
1885 lines
32 KiB
Markdown
# A股个人量化选股与回测平台架构
|
||
|
||
> 版本:v3.0
|
||
> 本版本重点:统一可视化 / Chart Service、K线与回测成交点、Signal 与实际成交 Fill 区分、A股复权口径、Bar Replay
|
||
> 定位:个人开发、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
|
||
数据管理
|
||
```
|
||
|
||
---
|
||
|
||
## 21. Chart / Visualization Service:统一量化可视化
|
||
|
||
本版本新增 Chart Service,负责把 Selection、Signal、Backtest、Factor 等研究结果转换成统一的前端图表数据。
|
||
|
||
核心原则:
|
||
|
||
> **前端只负责展示,不能自行重新计算交易信号、成交点或策略结果。**
|
||
|
||
数据流:
|
||
|
||
```text
|
||
Stock / Selection / Signal / Backtest
|
||
↓
|
||
Chart Service
|
||
↓
|
||
Chart DTO / API
|
||
↓
|
||
React Chart Components
|
||
↓
|
||
TradingView Lightweight Charts
|
||
```
|
||
|
||
推荐:React / Next.js + TypeScript + TradingView Lightweight Charts。
|
||
|
||
### 20.1 Chart Service 职责
|
||
|
||
负责:
|
||
- 股票历史 K 线、成交量
|
||
- 技术指标
|
||
- Selection / Signal / Backtest Fill 标记
|
||
- 持仓区间
|
||
- 策略 Score、因子值、Benchmark
|
||
- Tooltip 解释信息
|
||
- Bar Replay 数据
|
||
|
||
不负责重新计算 Selection、Signal 或 Backtest。
|
||
|
||
### 20.2 Chart API
|
||
|
||
```text
|
||
GET /api/stocks/{symbol}/chart
|
||
GET /api/stocks/{symbol}/signals
|
||
GET /api/stocks/{symbol}/selections
|
||
GET /api/backtests/{backtest_id}/stocks/{symbol}/chart
|
||
GET /api/backtests/{backtest_id}/trades
|
||
GET /api/backtests/{backtest_id}/positions
|
||
```
|
||
|
||
回测股票图表:
|
||
|
||
```text
|
||
ChartResult
|
||
├── symbol
|
||
├── name
|
||
├── adjust_mode
|
||
├── bars
|
||
├── volume
|
||
├── indicators
|
||
├── selections
|
||
├── signals
|
||
├── fills
|
||
├── holding_periods
|
||
├── factor_values
|
||
├── strategy_scores
|
||
├── benchmark
|
||
└── metadata
|
||
```
|
||
|
||
### 20.3 Signal 与 Actual Fill 必须严格区分
|
||
|
||
```text
|
||
Signal
|
||
↓
|
||
Portfolio / Execution Constraint
|
||
↓
|
||
Actual Fill
|
||
```
|
||
|
||
`signal_event` 表示策略产生的信号;`backtest_trade` 表示实际成交。涨停、停牌、现金、仓位、行业约束、换手限制等都可能导致 Signal 没有变成 Fill。
|
||
|
||
前端至少区分:
|
||
|
||
```text
|
||
BUY SIGNAL / SELL SIGNAL
|
||
EXECUTED BUY / EXECUTED SELL
|
||
```
|
||
|
||
### 20.4 Stock Research Page
|
||
|
||
每只股票提供统一研究页面:
|
||
|
||
```text
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 股票名称 / 代码 Strategy Score Signal │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ K-Line │
|
||
│ BUY / SELL / Fill markers │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ Volume │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ MA / MACD / RSI / ... │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ Selection / Signal / Trade Detail │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ Factor Values / Score / Reason / Risk Flags │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
每个事件应可点击查看原因、Score、Rank、因子值、成交价格、数量、滑点和费用。
|
||
|
||
### 20.5 A股复权与回测价格
|
||
|
||
必须严格区分:
|
||
|
||
```text
|
||
Chart Display Price
|
||
vs
|
||
Backtest Execution Price
|
||
```
|
||
|
||
图表支持:不复权 / 前复权 / 后复权。系统必须记录 `adjust_mode`、`price_basis`、`execution_price_basis`。如果图表和回测使用不同价格口径,Chart Service 必须完成坐标转换,避免成交点与K线处于不同价格体系。
|
||
|
||
### 20.6 Bar Replay
|
||
|
||
第二阶段支持历史逐日重放:
|
||
|
||
```text
|
||
|< < ▶ > >|
|
||
1D 5D 20D
|
||
```
|
||
|
||
Replay 必须只使用当时的 `as_of_date` 和 `available_data`,用于检查未来函数、Selection / Signal 一致性以及实际成交条件。
|
||
|
||
---
|
||
|
||
## 21. 前端输入
|
||
|
||
### 股票池
|
||
|
||
支持:
|
||
|
||
- 市场
|
||
- 股票类型
|
||
- 行业
|
||
- 市值
|
||
- 流动性
|
||
- 上市时间
|
||
- ST
|
||
- 停牌
|
||
- 指数成分
|
||
- 历史指数成分
|
||
|
||
### 因子
|
||
|
||
支持:
|
||
|
||
- 内置因子
|
||
- 自定义表达式
|
||
- 因子组合
|
||
- 权重
|
||
- 标准化
|
||
- 中性化
|
||
|
||
### 股票筛选
|
||
|
||
支持:
|
||
|
||
- 条件筛选
|
||
- Top N
|
||
- Top %
|
||
- Score
|
||
- Score Threshold
|
||
- 等权
|
||
- Score 加权
|
||
- 行业约束
|
||
- 市值约束
|
||
- 流动性约束
|
||
- 单股权重上限
|
||
|
||
### 交易信号
|
||
|
||
支持:
|
||
|
||
- 买入条件
|
||
- 卖出条件
|
||
- 持有条件
|
||
- 趋势条件
|
||
- 技术指标
|
||
- 市场环境
|
||
- 风险条件
|
||
|
||
### 回测
|
||
|
||
支持:
|
||
|
||
- 起止日期
|
||
- 调仓频率
|
||
- 初始资金
|
||
- 手续费
|
||
- 印花税
|
||
- 滑点
|
||
- 涨跌停限制
|
||
- 停牌限制
|
||
- 成交约束
|
||
|
||
---
|
||
|
||
## 22. 前端输出
|
||
|
||
### 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 内部对象。
|
||
|
||
---
|
||
|
||
## 23. 异步 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
|
||
```
|
||
|
||
不要第一版过度工程化。
|
||
|
||
---
|
||
|
||
## 24. 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(...)
|
||
```
|
||
|
||
散落在项目各处。
|
||
|
||
---
|
||
|
||
## 25. 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 绕过业务层
|
||
```
|
||
|
||
---
|
||
|
||
## 26. 研究与回测一致性
|
||
|
||
这是本平台必须保证的关键原则:
|
||
|
||
> **历史回测使用的选股、信号和组合逻辑,与当前实际选股使用的逻辑必须完全相同。**
|
||
|
||
正确方式:
|
||
|
||
```text
|
||
Strategy Specification
|
||
│
|
||
┌───────────┼───────────┐
|
||
▼ ▼ ▼
|
||
Historical Current Future
|
||
Backtest Screen Signal
|
||
│ │ │
|
||
└───────────┼───────────┘
|
||
▼
|
||
Same Engine
|
||
```
|
||
|
||
这样可以避免:
|
||
|
||
```text
|
||
回测一套逻辑
|
||
实际运行另一套逻辑
|
||
```
|
||
|
||
---
|
||
|
||
## 27. 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
|
||
=
|
||
可以重新得到相同研究结果
|
||
```
|
||
|
||
---
|
||
|
||
## 28. 测试要求
|
||
|
||
必须测试:
|
||
|
||
```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
|
||
```
|
||
|
||
---
|
||
|
||
## 29. 开发目录
|
||
|
||
```text
|
||
quant-platform/
|
||
│
|
||
├── frontend/
|
||
│ └── web/
|
||
│ ├── components/
|
||
│ │ ├── StockChart/
|
||
│ │ ├── TradeMarkers/
|
||
│ │ ├── IndicatorPane/
|
||
│ │ ├── SelectionPanel/
|
||
│ │ ├── SignalPanel/
|
||
│ │ └── ReplayControls/
|
||
│ └── services/
|
||
│ └── chart_api.ts
|
||
│
|
||
├── 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
|
||
│ │ └── chart_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
|
||
```
|
||
|
||
---
|
||
|
||
## 30. 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
|
||
```
|
||
|
||
---
|
||
|
||
## 31. 数据流总图
|
||
|
||
```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
|
||
```
|
||
|
||
---
|
||
|
||
## 32. 最终核心原则
|
||
|
||
这个系统必须坚持:
|
||
|
||
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 股量化研究平台。**
|
||
|