auto-sync: 2026-04-30 20:51:54
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
# 📐 架构设计:整合数据平台与回测环境
|
||||
|
||||
**任务ID**: integrate-data-platform-20260430
|
||||
**撰写人**: 庞统
|
||||
**日期**: 2026-04-30
|
||||
|
||||
---
|
||||
|
||||
## 一、现状分析
|
||||
|
||||
### 数据资产清单
|
||||
|
||||
| 数据类型 | 格式 | 存储位置 | 文件组织 | 数量 |
|
||||
|----------|------|---------|---------|------|
|
||||
| 日线行情 | Parquet | `raw/daily/{year}/{code}_daily.parquet` | 按年分目录 | 2013-2025 |
|
||||
| 财务估值 | Parquet | `raw/financial/valuation/{code}_valuation.parquet` | 按类型分目录 | ~5000股 |
|
||||
| 股票信息 | CSV | `raw/stock_info/stock_basic_info_*.csv` | 单文件 | 5493股 |
|
||||
| HS300成分 | CSV | `raw/stock_info/hs300_constituents_latest.csv` | 单文件 | 300只 |
|
||||
| 日线(旧) | Parquet | `raw/a_stock_daily/{year}/` | 按年分目录,无文件 | 可能为空 |
|
||||
|
||||
### 已有组件
|
||||
|
||||
| 组件 | 语言 | 接口 | 依赖 |
|
||||
|------|------|------|------|
|
||||
| VnpyLocalDataAdapter | Python | 类方法 | akshare |
|
||||
| backtest-service | Python | REST API (FastAPI) | vnpy |
|
||||
| 张飞回测框架 | Python | 函数调用 | numpy, pandas |
|
||||
|
||||
### 关键发现
|
||||
|
||||
1. **数据格式已经是 Parquet**(不是 CSV),字段:`date, open, high, low, close, volume, amount, outstanding_share, turnover, year`
|
||||
2. **姜维适配器路径硬编码** `/Users/chufeng/nas/stock/sanguo_vnpy/zhaoyun-data/data`,与实际数据路径不同
|
||||
3. **a_stock_daily/ 和 daily/ 是两套目录**,需确认哪套是主数据
|
||||
|
||||
---
|
||||
|
||||
## 二、架构设计
|
||||
|
||||
### 核心原则:最简方案
|
||||
|
||||
**不新建独立包/服务**。直接在现有项目内加一个 `data_platform.py` 配置文件 + 一个 `catalog.py` 数据接口。
|
||||
|
||||
### 架构图
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ 策略开发者 │
|
||||
│ (张飞回测 / vnpy回测 / 未来策略) │
|
||||
└───────────────────┬─────────────────────────────┘
|
||||
│ 调用
|
||||
▼
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ DataCatalog (catalog.py) │
|
||||
│ │
|
||||
│ get_daily(symbol, start, end) → DataFrame │
|
||||
│ get_stock_list() → DataFrame │
|
||||
│ get_financial(symbol) → DataFrame │
|
||||
│ get_index_constituents(index) → DataFrame │
|
||||
└───────────────────┬─────────────────────────────┘
|
||||
│ 读取
|
||||
▼
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ data_platform_config.yaml │
|
||||
│ DATA_ROOT: /path/to/zhaoyun-data/data │
|
||||
└───────────────────┬─────────────────────────────┘
|
||||
│ 指向
|
||||
▼
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ 赵云数据目录 (zhaoyun-data/data/) │
|
||||
│ │
|
||||
│ raw/daily/{year}/{code}_daily.parquet │
|
||||
│ raw/financial/valuation/{code}_valuation.parquet│
|
||||
│ raw/stock_info/stock_basic_info_*.csv │
|
||||
│ raw/stock_info/hs300_constituents_latest.csv │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 模块划分
|
||||
|
||||
```
|
||||
sanguo_quant_live/
|
||||
├── data_platform/ # 🆕 数据平台模块(新建)
|
||||
│ ├── __init__.py
|
||||
│ ├── config.py # 配置加载(读 yaml + 环境变量)
|
||||
│ ├── catalog.py # DataCatalog 核心接口
|
||||
│ └── data_platform_config.yaml # 配置文件(DATA_ROOT 等)
|
||||
├── zhaoyun-data/ # 赵云数据(已有)
|
||||
│ └── data/raw/...
|
||||
├── zhangfei-technical/ # 张飞回测(已有)
|
||||
└── jiangwei-platform/ # 姜维基建(已有)
|
||||
|
||||
sanguo_vnpy/
|
||||
└── src/
|
||||
└── adapters/
|
||||
└── vnpy_local_data_adapter.py # 姜维适配器(改路径配置)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、接口定义
|
||||
|
||||
### data_platform_config.yaml
|
||||
|
||||
```yaml
|
||||
# 数据平台配置
|
||||
data_root: "${ZHAOYUN_DATA_ROOT}" # 优先环境变量
|
||||
# 默认值(环境变量未设置时)
|
||||
default_data_root: "/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live/zhaoyun-data/data"
|
||||
|
||||
# 数据源配置
|
||||
sources:
|
||||
daily:
|
||||
format: parquet
|
||||
path_pattern: "raw/daily/{year}/{code}_daily.parquet"
|
||||
date_range: [2013, 2025]
|
||||
columns: [date, open, high, low, close, volume, amount, outstanding_share, turnover]
|
||||
|
||||
stock_info:
|
||||
format: csv
|
||||
path: "raw/stock_info"
|
||||
file_pattern: "stock_basic_info_*.csv"
|
||||
|
||||
financial:
|
||||
format: parquet
|
||||
path_pattern: "raw/financial/valuation/{code}_valuation.parquet"
|
||||
|
||||
index_constituents:
|
||||
format: csv
|
||||
path: "raw/stock_info/hs300_constituents_latest.csv"
|
||||
|
||||
# fallback(本地无数据时)
|
||||
fallback:
|
||||
enabled: true
|
||||
provider: akshare
|
||||
```
|
||||
|
||||
### config.py
|
||||
|
||||
```python
|
||||
"""数据平台配置加载"""
|
||||
import os
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
|
||||
def load_config() -> dict:
|
||||
"""加载配置,环境变量优先"""
|
||||
config_path = Path(__file__).parent / "data_platform_config.yaml"
|
||||
with open(config_path) as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# 环境变量覆盖 data_root
|
||||
env_root = os.environ.get("ZHAOYUN_DATA_ROOT")
|
||||
if env_root:
|
||||
config["data_root"] = env_root
|
||||
elif "${" in config.get("data_root", ""):
|
||||
config["data_root"] = config["default_data_root"]
|
||||
|
||||
return config
|
||||
```
|
||||
|
||||
### catalog.py 核心接口
|
||||
|
||||
```python
|
||||
"""DataCatalog - 统一数据访问接口"""
|
||||
import pandas as pd
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from .config import load_config
|
||||
|
||||
class DataCatalog:
|
||||
def __init__(self, config: dict = None):
|
||||
self._config = config or load_config()
|
||||
self._data_root = Path(self._config["data_root"])
|
||||
|
||||
def get_daily(self, symbol: str, start: str = None, end: str = None) -> pd.DataFrame:
|
||||
"""获取日线行情
|
||||
Args:
|
||||
symbol: 股票代码,如 "000001" 或 "sh600519"
|
||||
start: 开始日期 "YYYY-MM-DD"
|
||||
end: 结束日期 "YYYY-MM-DD"
|
||||
"""
|
||||
...
|
||||
|
||||
def get_stock_list(self) -> pd.DataFrame:
|
||||
"""获取全部A股列表"""
|
||||
...
|
||||
|
||||
def get_financial(self, symbol: str) -> pd.DataFrame:
|
||||
"""获取财务估值数据"""
|
||||
...
|
||||
|
||||
def get_index_constituents(self, index: str = "000300") -> pd.DataFrame:
|
||||
"""获取指数成分股"""
|
||||
...
|
||||
```
|
||||
|
||||
### stock code 标准化规则
|
||||
|
||||
```
|
||||
输入格式:
|
||||
"000001" / "sz000001" / "000001.SZ" → 标准化为 "sz000001"(parquet文件名)
|
||||
"600519" / "sh600519" / "600519.SH" → 标准化为 "sh600519"
|
||||
|
||||
规则:
|
||||
0/3 开头 → sz 前缀
|
||||
6 开头 → sh 前缀
|
||||
已有 sh/sz 前缀 → 保持
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、数据流设计
|
||||
|
||||
### 日线数据流
|
||||
|
||||
```
|
||||
赵云采集脚本 → raw/daily/{year}/{code}_daily.parquet
|
||||
↓
|
||||
DataCatalog.get_daily("600519", "2024-01-01", "2024-12-31")
|
||||
↓
|
||||
1. 标准化 code → sh600519
|
||||
2. 扫描 2024/ 目录
|
||||
3. pd.read_parquet("raw/daily/2024/sh600519_daily.parquet")
|
||||
4. 按 start/end 过滤日期
|
||||
5. 返回 DataFrame
|
||||
```
|
||||
|
||||
### 张飞回测对接
|
||||
|
||||
```
|
||||
# 改前(张飞直接读CSV,硬编码路径)
|
||||
df = pd.read_csv("/path/to/data.csv")
|
||||
|
||||
# 改后(通过 DataCatalog)
|
||||
from data_platform import DataCatalog
|
||||
catalog = DataCatalog()
|
||||
df = catalog.get_daily("000001", "2024-01-01", "2025-12-31")
|
||||
```
|
||||
|
||||
### vnpy适配器对接
|
||||
|
||||
```python
|
||||
# 改前(姜维硬编码路径)
|
||||
ZHAOYUN_DATA_BASE = "/Users/chufeng/nas/stock/sanguo_vnpy/zhaoyun-data/data"
|
||||
|
||||
# 改后(读取 DataCatalog 配置)
|
||||
from data_platform.config import load_config
|
||||
config = load_config()
|
||||
ZHAOYUN_DATA_BASE = config["data_root"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、权衡取舍
|
||||
|
||||
| 决策 | 选择 | 理由 |
|
||||
|------|------|------|
|
||||
| 新建独立包 vs 项目内模块 | **项目内模块** | 代码量小(~200行),不值得独立包 |
|
||||
| YAML配置 vs JSON | **YAML** | 支持注释,可读性好 |
|
||||
| Parquet vs CSV | **Parquet(保持现状)** | 已有数据都是Parquet,不改格式 |
|
||||
| 环境变量 vs 配置文件 | **环境变量优先+配置文件兜底** | 生产环境用环境变量,开发用配置文件 |
|
||||
| 全量加载 vs 按需加载 | **按需加载(按symbol+日期范围)** | 避免内存浪费 |
|
||||
| fallback akshare | **保留但默认关闭** | 策略开发者应先确认本地数据完备 |
|
||||
|
||||
---
|
||||
|
||||
## 六、待澄清项
|
||||
|
||||
| # | 问题 | 影响范围 |
|
||||
|---|------|---------|
|
||||
| Q1 | `raw/a_stock_daily/` 和 `raw/daily/` 是否有重叠?哪个是主数据? | catalog.py 的路径配置 |
|
||||
| Q2 | 财务数据除了 valuation 还有其他类型吗(income/balance/cashflow)? | get_financial 接口设计 |
|
||||
| Q3 | 分钟线数据是否纳入本次 DataCatalog? | 是否实现 get_minute() |
|
||||
| Q4 | NAS 路径 `/Users/chufeng/nas/stock/` 当前是否可用? | vnpy适配器是否能正常工作 |
|
||||
|
||||
---
|
||||
|
||||
## 七、各角色分工
|
||||
|
||||
| 角色 | 任务 | 交付物 |
|
||||
|------|------|--------|
|
||||
| 赵云 | Q1-Q3 澄清 + 数据目录确认 + 更新SOP | 数据目录说明 + 更新脚本 |
|
||||
| 张飞 | 回测框架对接 DataCatalog | 修改后的回测代码 |
|
||||
| 关羽 | 风控数据接口验证 | 风控相关数据接口测试 |
|
||||
| 姜维 | config.py + catalog.py 实现 + vnpy适配器更新 + 回测环境文档 | 代码 + 文档 |
|
||||
| 司马懿 | 架构评审 | 评审意见 |
|
||||
| 庞统 | 整合交付 | 最终报告 |
|
||||
|
||||
---
|
||||
|
||||
## 八、不做的事
|
||||
|
||||
1. ❌ 不建数据库
|
||||
2. ❌ 不建独立 pip 包
|
||||
3. ❌ 不做实时行情
|
||||
4. ❌ 不做 Web UI
|
||||
5. ❌ 不做云端部署
|
||||
6. ❌ 不改 vnpy 核心代码
|
||||
Reference in New Issue
Block a user