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

6.1 KiB
Raw Blame History

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 模式入口
    • envSTOCK_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.pySTOCK_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

launchctl load   ~/Library/LaunchAgents/com.sanguo.data-update.plist
launchctl unload ~/Library/LaunchAgents/com.sanguo.data-update.plist
launchctl list | grep sanguo.data-update

为何不用 crontabmacOS 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 限频 ≈ 数小时,夜间)+ 推。

手动触发补全:

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.080 跳变 CLEAN,撮合成交价 9.71–10.25 真实

接口(双目录路由)

  • datareader.read_parquet_daily(dir_key="...")dir_key 切换 daily_dir/raw_dir
  • data_source.iter_bars(adjust="raw")raw_diradjust="qfq"daily_dirraw 缺 raw_dir 报错(不 fallback,防混源)
  • engine.PaperEngine(adjust="raw") 默认 raw(撮合+信号共用真实价)

简化决策(单 raw,除权留分期项)

原 spec 双源(撮合 raw + 策略 qfq)。Linus 三问简化为单 raw:除权缺口对 MA 信号影响低频(年 1-2 次),「分红除权」已列分期项 #3。双源/除权合并进分期项。

daily_dir 后续

daily_dirmixed)暂保留给 backtestPhase 2),后续迁 raw_dirdaily_all_update.pyadjustflag="2" 在 Mac 无 baostock 时是死代码,实走 akshare raw fallback。