# 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 Access,Claude/终端无 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: 24(06-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.71–10.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)暂保留给 backtest(Phase 2),后续迁 `raw_dir`。`daily_all_update.py` 的 `adjustflag="2"` 在 Mac 无 baostock 时是死代码,实走 akshare raw fallback。