Files
claude_dev c3e53fbef3 docs(data): 归档数据层验证产物 + 数据层总览README
- scripts/data_platform/_archive/legacy/: 归档20个独立探针/诊断/旧降级脚本(零引用验证)
- docs/archive/data/: 归档17个数据相关旧设计/plan/report(保留fusion spec作深读)
- docs/data-platform/README.md: 数据层单一权威记录(8节:架构/布局/源/管线/铁律/API/缺口/待办)
- 删除 _mootdx_depth_result.txt
- Phase2待办: 15m灌库链+旧回填import链(有测试/wrapper依赖,VPS schtask确认后归档)
2026-07-29 10:11:38 +08:00

9.1 KiB
Raw Permalink Blame History

15min 数据层设计文档

项目: sanguo_vnpy_v2 数据层 日期: 2026-07-122026-07-0810 审计+回填后落地) 范围: A 股 15 分钟 K 线数据层(数据源、覆盖现状、脚本、刷新机制、硬约束、已知问题) 相关文档: docs/data-platform/daily-update-design.md(日线+15min+vNpy DB 早期多源架构 v1v3,本文件聚焦 15min 最终落地的实现)


一、数据源

用途 协议 特点
新浪财经 15min API 主源·增量刷新 HTTP datalen=800(≈2.5 个月)/ 次,有真实 amount,不复权,无法回填历史
腾讯 minute/query + 聚合 备源·仅当天 HTTP sina 失败时用,拉 1min 聚合成 15min
baostock 历史回填 TCP adjustflag=3 不复权,2024-01-01 起,0.4s/票,单连接,不支持 BSE

1.1 新浪 15min API(主源)

  • URL: https://quotes.sina.cn/cn/api/jsonp_v2.php/.../CN_MarketDataService.getKLineData?symbol={symbol}&scale=15&ma=no&datalen=800
  • datalen 最大有效值 800(超过返回 null),即 15min ≈ 2.5 个月
  • 字段: day, open, high, low, close, volume, amountamount 为真实成交额
  • 时间戳为 end-of-bar 格式(09:45, 10:00 ...
  • 返回 JSONP,需正则提取 JSON 数组
  • 不复权,无法指定起始日期 → 只能增量刷新最近 2.5 月,不能回填更早历史

1.2 腾讯 minute/query(备源)

  • URL: http://web.ifzq.gtimg.cn/appstock/app/minute/query?code={symbol}
  • 仅返回当天 1min 数据,聚合为 15min_aggregate_1m_to_15m
  • 仅在 sina 主源失败时兜底

1.3 baostock(历史回填)

  • query_history_k_data_plusadjustflag="3"(不复权,与 sina 主源一致)
  • 起点 2024-01-01,可按日期范围全量拉取
  • 0.4s/票,单连接(并发会崩),每 400 票 relogin 防断会话
  • 不支持 BSE(北交所 920xxx

1.4 源降级链(15min

增量刷新(每日 15:30 cron:
  sina 15min(主,800 条/次)→ 腾讯 minute/query(备,仅当天)

历史回填(一次性):
  baostock adjustflag=3(全量历史,2024-01-01 起,不含 BSE

二、覆盖现状(2026-07-12 审计+回填后)

维度 数值
全市场 universe 5493
主板 SH/SZ 覆盖 5193 = 5023 老股(≥2.5 年,sina 长期累积)+ 170 新股(baostock 回填至上市日)
BSE 北交所缺口 300baostock + sina 均不支持,待 akshare/腾讯另接)
15min 主目录文件数 5403
数据新鲜度 2026-07-08 ~ 2026-07-10

2.1 数据深度

股票类型 深度 起点
成熟股(5023 只) ≈ 2.5 年 2024-01-01sina 长期累积 + baostock 回填)
新股(170 只) = 上市日 baostock 回填至各自上市日
5 年深度扩展(未来) 2.5yr → 5yr baostock 从 2020 起回填(大工程,未来阶段)

2.2 BSE 缺口说明

  • 300 只北交所股票(920xxxbaostock 和 sina 均不支持
  • 多为小盘新股,多数策略可剔除
  • 待后续用 akshare / 腾讯另接(东财接口有封 IP 风险,建议按需)

三、脚本清单(scripts/data_platform/

脚本 作用 关键点
download_minute.py sina 增量刷新 STOCK_ROOT 环境变量参数化(默认 /Volumes/stockNAS 用 /volume1/stock);0.3s/票单线程;断点续传 download_progress.json--scope all/hs300--codes--resume
backfill_15min_baostock.py baostock 历史回填 全量重建 + 备份 backup_sina/adjustflag=30.4s/票;marker 防重;每 400 票 relogin
refresh_15min_daily.py(新) cron 入口 pop 代理直连;交易日判断(周末短路 + baostock query_trade_dates);调 download_minute --scope all --resume;日志 $STOCK_ROOT/logs/daily_update/

3.1 download_minute.py 关键参数

参数 值 / 说明
STOCK_ROOT os.environ.get("STOCK_ROOT", "/Volumes/stock")line 47
OUTPUT_DIR $STOCK_ROOT/minute_kline/15min
REQUEST_INTERVAL 0.3s
MAX_RETRIES 3
连续失败暂停 5 次连续失败 → 暂停 60s
写入策略 增量合并:concat + drop_duplicates(subset=["day"], keep="last") + 原子写 .tmprename

3.2 backfill_15min_baostock.py 关键参数

参数 值 / 说明
NAS_ROOT 硬编码 /Volumes/stockline 43待参数化
adjustflag "3"(不复权,line 131
RELOGIN_EVERY 400 祒(line 268
防重 marker .{stem}.baostock 空文件(line 98/208
旧数据备份 $MINUTE_15_DIR/backup_sina/

3.3 refresh_15min_daily.py 职责

  1. pop 全部代理环境变量(http_proxy/https_proxy/...)保证直连
  2. 交易日判断:周末短路;工作日用 baostock query_trade_dates,失败降级为"默认交易日"
  3. 交易日 → subprocessdownload_minute.py --scope all --resume,继承 STOCK_ROOT
  4. 日志写 $STOCK_ROOT/logs/daily_update/refresh_15min_YYYYMMDD.log

四、刷新机制(本次新落地)

4.1 调度

  • NAS Synology 任务计划,每交易日 15:30A 股 15:00 收盘后半小时)
  • 之前无任何自动刷新(crontab / Synology / 容器 cron 全空),7-08~10 的数据新鲜是手动跑的;本次补 cron

4.2 执行命令

容器 sanguo_vnpy_v2 bind-mount /volume1/stock,路径在容器内不变:

docker exec sanguo_vnpy_v2 bash -c "cd /app && python3 scripts/data_platform/refresh_15min_daily.py"

4.3 交易日判断

  • 周末(weekday ≥ 5)→ 直接跳过
  • 工作日 → baostock query_trade_dates 查节假日
  • baostock 不可用 → 降级为"工作日默认交易日"(非交易日跑也只是全部 skip,幂等)

五、硬约束

来源:CLAUDE.md 全局约定 + 数据下载经验(见 MEMORY.md

约束 说明 实现
直连不走代理 避免被识别为异常流量 / akshare 代理污染 脚本入口 pop http_proxy/https_proxy/...download_minute._make_opener()ProxyHandler({})
单线程限速,0 并发 baostock 单连接并发会崩;新浪猛打封 IP sina 0.3s/票,baostock 0.4s/票,无并发
间隔别太大 baostock 长空闲断会话 sina 0.3s / baostock 0.4s
NAS 内存紧 swap 近满,分块+断点续传,别全市场并发 历史踩过 macOS Jetsam 崩溃(见 MEMORY 数据下载崩溃教训)
见空就停 连续 5 空 = 会话掉了 MAX_CONSECUTIVE_FAILS=5 → 暂停 60s

六、路径映射表(Mac / NAS / 容器 三端)

STOCK_ROOT 15min 目录
Mac 开发 /Volumes/stockNAS 挂载) /Volumes/stock/minute_kline/15min
NAS host /volume1/stock /volume1/stock/minute_kline/15min
容器 sanguo_vnpy_v2 /volume1/stockbind-mount 同 NAS

对应 config/data_platform.yaml 路径键:minute_15_dir: /volume1/stock/minute_kline/15min(容器/NAS 视角)。脚本通过 STOCK_ROOT 环境变量切换,不写死。


七、已知问题 / 后续

优先级 问题 说明 处理
HIGH bug download_minute.py _aggregate_1m_to_15mamount=("amount","last") 应为 "sum" 腾讯备源路径 amount 聚合错误(sina 主源不受影响) 待修(line 147
MEDIUM BSE 920 缺口 300 只 baostock + sina 均不支持 待 akshare/腾讯另接(东财有封 IP 风险,建议按需)
LOW 5 年深度扩展(5023 老股 2.5yr → 5yr baostock 从 2020 起回填,大工程 未来阶段
LOW backfill_15min_baostock.pyNAS_ROOT 仍硬编码 /Volumes/stock Mac 视角写死,NAS 跑需手改 建议后续也参数化为 STOCK_ROOT

八、相关文件索引

文件 路径 说明
15min 主目录 $STOCK_ROOT/minute_kline/15min/ 5403 个 _15min.parquet 文件
断点续传进度 $STOCK_ROOT/minute_kline/15min/download_progress.json download_minute.py --resume
审计清单 /volume1/stock/minute_kline/15min/backfill_target.json 470 个回填目标
回填进度 /volume1/stock/minute_kline/15min/backfill_470_progress.json done=170, bse_unsupported=300
旧文件备份 /volume1/stock/minute_kline/15min/backup_sina/ baostock 全量重建前的 sina 旧数据
日刷新日志 $STOCK_ROOT/logs/daily_update/refresh_15min_YYYYMMDD.log cron 每日产出
配置 config/data_platform.yaml minute_15_dir 路径键
配置加载 sanguo_data/config.py DataConfig.data_paths["minute_15_dir"]

变更记录

日期 变更 作者
2026-07-12 初始版本:15min 数据层落地后真实数据(5493 universe / 5193 覆盖 / 300 BSE 缺口 / cron 15:30 / sina主源+baostock回填) 文档 Sub Agent