Files
sanguo_vnpy_v2/docs/deployment/data-download.md
T
claude_dev 1ed7b72aca feat(data): raw真实价数据源(task#79)—raw_dir+dir_key路由+新浪源重下
根因: daily_dir mixed-adjust(hfq bulk+akshare raw tail)致3-30 -94%假跌。
方案(Linus三问简化单raw, 除权留分期项#3):
- datareader read_parquet_daily/15min 加 dir_key 参数
- data_source iter_bars/fetch_day: adjust=raw→raw_dir(缺配置报错防混源), qfq→daily_dir
- engine PaperEngine 默认 adjust=raw
- config 加 raw_dir; scripts/raw_redownload.py 新浪源adjust='' 直连+单线程限速
- 验证: 浦发606行close 6.5/14.6 mean10.08 0跳变, 撮合成交价9.71-10.25真实
- 测试9/9+trader全量108/108通过
2026-07-07 22:19:11 +08:00

113 lines
6.1 KiB
Markdown
Raw 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 维护)
> 维护:Main Agent · 2026-07-07
> v1 数据下载脚本(`~/.openclaw/sanguo_projects/sanguo_vnpy/data_platform/`)移植到 v2
> 改 SSH 模式(免 SMB 挂载/密码/macFUSE),Mac launchd 定时(替代 crontab)。
## 架构
```
Mac Mini(常开)
launchd 每日 15:30
→ run_daily_update.sh
1. rsync 拉 NAS 现有 → Mac 本地(/tmp/stock_dl,增量;首次慢后续快)
2. 跑 v1 daily_all_update.py(多源 fallback + 增量 + 失败率熔断)
3. rsync 推 本地 → NAS/volume1/stock
↕ SSH key 免密(sanguo-nas,不依赖 SMB 挂载/密码)
NAS /volume1/stock(日线/15min parquet + vnpy DB
```
不挂载、不要密码、不装 macFUSE,用 `sanguo-nas` SSH key`~/.ssh/config`)。
## 脚本(`v2/scripts/data_platform/`
从 v1 `data_platform/` 复制(11 个脚本)。关键改动:
- **`daily_all_update.py`** — v1 全市场增量(日线 + 15min,多源 fallback:东财 4s + BaoStock + 腾讯,失败率熔断 >80% 终止)
- `STOCK_MOUNT` env:路径根(默认 `~/stock_mount` SMB 挂载点;SSH 模式包装脚本设 `/tmp/stock_dl`
- `STOCK_LIMIT` env:限制股票数(前 N,**验证用**,默认 0=全市场)
- **`run_daily_update.sh`** — 包装(rsync 拉 + v1 + 推),SSH 模式入口
- env`STOCK_LIMIT=N` / `SKIP_PULL=1`(验证跳过拉)
### 完整脚本清单(`v2/scripts/data_platform/`
| 脚本 | 用途 | 用法 |
|------|------|------|
| `run_daily_update.sh` | **SSH 模式入口**rsync 拉+v1+推)| `./run_daily_update.sh [--skip-daily\|--skip-15min]` |
| `daily_all_update.py` | **全市场每日增量**(日线+15min,多源 fallback+熔断)| `python3 daily_all_update.py``STOCK_MOUNT`/`STOCK_LIMIT` env|
| `backfill_15min_baostock.py` | BaoStock 全量重建 15min 历史(`adjustflag=3` **raw**| 手动回补,按需 |
| `download_minute.py` | 15min 下载(HS300 子集等)| 按需 |
| `fallback.py` | 多源降级管理器(日线 akshare→腾讯 / 实时 新浪→东财→腾讯)| 被主脚本调用 |
| `realtime.py` | 实时行情三源降级 | 盘中按需 |
| `updater.py` | vnpy DB 增量更新(腾讯主源)| 被主脚本调用 |
| `validator.py` | 数据校验(7 条 fatal 规则)| 校验按需 |
| `import_vnpy_daily.py` / `import_vnpy_daily_fast.py` | vnpy DB 日线导入 | 迁移按需 |
| `import_vnpy_minute.py` | vnpy DB 分钟导入 | 迁移按需 |
> **主入口**`run_daily_update.sh`(定时/手动)。其他脚本是组件或按需工具。
> v1 调研文档(需求/设计/总结)已复制到 `v2/docs/data-platform/` 供参考。
## 定时(launchd,替代 crontab
`~/Library/LaunchAgents/com.sanguo.data-update.plist` — 每日 15:30 跑 `run_daily_update.sh`
```bash
launchctl load ~/Library/LaunchAgents/com.sanguo.data-update.plist
launchctl unload ~/Library/LaunchAgents/com.sanguo.data-update.plist
launchctl list | grep sanguo.data-update
```
**为何不用 crontab**macOS crontab 写(`crontab file`)需 Full Disk AccessClaude/终端无 FDA 时写操作卡死(读 OK)。launchd 用户级 plist`~/Library/LaunchAgents/`)不需 FDA,更稳。Mac 原生推荐方式。
## 验证(2026-07-07
```
STOCK_LIMIT=2 STOCK_MOUNT=/tmp/stock_dl_test python3 daily_all_update.py --skip-15min
→ updated: 2, records: 2406-19~07-07),000001 拉到 2026-07-07(今天),21.8s ✅
```
增量逻辑:v1 读本地现有 parquet 最后日期(`get_daily_last_date`)→ 拉 last+1 ~ 今天。**本地必须有现有 parquet**(rsync 拉或之前数据),否则 skip。
## v1 crontab 取消
v1 crontab `30 15 * * 1-5 .../sanguo_vnpy/data_platform/daily_update.sh` 取消——用 v2 launchd 替代。
> macOS crontab 写卡(FDA),`crontab -e` 手动去那行,或给终端 Full Disk Access。
v1 crontab 若残留无害(v1 脚本跑时 NAS 未挂载会 `ERROR: NAS未挂载,跳过更新`)。
## 全市场补全(首次)
`run_daily_update.sh` 首次跑:rsync 拉全市场现有(5264 parquet,几分钟)+ v1 增量(全市场 × 东财 4s 限频 ≈ 数小时,夜间)+ 推。
手动触发补全:
```bash
cd v2/scripts/data_platform
./run_daily_update.sh # 全量(日线+15min),夜间跑
./run_daily_update.sh --skip-15min # 只日线
```
## raw 真实价数据源(task #79,已实现)
### 根因:daily_dir mixed-adjust 污染
`daily_dir``/volume1/stock/A股数据/日线数据/daily`)历史数据是 **mixed-adjust**
- 历史 bulk = 早期遗留 **hfq**(浦发 ~196 元)
- 近期增量 = akshare **raw** tail(浦发 ~10 元),因 Mac 无 baostock、`adjustflag="2"` 是死代码
- 同一 parquet 半截 hfq 半截 raw → 3-30 单日 **-94% 假跌** → 撮合出垃圾结果(假跌停/假低价)
### raw_dir 通路(干净单一 raw
新建 `raw_dir``/volume1/stock/A股数据/日线数据/raw`),akshare 新浪源 `adjust=""` 从头重下:
- `scripts/data_platform/raw_redownload.py`**直连**unset proxy+ **单线程 SLEEP 限速**(防封 IP+ 新浪源 `stock_zh_a_daily`
- 文件名与 daily_dir 同构(`{prefix}{symbol}_daily.parquet`,按 year 分目录),datareader 直读
- 验证(2026-07-07):浦发 606 行 close 6.5/14.6/mean 10.08**0 跳变 CLEAN**,撮合成交价 9.7110.25 真实
### 接口(双目录路由)
- `datareader.read_parquet_daily(dir_key="...")`dir_key 切换 `daily_dir`/`raw_dir`
- `data_source.iter_bars(adjust="raw")``raw_dir``adjust="qfq"``daily_dir`raw 缺 raw_dir **报错**(不 fallback,防混源)
- `engine.PaperEngine(adjust="raw")` 默认 raw(撮合+信号共用真实价)
### 简化决策(单 raw,除权留分期项)
原 spec 双源(撮合 raw + 策略 qfq)。Linus 三问简化为**单 raw**:除权缺口对 MA 信号影响低频(年 1-2 次),「分红除权」已列分期项 #3。双源/除权合并进分期项。
### daily_dir 后续
`daily_dir`mixed)暂保留给 backtestPhase 2),后续迁 `raw_dir``daily_all_update.py``adjustflag="2"` 在 Mac 无 baostock 时是死代码,实走 akshare raw fallback。