# P3 需求规格文档：分钟线数据下载与导入

**任务ID**: data-platform-p3-20260502
**节点**: pangtong_requirements
**作者**: 庞统（副军师）
**日期**: 2026-05-02

---

## 一、背景

### 1.1 已完成的前置工作

| 项 | 状态 | 证据 |
|----|------|------|
| P1 vnpy数据通路 | ✅ 完成 | 5191只日线，1281万行，回测验证通过 |
| P0 腾讯限频验证 | ✅ 通过 | 100只100%成功，0.19秒/请求，无封禁 |
| vnpy DB Schema | ✅ 已知 | DbBarData表，interval字段：d=日线，1m=1分钟 |
| 已有分钟线数据 | ⚠️ 84只 | `/Volumes/stock/minute_kline/15min/sz{code}_15min.parquet` |

### 1.2 已有分钟线数据格式

**文件名**：`sz000001_15min.parquet`
**字段**：day, open, high, low, close, volume, amount（7列）
**日期范围**：2025-09-17 ~ 2026-03-27（约1970条/只）
**字段类型**：day=object, open/high/low/close=float64, volume/amount=object

### 1.3 vnpy DB分钟线interval值

根据P1赵云确认：`1m` = 1分钟线。**15分钟线的interval值需在编码阶段确认**（可能是 `15m` 或其他值）。

### 1.4 腾讯mkline API

唯一可用的分钟线数据源（akshare `stock_zh_a_minute()` 已失效）。
- 限频：100只连续请求无限制，全市场预估17分钟
- 需确认API的请求格式、返回格式、单次返回的历史数据长度

---

## 二、功能需求

### P3-1：下载脚本 `download_minute.py`

| 项 | 说明 |
|-----|------|
| 需求 | 从腾讯mkline API下载15分钟线数据 |
| 数据源 | 腾讯财经mkline API（唯一可用源） |
| 存储格式 | Parquet，与已有84只保持一致（day,open,high,low,close,volume,amount） |
| 存储路径 | `/Volumes/stock/minute_kline/15min/{code}_15min.parquet` |
| 文件名格式 | `sz000001_15min.parquet` 或 `sh600000_15min.parquet` |

**功能要求**：
1. 支持指定股票列表（HS300 / 全市场）
2. 支持增量下载（已有数据只追加新部分）
3. 断点续传（记录已下载到哪只）
4. 限频保护（如遇封禁自动等待重试，最大重试次数限制）
5. 下载日志（成功/失败/跳过/耗时）
6. 对已有84只文件做增量更新而非覆盖

**输出**：
- 下载报告（成功数、失败数、总耗时、总数据量）

### P3-2：HS300 15分钟线全量下载

| 项 | 说明 |
|-----|------|
| 需求 | 下载HS300成分股的15分钟线 |
| 股票数 | ~300只 |
| 预估耗时 | ~1分钟（基于P0验证：0.19秒/只） |
| 预估存储 | ~1.2GB（300只 × ~4MB/只） |

### P3-3：全市场15分钟线下载

| 项 | 说明 |
|-----|------|
| 需求 | 下载全市场A股15分钟线 |
| 股票数 | ~5500只 |
| 预估耗时 | ~17分钟 |
| 预估存储 | ~22GB |
| 前置 | P3-2验证无问题 |

### P3-4：分钟线导入vnpy DB `import_vnpy_minute.py`

| 项 | 说明 |
|-----|------|
| 需求 | 将15分钟线Parquet导入vnpy SQLite DB |
| 输入 | `/Volumes/stock/minute_kline/15min/{code}_15min.parquet` |
| 输出 | quant_trading.db 新增分钟线数据（interval ≠ 'd'） |
| 约束 | 复用P1的导入逻辑（pandas向量化+批量INSERT OR REPLACE） |

**关键映射**：

| Parquet字段 | DB字段 | 转换规则 |
|------------|--------|---------|
| day | datetime | 直接使用（已是 "YYYY-MM-DD HH:MM:SS" 格式） |
| open | open_price | 直接映射 |
| high | high_price | 直接映射 |
| low | low_price | 直接映射 |
| close | close_price | 直接映射 |
| volume | volume | float转换 |
| amount | turnover | float转换 |
| 文件名前缀 | symbol+exchange | sz→SZSE, sh→SSE |
| 固定值 | interval | **待确认**（可能为 "15m"） |
| 固定值 | open_interest | 0.0 |

**SMB锁库问题**：同P1，先写 `/tmp/` 再复制到NAS。或在本地操作DB后整体替换。

---

## 三、交付物清单

### 代码文件（`~/.openclaw/sanguo_projects/sanguo_vnpy/data_platform/`）

| 文件 | 功能 | 预估行数 |
|------|------|---------|
| `download_minute.py` | 腾讯mkline下载+增量+断点续传 | ~200 |
| `import_vnpy_minute.py` | Parquet→vnpy DB导入 | ~150（复用P1逻辑） |

### 数据文件

| 产物 | 位置 | 预估大小 |
|------|------|---------|
| HS300 15分钟线Parquet | `/Volumes/stock/minute_kline/15min/` | ~1.2GB |
| 全市场15分钟线Parquet | `/Volumes/stock/minute_kline/15min/` | ~22GB |
| vnpy DB（增量） | `/Volumes/stock/sanguo_vnpy/data/quant_trading.db` | 增加~2GB |

### 报告

| 文件 | 内容 |
|------|------|
| 下载报告 | 成功/失败/耗时统计 |
| 导入报告 | 记录数/字段校验结果 |

---

## 四、假设与不确定项

| # | 不确定项 | 影响 | 验证方式 |
|---|---------|------|---------|
| 1 | 腾讯mkline API的具体请求/返回格式 | 下载脚本实现 | 赵云编码时实测 |
| 2 | vnpy 15分钟线的interval值 | 导入脚本实现 | 查vnpy源码或实测 |
| 3 | 腾讯API单次返回的历史数据长度（是否支持获取全量历史） | 全量下载策略 | P3-1实测 |
| 4 | SMB写入大量小文件的性能 | 下载耗时 | 实测 |
| 5 | DB导入分钟线后的总大小和对查询性能影响 | 回测性能 | P3-4后验证 |
| 6 | 已有84只Parquet的字段格式与新下载是否一致 | 数据一致性 | 编码时对比 |

---

## 五、约束

1. 产出放到 `~/.openclaw/sanguo_projects/sanguo_vnpy/data_platform/`
2. 不引新依赖
3. 15分钟线优先，1分钟线暂缓
4. 腾讯API是唯一数据源
5. 遇阻塞用最大尝试轮数限制
6. 先输出设计方案经评审再编码
7. 与已有84只Parquet格式保持一致

---

## 六、成功标准

| # | 标准 | 验证方法 |
|---|------|---------|
| 1 | HS300 300只15分钟线下载完成 | 检查文件数和数据完整性 |
| 2 | 全市场5500只下载完成 | 检查文件数和总大小 |
| 3 | 分钟线成功导入vnpy DB | DB中有interval≠'d'的记录 |
| 4 | 已有84只数据增量更新无覆盖 | 对比更新前后首条记录 |
| 5 | 断点续传有效 | 中断后重启继续 |
