- USAGE 新增 §6.3.1「归档的日常操作」:查看 / 筛选(回写 URL)/ 导出完整 JSON / 以此参数再跑 / 删除(写明「删除即失去结果,结果只存归档一份」)/ 历史归档用 restore_experiment_from_job 按原 id 重建;并说明归档完整度如何标注 - USAGE/README 更正技术栈与图表基座:TradingView Lightweight Charts 4.2.3 为唯一 图表基座(ECharts 已从 package.json、pnpm-lock.yaml、node_modules、文档与 架构图标注中全部清除),并记录实测证据(个股页图表根节点为 div.tv-lightweight-charts,页面 canvas 无一来自其它图表库) - ARCHITECTURE 更正「当前数据库」(原写 SQLite/未来 MySQL):现为本机 MariaDB 10.11, §6 补目标库硬约束;USAGE 补服务器身份与实测连接证据 - AGENT.md 新增 §0.1:数据库目标只允许本机 MariaDB,禁止 192.168.1.10, 由 config.py::assert_db_target_allowed 硬拦截(命中直接抛错,不静默降级) - DEV_PLAN_DIVIDEND_BACKTEST 记录三轮实施与验证、归档恢复边界(§12.5)、已知限制 - DEV_PLAN v2/v3 标注为历史记录(避免把当时的远端库地址当现状照抄); ROADMAP 更正 M3 图表选型
1042 lines
20 KiB
Markdown
1042 lines
20 KiB
Markdown
# A股个人量化选股与回测平台架构
|
||
|
||
> 版本:v1.0
|
||
> 定位:个人开发、A股、中低频选股/回测、AI Agent 二次开发
|
||
> 数据源优先级:Tushare > 新浪财经
|
||
> 当前数据库:**本机 MariaDB 10.11(`127.0.0.1:3306/qlib`)**
|
||
> 数据库目标约束:**只允许本机**;`192.168.1.10` 已禁止作为 DB 目标,由
|
||
> `app/core/config.py::assert_db_target_allowed` 在解析配置时硬拦截(见 `AGENT.md` §0.1)
|
||
> 历史:SQLite(`data/quant.db`)→ 远端 MySQL → 本机 MariaDB(逐表一致副本)
|
||
> 核心量化引擎: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. 数据库设计
|
||
|
||
> **目标库约束(硬性)**:一律 `127.0.0.1:3306/qlib`(本机 MariaDB 10.11)。
|
||
> `192.168.1.10` 禁止作为数据库目标 —— 连错库不会报错、界面也正常,却会把回测/归档/策略
|
||
> 静默写到另一台机器上,属于最难发现的一类故障。守卫在 `get_settings()` 里执行:
|
||
> 命中禁用主机直接抛错(应用起不来),禁用列表可用 `QLIB_FORBIDDEN_DB_HOSTS` 覆盖。
|
||
> 启动日志会打印 `数据库目标:mysql qlib@127.0.0.1:3306/qlib`(不含密码),便于随时确认。
|
||
|
||
|
||
## 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 # → 由 stock_name_history(tushare namechange)落地时点 ST 判定
|
||
|
||
financial_indicator
|
||
income_statement
|
||
|
||
# ---- 后续增量(已落地,见 docs/DEV_PLAN_DIVIDEND_BACKTEST.md §10)----
|
||
daily_basic # 每日指标:dv_ratio/dv_ttm 股息率、PE/PB、市值(高股息选股)
|
||
stock_name_history # 名称生效区间:exclude_st 的**时点**口径(股息陷阱可见)
|
||
|
||
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
|
||
研究 总览 / 股票池 / 股票筛选
|
||
策略 策略库 / 选股回测 / 实验对比
|
||
因子与信号 因子研究 / 因子组合 / 交易信号
|
||
数据 数据同步 / 数据管理
|
||
```
|
||
|
||
## 12.1 表现层约定(本轮定型)
|
||
|
||
| 约定 | 取值 | 理由 |
|
||
|---|---|---|
|
||
| 图表库 | **TradingView Lightweight Charts**(唯一) | 轻量(~45KB)、原生支持「在 series 上打买卖点标记」,金融图表交互(十字光标/缩放)开箱可用;ECharts 已下线(依赖已移除),避免两套图表基座带来的样式与交互分裂 |
|
||
| 图表基座 | `components/charts/LwChart.tsx` | 折线/面积/柱状 + 标记 + tooltip + 可点击图例由一个组件承载;**chart 实例只在结构变化时重建**,数据变化只 `setData`,避免每次刷新重建 canvas |
|
||
| 主题 | `components/charts/theme.ts` | 颜色/数值格式集中定义(涨绿跌红按 A 股习惯),组件内不出现硬编码色值 |
|
||
| 标记约束 | 标记时间必须存在于对应 series 且**升序** | Lightweight Charts 硬约束:不满足会整组标记丢失。`LwChart` 内统一做「过滤到已有时间点 + 排序」,页面只负责给语义(BUY/SELL) |
|
||
| 股票标识 | `SymbolLink`(`lib/symbols.tsx`) | 「有代码必有名称」是产品要求:后端填充 `name`(权威),前端 `GET /api/stocks/names` 缓存兜底;名称缺失显示「—」,**不猜不造**(§7 无静默行为) |
|
||
| 参数模型 | `components/StrategyParamsForm.tsx` 单一 `StrategyParams` | 策略库/回测/直通入口共用同一参数模型与校验,避免三处各自维护字段(§6 依赖抽象) |
|
||
| 策略说明 | `StrategyDoc`(后端 `describe_strategy` 推导) | 说明与公式**由 spec 真实推导**而非前端手写模板:参数一改,公式同步变;引擎未建模处进 `warnings` 如实暴露(§7/§24) |
|
||
| 结果视图 | `components/BacktestResultView.tsx`(回测页与归档页**共用**) | 「刚跑完」和「翻回来看」必须是同一套图表与表格;两处各写一套必然漂移成「归档里少一张图」 |
|
||
| 归档页 | `/experiments/{id}` 为 **Server Component**(`app/experiments/[id]/page.tsx`) | 归档是只读内容:选股条件/执行依据/元数据必须服务端直出(客户端渲染时 SSR HTML 里连「选股条件」都搜不到);交互(删除/导出/折叠 spec)隔离在 `components/ArchiveActions.tsx` |
|
||
| 归档口径说明 | 归档页顶部「选股条件」+「交易执行依据」两块,取自**归档内 spec** | 说明必须与那次执行一致,不能读当前页面状态(否则「看归档」会看到今天的参数);字段逐项对应引擎实执行语义,不写泛泛的模板话 |
|
||
| 归档列表分页 | body 保持 `list[...]`,总数放 `X-Total-Count` 响应头 | 不破坏既有前端契约,同时消除「硬编码 limit=50 静默截断」(§7):前端据此显示「显示 N 条 / 共 M 条」 |
|
||
|
||
> 前端**只**依赖 `/api/*` 的 Domain 结构(§3.2):`name` 由后端填充而不是前端反查数据库,
|
||
> 图表库可替换而不影响领域层,`/backtest` 的三种入口(策略/选股/实验)都只是把 URL 参数
|
||
> 映射成同一个 `StrategyParams`。
|
||
|
||
第二阶段:
|
||
|
||
```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 股量化研究平台。**
|
||
|