Files
sanguo_vnpy_v2/docs/superpowers/specs/2026-07-21-data-source-fusion-design.md
T

632 lines
45 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 股多数据源融合层设计
> 日期:2026-07-21 创建 | 基于 brainstorming + 4 源全能力调查(akshare / baostock / miniQMT / csindex)
> **状态:活文档(唯一数据设计文档)** —— 2026-09-02 起用户钦定:本文件是数据架构唯一权威设计,
> 每次数据架构变更必须同批更新到最新状态;演进采用「日期节追加,新节覆盖旧节相关决策」模式。
> 最后更新:2026-09-02(A 档截面数据域全量上生产,§15;使用层 provider 接口,§16;首夜巡查修正,§17)
---
## 1. 背景与痛点
多数据源(akshare / baostock / xtdata / miniQMT)各不全,整合时格式有偏差:
- **symbol 格式**:`600519` vs `sh.600000` vs `600519.SH`
- **exchange 命名**:`SSE` vs `SH`
- **复权口径**:raw vs qfq
- **volume 单位**:xtdata÷100 vs 原值
- **价格源间漂移**:同股同日不同源 close 微差
### 用户约束(明确)
- ❌ 不要查询时网络源切换(源变化/限流不可控)
- ✅ VPS 本地一份稳定数据,日常只读本地
- ✅ 网络源只用于「采集时拼凑完整本地」
- ✅ 使用层无感(本地缺才网络兜底,罕见)
- ✅ 优先 miniQMT + baostock
---
## 2. 设计原则(三层)
| 层 | 职责 | 原则 |
|---|---|---|
| **采集层** | 多网络源 → 拼凑完整本地 | 各源 adapter + 定时 schtask;源不可控隔离在采集(失败重试,不影响使用层) |
| **数据层** | 整理(重叠定权威,特定保留) | **不强合物理表**(vnpy 回归风险);每类定权威源(优先 baostock+miniqmt) |
| **使用层** | `LocalUnifiedProvider` 逻辑融合 | 读权威表 + 归一化 + 本地缺网络兜底;策略无感 |
**核心**:网络源不稳的风险只影响采集层(定时跑、可重试),使用层永远读本地 —— 风险隔离。
---
## 3. 数据源全能力盘点(综合调查)
### 3.1 已下(稳定源)
| 表/源 | 内容 | 范围 | 增量 |
|---|---|---|---|
| `dbbardata` | 日线+5m/15m(xtdata/akshare/baostock) | 日线2010+/分钟2020+ | ✅ 16:30 |
| `daily_baostock_full` | 日线 18 字段(pe/pb/turn/pctChg) | 19902026 | 待 #7 |
| `bs_index_constituent` | 成份股 300/500/50(含退市) | 2006+ | 待增量 |
| `bs_adjust_factor` | 复权因子 | 全史 | 待增量 |
| akshare 静态表 | 三表/估值/北向/龙虎榜/融资融券/股本/解禁/业绩预告 | - | 部分增量 |
| miniQMT xtdata | 日线+5m/15m 全周期(实时 T+0,零漂移) | 16年 | 按需 |
| miniQMT PershareIndex | ROE/毛利率/EPS | 季频 | 按需 |
| parquet | data/raw、daily_baostock、minute_5/15、static/index_const、qfq+raw ETF(5只) | - | 部分 |
### 3.2 重叠(5 处)
1. 日线 OHLCV:dbbardata ∩ daily_baostock_full ∩ parquet raw(三处)
2. 估值 PE/PB:akshare valuation ∩ daily_baostock_full(peTTM/pbMRQ)
3. 15min:dbbardata ∩ parquet minute_15
4. 基本面:akshare 三表 ∩ miniQMT PershareIndex ∩ baostock 季频
5. 成份股:bs_index_constituent ∩ parquet index_const
### 3.3 新发现缺口(本次调查)
- **ETF 全市场日线**(现仅 5 只,策略资产类别缺口)
- **深证/中证历史成份股**(治幸存者偏差,当前仅最新快照 = latent bug)
- **退市股 K 线**(baostock 有,从未提取;反幸存者偏差核心)
- 申万行业 SW1/2/3 + 历史变动
- 龙虎榜 / 合约信息(涨跌停/ST)/ 可转债 / 研报一致预期 / 股东户数 / 除权明细
---
## 4. 权威源地图(数据层整理)
| 数据类 | 权威源 | 物理存储 | 重叠处理 / 备注 |
|---|---|---|---|
| 日线 OHLCV(个股,历史) | **baostock** | `daily_baostock_full` | dbbardata 日线保留(vnpy 回测硬依赖);parquet raw 冗余 |
| 日线(盘中实时) | **miniQMT xtdata** | xtdata API | 独有(T+0 实时) |
| **日线 ETF(全市场)** | **miniQMT xtdata** | parquet/dbbardata | universe 加 `沪深ETF∪沪深基金`,`dividend_type='front'` 自动复权 |
| 估值 PE/PB/turn | **baostock** | `daily_baostock_full` | akshare valuation 兜底/校验 |
| 基本面指标 ROE/毛利率 | **miniQMT PershareIndex** | miniQMT API | akshare 三表补原始报表 |
| 基本面三表(原始) | akshare | akshare 表 | miniQMT Balance/Income/CashFlow + baostock 季频交叉 |
| 15min | **baostock** | `dbbardata` | parquet minute_15 冗余可清 |
| 成份股 300/500/50(含退市) | **baostock** | `bs_index_constituent` | `query_*_stocks(date)` 任意时点 |
| **成份股 深证/国证(399xxx)** | **akshare(国证源)** | parquet | `index_detail_hist_cni` + `index_detail_hist_adjust_cni` |
| **成份股 中证1000/2000(000852/932000)** | **新浪** | parquet | `vII_HistoryComponent`(gb2312,含退市) |
| **退市股 K 线** | **baostock** | `daily_baostock_full` | `query_all_stock` status=0 + `query_stock_basic` 退市日期 + 逐只 K |
| 复权因子 | **baostock** | `bs_adjust_factor` | 独有 |
| 申万行业 SW1/2/3 | **miniQMT xtdata** | parquet | `get_sector_list` + `get_stock_list_in_sector`;akshare 补历史变动 |
| 龙虎榜 | **miniQMT xtdata** | parquet | `get_longhubang`;akshare 兜底 |
| 合约信息(涨跌停/ST/上市日) | **miniQMT xtdata** | parquet | `get_instrument_detail` 全 A 一入库 |
| 可转债 | akshare | parquet | `bond_zh_hs_cov_min` + `bond_cb_adj_logs_jsl`(转股价) |
| 研报/一致预期 EPS | akshare | parquet | `stock_research_info_em` |
| 股东户数 | miniQMT/akshare | parquet | `Holdernum` 表 / `stock_zh_a_gdhs_detail` |
| 除权明细 | miniQMT xtdata | parquet | `get_divid_factors` |
| 龙虎榜/北向/融资融券/解禁 | akshare | akshare 表 | 独有(保留) |
---
## 5. 归一化规则
| 维度 | 统一标准 | 源映射 |
|---|---|---|
| symbol | `600519.SH`(数字+交易所后缀) | baostock `sh.600000``600000.SH`;dbbardata 纯数字+exchange 字段 |
| exchange | `SH`/`SZ` | dbbardata `SSE`/`SZSE``SH`/`SZ` |
| 日期 | ISO `2026-07-21` | 各源统一 |
| 复权 | raw 存储 + `factor` 字段(QLib:`factor=adj/raw`) | 查询时按需 qfq(`$close/$factor`);治 raw/qfq 冲突 |
| volume | 原值(股) | xtdata ÷100 还原 |
| 停牌 | OHLCV 全 NaN | QLib 约定 |
| 溯源 | `source` 字段 | 每行标来源 + 主源/补丁标记 |
---
## 6. 使用层:`LocalUnifiedProvider`(逻辑融合)
**接口**:
```python
get_daily(symbol, start, end, adjust='raw') # 个股日线
get_etf_daily(symbol, ...) # ETF 日线
get_fundamentals(symbol, fields, date) # 财务指标/三表
get_constituent(index, date) # 成份股(含历史,治幸存者偏差)
get_industry(symbol, date) # 申万行业(含历史变动)
get_longhubang(symbol, start, end) # 龙虎榜
get_instrument_detail(symbol) # 涨跌停/ST
get_delisted_kline(...) # 退市股 K 线
```
**职责**:
- 按数据类路由到权威表(§4 地图)
- 归一化(§5 规则):源格式 → 统一 vt_symbol/exchange/复权/单位
- 本地缺 → `network_fetcher` 透明兜底(罕见,如新股未及采集)→ 写本地 → 返回
- `source` 字段溯源;可选多源交叉校验
- 使用层 API 不变,不知数据来自哪个源
**实现**:扩展现有 `sanguo_portfolio/providers/``DataProvider` 接口(BaostockProvider/LocalParquetProvider 已有)。
---
## 7. 增量 schtask 清单
| schtask | 数据 | 源 | 时间 |
|---|---|---|---|
| `sanguo-daily-update`(已有) | 日线+分钟→dbbardata | xtdata | 16:30 |
| `sanguo-bs-daily-increment`(#7 待建) | 日线→daily_baostock_full | baostock | 17:00 |
| `sanguo-etf-daily-increment`(新) | ETF 全市场日线 | xtdata(universe 沪深ETF) | 17:30 |
| `sanguo-akshare-static-increment`(新) | 估值/龙虎榜/三表/北向 | akshare | 18:00 |
| `sanguo-index-hist`(新,半年度) | 历史成份股调样 | akshare 国证 + 新浪 | 调样后(6/12 月) |
| `sanguo-delisted`(新,月度) | 退市股列表+K 线 | baostock | 月初 |
**query 预算守 48000/天/IP**(baostock 硬限):各 baostock schtask 错开 + 日计数器。
---
## 8. 分阶段实现
### P0 — 治幸存者偏差 + 策略核心缺口
1. **历史成份股**:深证/国证(`index_detail_hist_cni`)+ 中证1000/2000(新浪 `vII_HistoryComponent`)+ 300/500/50(baostock 已有)
2. **ETF 全市场日线**:xtdata universe 改 `沪深A股∪沪深ETF∪沪深基金` + `dividend_type='front'`(改 `build_daily_from_xtdata.py:40` + `daily_update_xtdata.py:114`)
3. **退市股 K 线**:baostock `query_all_stock` 筛 status=0 + `query_stock_basic` 退市日期 + 逐只 K → `daily_baostock_full`
### P1 — 策略增强
4. 申万行业 SW1/2/3(xtdata `get_sector_list`)+ 历史变动
5. 龙虎榜(xtdata `get_longhubang`)
6. 合约信息涨跌停/ST(xtdata `get_instrument_detail`)全 A 入库
7. 可转债(akshare `bond_zh_hs_cov_min` + 转股价调整)
8. 研报/一致预期 EPS(akshare `stock_research_info_em`)
### P2 — 按需
9. 股东户数 / 除权明细 / 业绩快报 / 大宗交易 / 宏观 / 期货
### 融合层(贯穿)
10. 归一化库(vt_symbol/exchange/factor/volume 映射)
11. `LocalUnifiedProvider`(读权威表 + 归一化 + 网络兜底)
12. 完整度监控报表(每类覆盖率/缺口,源退化早发现)
---
## 9. 陷阱清单(实证)
- `ak.index_stock_hist` **已下线**(akshare 1.10.37,2024 初)—— 别抄 2022-23 旧博客
- `ak.index_stock_cons` 的"纳入日期"字段有迷惑性 —— 只是当前 300 只各自最初纳入日,不含被剔除,治不了幸存者偏差
- csindex.com.cn 是 Vue SPA —— `requests.get` 拿空壳,官网只当前 Excel 无历史
- 新浪 `fund_etf_hist_sina` **不复权** —— 不适合回测;ETF 复权走 xtdata `dividend_type='front'`
- 东财 `fund_etf_hist_em` **封 IP** —— 单线程限速或避用
- baostock `query_all_stock` 不列退市日期 —— 配合 `query_stock_basic`
- 申万历史板块有变更 —— 回测用当时分类
- `ak.index_detail_cni`(非 hist 版)2025-11-25 起只近期 —— 必须用 hist 版
---
## 10. YAGNI(不做)
- ❌ 不强合物理表(冲突解决/历史一致性/vnpy 回归风险,代价大)
- ❌ 不引 QLib/OpenBB 框架(几百 MB,只摘模式:factor/source/归一)
- ❌ CS 截面归一(中期按需,先解决不全+格式)
- ❌ 实时 tick/盘口(非日终策略才需)
---
## 11. 风险与对策
| 风险 | 对策 |
|---|---|
| vnpy 回测硬读 dbbardata | 不动 dbbardata,provider 层 SSE↔SH 映射 |
| baostock query 预算 48000/天 | 增量 schtask 错开 + 日计数器(#7+day2b 同天 44296<48000) |
| 东财封 IP | 避用东财,优先 baostock/xtdata/新浪/国证 |
| 接口下线(如 index_stock_hist) | 调查实证,不抄旧文 |
| 数据源漂移/幽灵尖峰 | source 溯源 + 涨跌停/量异常校验 |
| 历史成份股缺口致回测幸存者偏差 | P0 优先补(深证+中证1000/2000+退市) |
---
## 12. 实现路径(writing-plans 拆)
- **Phase 1(P0 数据补全)**:历史成份股 + ETF 全市场 + 退市 K 线(3 个采集脚本 + 灌库)
- **Phase 2(融合层)**:归一化库 + `LocalUnifiedProvider`(读现有+新表)
- **Phase 3(P1 增强)**:板块/龙虎榜/合约/可转债/研报
- **Phase 4(运维)**:增量 schtask 全套 + 完整度监控
---
## 13. 开放问题与默认决策(自行决策,你可推翻)
| # | 问题 | 默认(我定) | 备选 | 理由 |
|---|---|---|---|---|
| 1 | exchange 统一格式 | **SH/SZ**(provider 映射 dbbardata SSE→SH) | 保留 SSE/SZSE | baostock/xtdata 都用 SH/SZ,主流;vnpy SSE 在 provider 层映射 |
| 2 | P0 三项优先级 | **全做**(历史成份股 + ETF + 退市 K 线) | 先 ETF(策略即用) | 三项都治幸存者偏差/核心缺口,并行不冲突 |
| 3 | ETF 复权方式 | **xtdata `dividend_type='front'`**(前复权) | raw + factor(精确还原) | 前复权够策略用;raw+factor 中期按需 |
| 4 | 退市股 K 线范围 | **近 5 年退市**(守 baostock 48000/天预算) | 全退市(几千只,慢) | 近 5 年覆盖绝大多数回测;全量可后补 |
| 5 | `LocalUnifiedProvider` 接口 | §6 签名(get_daily/get_etf/get_fundamentals/get_constituent/get_industry/...) | 精简 | 覆盖全天候 + CTA 需求 |
| 6 | 增量 schtask 时间 | 17:00(baostock 日线)/ 17:30(ETF)/ 18:00(akshare 静态) | 调整 | 错开 sanguo-daily-update 16:30 + day2b 02:00 |
| 7 | 物理表 | **不新建统一表**,provider 读现有(dbbardata/daily_baostock_full/各 parquet) | 建 daily_unified | 避免 vnpy 回归 + 数据迁移(§10 YAGNI) |
**默认推进路径**:按以上默认 → spec 定稿 → 转 writing-plans(P0 拆 3 个采集脚本实现计划)。你审 spec 时可推翻任一项,我改。
---
## 14. 方案 A 定稿(2026-07-22 讨论收敛 — 本节为最新,覆盖前文相关决策)
### 14.1 背景
P0 补全 + schtask 部署完成后,审计(`audit_data_layout.py` + `dbbardata_probe.py` 实证)发现「同类多源、多份落地、DB 多表」混乱。讨论收敛为方案 A:**每类数据唯一权威源(允许互补 fallback,禁止并行)、DB 表唯一、估值/三表/事件不进 DB、DB 只放高频随机读取的 K 线+成份股+复权**。
### 14.2 权威源最终分工
| 数据类 | 权威源 | 备注 |
|---|---|---|
| 个股日线 OHLCV(含退市) | **baostock** | raw 真实价 → dbbardata('d') |
| ETF/基金日线 | **xtata** | baostock 盲区(只取 type=1) |
| 个股当天实时(盘后 baostock 未更窗口/盘中) | **xtata** | 拼 baostock 历史,同为 raw |
| 15min | **baostock** | 历史+增量同源 |
| 5min/1min | baostock(暂停) | 战略占位,size 扩容续 |
| 估值 pe/pb/ps/pcf/turn/pctChg/isST | **baostock** | 日线18字段拆出 |
| 基本面三表 | **akshare** | |
| 成份股 300/500/50 | **baostock**(历史) | |
| 成份股 深证 399xxx | **akshare cni**(历史 union) | |
| 成份股 中证1000/2000 | akshare csindex(当前快照) | 历史不可补=永久 gap |
| 复权因子 | **baostock** | 全链路复权基准 |
| 事件类(龙虎榜/大宗/北向/两融/解禁/预告) | **akshare** | |
三大源:xtata(ETF+实时) / baostock(个股日线+估值+15min+复权+300.500.50) / akshare(三表+事件+深证中证成份股)。同类不并行,按标的/字段互补。
### 14.3 DB 边界(只放)
- `dbbardata`:日线('d')+15min('15m')+5min('5m'占位)— **唯一行情表**
- `constituent_unified`:成份股合并唯一表(date,index_code,code,code_name,source)
- `bs_adjust_factor`:复权
- `backtest_stats`:回测(已有)
- **不进 DB**:基本面三表、估值 pe/pb、事件类、回测明细(独立 db)
- **废弃** `daily_baostock_full`(OHLCV→dbbardata,pe/pb→parquet)、`bs_index_constituent`(合入 constituent_unified)
### 14.4 pe/pb 落地:parquet 按年宽表
`data/valuation_baostock/<year>.parquet`,列 `date,symbol,pe_ttm,pb_mrq,ps_ttm,pcf_ncf_ttm,turn,pct_chg,is_st`。选股排序(全市场某日)列存宽表秒级。baostock 日线增量同源拆出。
### 14.5 增量 schtask(4 个)
| schtask | 时间 | 源 | 内容 | 落点 | 预算 |
|---|---|---|---|---|---|
| sanguo-bs-eod | 18:05 | baostock | 个股日线+15min 增量+拆 pe/pb | dbbardata('d'/'15m')+valuation_baostock/ | ~11000/48000 |
| sanguo-xt-eod | 18:40 | xtata | ETF/基金日线+个股当天实时补 | dbbardata('d') | 无限流 |
| sanguo-bs-akshare | 19:00 | akshare | 三表+事件类 | parquet | 限频单线程 |
| sanguo-index | 月度 19:50 | baostock+akshare | 成份股合并 | constituent_unified | 小 |
baostock 单进程单登录,`DAILY_LIMIT=48000`,sleep 限速,login 探针 graceful skip,直连不走代理。5min/1min 不设 schtask。
### 14.6 dbbardata 补退市(本次审计发现,顺带治回测幸存者偏差)
实证(`dbbardata_probe`):退市股(000005/000023/600811)在 dbbardata **只有 15m,无日线** → 回测读 dbbardata 日线天然幸存者偏差。迁移:`daily_baostock_full` OHLCV 全量(含退市)→ dbbardata('d') INSERT OR REPLACE(本地 DB 迁移,无网络)。ETF 已在 dbbardata(不碰)。
### 14.7 复权统一
全链路 raw 真实价存储(dbbardata 存 raw),前复权由消费端按 `bs_adjust_factor`(baostock)统一算。xtata 当天实时同为 raw,可拼接。禁止混 xtata dividend_type=front。
### 14.8 数据迁移(5 单元,风险升序,备份+staging+可回滚+审计日志)
1. 存量垃圾清理(`_staging_xtdata` 14万文件 / `_xtdata.tar` 1.4G / 归拢 cta_* dbg_* → backtest_files/)
2. config 统一 VPS 路径(NAS 仅备份)
3. 成份股合并(bs_index_constituent + index_const_hist union → constituent_unified,按指数代码去重,新浪300/50丢弃)
4. daily_baostock_full 拆分(OHLCV→dbbardata('d') 含退市;pe/pb→valuation_baostock/<year>.parquet;旧表 rename _old)
5. dbbardata 个股日线切 baostock 源(单元4已覆盖:daily_baostock_full 含全量,在市股 REPLACE 覆盖 xtata,数值一致)
每单元:全库 `sqlite3 .backup` + rsync NAS → 脚本写 staging(新表/新目录)→ 验证探针(行数/distinct symbol/抽样价格/成功率)→ 用户确认合并 → 旧数据 rename _old 保留 7 天。全程 nohup + 审计日志 `data/migration_logs/`
### 14.9 config 清理
VPS config 的 daily_dir/raw_dir/qfq_dir/minute_15_dir 改 `C:\sanguo_vnpy_v2\data\...`(当前 yaml 指 NAS /volume1,容器版遗留)。NAS config 保留作备份。read_parquet_daily 的 daily_dir 统一指向 qfq(消除 daily/ vs qfq/ 分叉)。
## 15. 增补 2026-09-02:A 档截面数据域全量上生产(本节为最新,覆盖前文相关决策)
> 本节数据的**使用层读取接口见 §16**(get_event_panel / get_limit_pool,同日落地)。
> 背景:调研 [daily_stock_analysis](https://github.com/ZhuLinsen/daily_stock_analysis)(Gitea 镜像 `sanguo/daily_stock_analysis`)
> 的数据采集面,双机实验(Mac + VPS 生产 IP 49.232.102.198)后落地。四 commit
> db789d6→020d7cd→00cfd45→46a0569,CI#303 NAS 验证绿 + vps-deploy#304 绿,tag=46a0569。
### 15.1 架构红线:单脚本注册表,零新采集脚本(用户钦定)
脚本按**数据源(栈)**分类恒定:akshare 栈唯一采集入口=`scripts/data_platform/akshare_static_download.py`,
baostock 栈=bs_* 系列,xtdata 栈=daily_update_xtdata,新浪指数=sina_index_eod。**新数据类型=注册表添行
+一个 fetcher 函数+wrapper 加名字**,禁止每类型开新脚本。akshare 本身是聚合库(东财/新浪/同花顺都在内),
新浪/同花顺数据进 akshare 脚本=按栈分类,不算混源。
### 15.2 新数据域清单(全部落 data/static/<type>/,parquet+marker)
| 数据域 | 类型 | 源/端点(集群) | 调度 | 行数 | 回补能力 |
|---|---|---|---|---|---|
| zt_pool 涨停池 | per-date | 东财 stock_zt_pool_em(push2ex) | ak-events 19:30 | ~83/日 | **30 交易日内可回补** |
| zt_pool_zbgc 炸板池 | per-date | 东财 zbgc_em(push2ex) | 同上 | ~6/日 | 同上 |
| zt_pool_dtgc 跌停池 | per-date | 东财 dtgc_em(push2ex) | 同上 | 0-2/日(空=当日真无跌停,写空+done) | 同上 |
| fund_flow_industry 行业资金流 | per-date 快照 | 新浪 stock_fund_flow_industry('即时') | 同上 | 90/日(净额/流入/流出/领涨股) | ❌无历史回补,洞即永久 |
| fund_flow_concept 概念资金流 | per-date 快照 | 新浪 fund_flow_concept | 同上 | ~387/日 | ❌ |
| ths_industry 行业榜 | per-date 快照 | 同花顺 board_industry_summary_ths | 同上 | 90×12列/日 | ❌ |
| ths_concept 概念名单 | per-date 快照 | 同花顺 board_concept_name_ths | 同上 | ~375/日 | ❌ |
| xueqiu_hot 雪球热度 | per-date 快照 | 雪球 stock_hot_follow_xq('最热门') | 同上 | ~5634/日 | ❌ |
| sina_sector 新浪行业 | per-date 快照 | 新浪 stock_sector_spot | 同上 | 49/日(ths_industry 对账源) | ❌ |
| hot_rank 东财人气榜 | per-date 快照 | 东财 stock_hot_rank_em(emappdata) | **fetcher 就位未挂载,待墙测量拍板** | ~100/日 | ❌ |
| gdhs 股东户数 | **per-period** | 东财 stock_zh_a_gdhs(datacenter) | **ak-weekly 周六** | ~5342/期 | marker 去重,无新期零网络 |
- **ak-events 事件窗现状 13 类** = 上表前 9 + 原有 dragon_tiger/block_trade/margin_sse/restricted
- gdhs 形状特殊:`build_gdhs_units` 只枚举**距今>90 天的季度末**(披露守卫)——防未披露期拉空走「真空+done」
被 marker 锁死永不重拉;cyq 筹码判死后的筹码结构免费替代(策略侧共识)
- 快照族节假日拉到上一交易日态(端点无 date 参数无自日期列),接受重复,消费方按交易日历过滤
### 15.3 东财墙模型(实测,勿再踩)
- **每 IP 每窗口(~30-60min)放 1 发**:push2 clist(行业/概念榜/资金流榜)、push2his(kline/cyq/个股资金流)、
emappdata(人气榜)三集群同款;第二发必死、镜像(1./17./79.push2)共享、请求形状无关
(dsa 的 efinance 四差异 http+IE11UA+无ut+fid=f12 全复刻也死)、失败重试不重置窗口
- **datacenter 集群(三报表/gdhs/top_holders)独立健康**,不受 push2 惩罚波及;**push2ex(涨停池)独立稳定连打全绿**
- **cyq 筹码全市场=数学死**(5552×40min≈154 天);dsa 的答案是 tushare cyq_chips token 且免费档 15 次/天
- **行业/概念榜+资金流的免费答案=换域**:同花顺(行业+概念榜)+新浪(资金流+行业)实测秒级零限流
### 15.4 语义与防线(全族统一)
- 失败→返 None 不写不标保旧数据(次日重试);真空 df→写空+done;列名零清洗 akshare 原样落盘
- **缺日防线**(static_vintage_check.py 09:00):panel_gap_check 每工作日应有 1 个 parquet(节假日空文件也算有);
可回补族(zt_pool×3)洞≤42 日历日→告警+回补指引;快照族洞即永久→近窗洞告警查日志、旧洞只入 json 不刷告警
- **vintage_status.json 的 panel 块**=策略守卫层消费契约:`panel.<type>={n_files,first_date,holes_backfillable,holes_permanent}`
### 15.5 消费契约(与策略 session 09-02 对齐)
- **炸板率 = 炸板池行数/(涨停池+炸板池行数)**:涨停池=收盘仍封(「炸板次数」>0 行=炸过又回封),炸板池=触板未封,
并集≈当日触板全集,分母无遗漏
- 涨停池 16 列:封板资金/首次封板时间/最后封板时间/炸板次数/涨停统计/连板数/**所属行业**(
=免费当日热点行业分布信号,涨停行业集中度原料)/换手率/市值等
- 温度计三支柱=涨跌停(hot_rank 待批)+雪球;情绪周期/打板/行业轮动因子原料自 2026-08 起逐日积累
## 16. 增补 2026-09-02:使用层 provider 接口(A 档数据的读取出口)
> §15 采集落盘的数据在本节获得 provider 出口。设计经业界对照定稿(2026-09-02 用户拍板):
> dsa `get_limit_up_pool` / tushare `limit_list_d`(U/D/Z 参数化)/ 聚宽 per-domain 方法 / OpenBB TET
> ——共识三条:**接口轴=数据域**、**列名在数据层边界标准化**(无一家透传原始中文列)、
> **泛型传输+语义入口分层**(tushare 底层也是 `pro.query(api_name, params)` 泛型通道)。
> miniQMT/QMT/PTrade 均无涨停池/龙虎榜类接口(业界惯例=外部源补),实盘 provider 同样读本地文件。
### 16.1 两层出口(「泛型底座 + 域语义门面」)
| 接口 | 定位 | 返回列 |
|---|---|---|
| `get_event_panel(event_type, date / start+end, trading_days_only=True)` | **保真底座**:白名单 14 类统一通道(§15.2 全部+gdhs),研究/因子探索用 | akshare 原样中文列 + `trade_date`(YYYY-MM-DD,文件名合成);**别把底座列名当生产契约** |
| `get_limit_pool(kind="zt"\|"zbgc"\|"dtgc", date / start+end, ...)` | **涨停池门面**:kind 三合一(← tushare limit_list_d),唯一有消费契约的域先建(温度计/炸板率/行业集中度) | 英文标准列:`code/consecutive_boards/seal_amount/break_count/first_seal_time/industry/limit_stat`…(键名对齐 dsa) |
- 实现=TET Fetcher(`fetchers/event_panel.py`,FETCHERS 注册表新增 `event_panel`/`limit_pool`),
LocalUnifiedProvider(回测)与 SanguoMiniQmtProvider(实盘,委托 `self._unified`)双侧同款
——方法面钉死测试(issue #35)强制无缺口;双侧同 schema 支持副本对照验证
- **列名漂移吸收**:akshare 改中文列名时,门面映射表(`_LIMIT_POOL_COLUMNS`,基于 VPS 真实
parquet 实测 2026-09-02,dtgc 实测含 动态市盈率/封单资金/板上成交额/连续跌停/开板次数)吸收,
下游英文键不炸;有行但缺源列→DataSchemaError fail-fast
- **trading_days_only=True(默认)**:用 `get_trade_days` 滤非交易日——治快照族「周中法定假日文件
=上一交易日态复制品」的区间双计数;`=False` 按周一~五枚举(=采集侧口径)
- 缺文件(洞/未来日/从未采集)=合法缺失→空 DataFrame;真空日(dtgc 0 跌停)→门面仍返标准列空表
- hot_rank 未挂载不在白名单(拍板后与采集注册表、PANEL_TYPES 三处同步加)
- 新数据类型接入=底座白名单加一行(零新方法);某域有消费契约后再升格门面(YAGNI,不加投机门面)
### 16.2 MCP 出口预留
FETCHERS 注册表新增两键即自动可被未来 provider MCP server 暴露
(`Fetcher.fetch(ctx=provider, **kwargs)` 直接调用,fetchers 包设计初衷)。
## 17. 增补 2026-09-02 深夜:首夜巡查修正(覆盖 §15 相关决策)
- **首夜实绩(09-02 19:30,13 类)**: 12/13 绿——快照族 6/6 行数与双机实验一致
(资金流 90/387、同花顺 90/375、雪球 5634、新浪行业 49);唯一红=margin_sse(下条)。
- **margin_sse 结构性缺陷根治(用户批准)**: SSE 融资融券 **T+1 供应**(当晚拉当天→空响应
→akshare Length mismatch 崩),自 07-22 起慢性失血 43 天全空(旧码 empty+done 锁死,
缺日检查未覆盖老四类故无人发现)。修=①`--force` 回补 0722~0901(30/30 ok 59865 行,
VPS+NAS 双端);②wrapper 拆 margin_sse 单独 **T-1~T 两天窗**(564160d):每晚稳定写昨日,
当天失败不写不标、次晚同窗自愈。
- **NAS 同步链扩容(ab8f4e3)**: `sync_parquet_daily.sh` TYPES 原写死老 4 类——扩到 13 类;
gdhs=per-period 季度日期永不落 7 天滚动窗,单独全量拉(≤10 文件幂等)。⚠️NAS 坑:03:00 链
以 root 跑留 root 属主文件,admin scp 覆盖之=Permission denied,先 rm 再拉。
- **回灌纪律(zt_pool 0902 事故)**: 回灌窗口**绝不含当日**——盘前拉当日=拿到上一交易日态
复制品(0902 文件≡0901 逐值同)+marker 占位致当晚 19:30 跳过;已删+盘后重拉 52/15/8 真数据。
- **VPS 部署终态**: 使用层 3 commit(4966d30/7f01c5f/564160d)推 VPS(run#1043,tag=564160d,
gap=0),VPS 端 8/8 功能验证过(双层接口/区间滤日/回补数据可读/白名单拒绝/实盘方法面)。
## 18. 增补 2026-09-06:基本面语料库(新闻+公告)采集设计——NAS 域(本节为最新,覆盖前文相关决策)
> 用户拍板(2026-09-06,经 factor session 转达):范围=六项全做(新闻标题+摘要级增量/新闻全文级/
> 新闻历史回补/公告元数据全量回补 2000 起/公告每日增量/定期+业绩类 PDF),**唯一不做=公告 PDF 全量
> (520GB/年)**。前置调研=`docs/fundamental_corpus_probes_20260906.md`(三摸底实测)。
> 本节为 spec,验收通过后才实施;spec 阶段零建表零采集。
### 18.1 硬约束(用户原话级)
1. **存储全部落 NAS、一律不上 VPS**——「vps承载有压力,之前基本面都放在了nas上,没有放vps,本次
也一样」。VPS 零参与:零 schtask、零存储、零采集进程;repo 里进脚本仅为随 NAS 部署管道分发
(promote --target nas → /volume1/homes/admin/.sanguo_projects/sanguo_vnpy_v2/**宿主机
直读该路径,不经容器**),VPS 侧永远不会被调度。
2. **采集进程=NAS 宿主机直跑,不绑定 docker**(用户钦点:「不要和docker绑定,避免docker重启就
失败」)。运行时=/volume1/stock/corpus/venv(`python3 -m venv --copies` 自举,DSM 自带
Python 3.8.12/pip 已实测可用,x86_64;依赖锁 cp38 兼容版 pandas/pyarrow/requests)——容器
重启/升级/停用零影响,venv `--copies` 连 DSM 换 Python 也不怕。家宽出口 IP ≠ VPS 公网 IP
(49.232.102.198),与 VPS 侧 ak-daily/ak-events 的东财限流**零冲突**。09-06 实测佐证:
np-listapi/巨潮/东财文章页 ~35 发连续探测自家宽 IP 全成功、零限流。
**与 sanguo-5m 独立容器方案的差异**(用户问):两者同治「不被主容器重启波及」,但 5m 停在
docker 家族内(`docker run --rm` 一次性容器,仍依赖 daemon+镜像+tag 不改名,优点=镜像环境
完整+版本自动跟随主容器),corpus 按用户指令走到底(零 docker)。5m 当年未走到底是合理的——
bs_5m_eod.py 依赖面=整个镜像环境(baostock 等),宿主 3.8 venv 装不齐;corpus 脚本依赖面
收敛为 3 通用包才有条件零 docker(代价=venv 冻结,版本漂移需手动 pip 对齐,已由 T1 锁版本
缓解)。**5m 不迁**:在跑且稳定、迁移需重验 baostock@3.8、没坏不动;但其为存量 docker
依赖点,NAS docker 套件大升级/镜像重建时需人工盯,届时再评估迁 venv。
3. **时间带**:全部采集限于 **00:3017:30**,避开 18:0523:45 傍晚带(VPS 夜任务密集+家宽使用)。
唯一日窗=每日 06:00 起(见 18.3)。
4. 慢爬纪律:单进程单线程、per-domain 限速+抖动、直连不走代理(Session.trust_env=False,防
Mac 系统代理同款坑)。新浪线已判不可依赖(09-06 实测空返),本设计不使用。
### 18.2 数据模型(NAS 落位:/volume1/stock/corpus/,与 A股数据/ 平级)
```
/volume1/stock/corpus/
news_meta/dt=YYYY-MM-DD/part-0.parquet # 东财个股新闻·标题+摘要级(仅新条目,append-only)
news_fulltext/dt=YYYY-MM-DD/part-0.parquet# 东财新闻正文(按 art_code 全局去重,4.1KB/条)
ann_meta/dt=YYYY-MM-DD/part-0.parquet # 巨潮公告元数据(仅新条目;回补的也落发现日分区)
ann_pdf/YYYY/<announcementId>.pdf # 定期+业绩类 PDF(文件名=唯一id,天然幂等)
state/ # 断点水位+unit marker(JSON/parquet)
logs/corpus_YYYYMMDD_HHMMSS.log
```
Schema(列名冻结,消费方=factor session 因子加工层,后续 provider fetcher 可包):
- **news_meta**: `art_code`(pk), `stock_code`(6位), `show_time`, `title`, `summary`(可 null:
np-listapi 回补段无摘要——search-api 只有最近100条,历史摘要物理不存在), `media_name`(同上可
null), `url`, `first_seen_date`
- **news_fulltext**: `art_code`(pk,跨股票全局一条——同一篇稿提及多股只在 meta 层多行),
`url`, `show_time`, `content_text`(去标签正文), `fetch_date`
- **ann_meta**: `announcement_id`(pk), `sec_code`, `sec_name`, `org_id`, `title`, `short_title`,
`content`(摘要原文), `ann_time`(epoch ms→ts), `ann_type`, `ann_type_name`, `column_id`,
`important`, `adjunct_url`, `adjunct_size`, `batch_num`, `first_seen_date`
- **ann_pdf 索引**(state/ann_pdf_index.parquet): `announcement_id`, `sec_code`, `ann_type_name`,
`report_year`(从报告类别+公告年推), `local_path`, `bytes`, `fetch_date`
设计要点:**id 键控、无「$today 文件名」语义**——条目自带时间戳(show_time/ann_time),分区键是
发现日而非业务日,盘前跑/隔夜跑都无 0902/0904 式错标风险(与 A 档快照族的root差异)append-only
不重写(仅新条目入区,短窗 id 去重=读近 N 日分区),无 merge 改写类事故面。
### 18.3 采集设计:**1 个脚本 + 1 个调度入口**(脚本整合原则,用户追加指令②)
- **脚本**: `scripts/data_platform/corpus_download.py`(repo 内唯一新文件;单脚本红线同款——
corpus 栈一个入口,类型靠内部注册表,禁再开新脚本)。参数 `--lane daily|backfill`
`--until HH:MM`(墙钟自停)、`--limit N`(手动冒烟)。
- **调度**: DSM 任务计划 **sanguo-corpus-daily,每日 06:00 一条,以 admin 身份跑**(先例=现有
03:00 同步链 DSM 任务(id=2),宿主机直跑多年零 docker;本设计沿同模式但改 admin 跑,避该链
root 属主文件坑)。
**为何 admin 而非统一 root**(用户问):①03:00 链 root 属主文件坑已在案——admin scp 覆盖
root 文件 Permission denied 只能先 rm 再拉;语料库生命周期内 admin 侧操作密集(venv 装包/
回补盯跑/删错分区/debug),admin 属主=全程零摩擦 ②最小权限:出网慢爬+写文件的进程没必要
root,出错爆炸半径小一截 ③成本为零:DSM 建任务本就选用户,不比 root 贵——统一到 root 统一
的是坏模式。**存量脚本一个都不迁移**(用户问「有必要全改admin吗」:没有——03:00 链等既有
root 任务照旧跑,没坏不动;admin 仅是新建 corpus 任务从第一天的选型;两套并行零冲突:目录
隔离/时间窗错开/部署管道不同,互不碰对方文件)。**admin 权限逐项实测**(2026-09-06):
/volume1/stock 建目录/写/删全通(rwxrwxrwx+ACL,admin 属主);venv `--copies` 在 /volume1
建成+stdlib OK+pip user-site 既有;读 admin 家 CI 部署路径无障碍;⚠️坑:venv 建在 **/tmp
会 Permission denied**(DSM /tmp 特殊限制,且 /tmp 会被清空)——设计本就落 /volume1,勿改
/tmp。设计内无任何一步需要 root;万一未来例外,人工 sudo/改任务属主是逃生门非设计依赖。
**root vs admin 终局论证**(用户问「root 数据不可修改的设计更好吗」):root 属主的「写保护」
是半吊子幻觉——admin 不能覆写 root 文件**但能删**(删看目录权限,/volume1/stock rwxrwxrwx,
03:00 链「先 rm 再拉」workaround 实证),防住原地改防不住删了重建;而 root 跑采集的代价是
全天候的——**root 进程 admin 杀不动**(Synology sudo 要交互密码,自动化做不了;本设计验收
含 kill -9 续跑项,root 方案连测试都无法执行)+venv 装包/盯跑全要 root 陪跑+外网爬虫拿最大
权限。**不可改性交给正确工具**:append-only 协议(dt=分区只追加/tmp+rename/id 键控)+
可再生性(公告新闻都在源站,断点机制可重拉,语料=全体系唯一可完全再生的数据类);如仍需
防篡改层,验收后加 DSM 快照/每周 tar+校验和归档——对任何属主都生效,属主只是假不可变。
**「root=和之前数据一致」前提实测不成立**(用户追问后核查):/volume1/stock 现状=**三种属主
混合**——cfdaily(A股数据/minute_kline/knowledge_base 等,**用户记忆中的「之前基本面数据」
恰是 cfdaily 属主而非 root**)/root(03:00 链产物+sanguo_5m)/admin(_dbuild/gitea/frp 等);
且文件全 rwxrwxrwx+ACL,无任何消费方依赖属主。真正的一致在方法论层(schtask 语义/marker/
慢爬/单脚本红线),root 与 admin 两案完全同款;唯一实质差异=运维通道(admin ssh 可杀进程/
装 vps 包,root 全要 DSM 一次性任务或交互 sudo,自动化不可达)。终判 **admin**,若用户仍拍
root 亦可行,代价=venv 引导与 kill 全走 DSM 一次性 root 任务/人工 sudo。
**为何独立任务而非并进 03:00 链**(用户问):①失败不连坐——03:00 链=从 VPS 拉
行情的对内同步,corpus=对外 HTTP 慢爬+数小时回补马拉松,合成一条则 corpus 卡死会拖死每日
行情同步(断路器饿死同款教训,绝不复刻)②属主/部署管道不同——sync 脚本在 /volume1/stock
root 地盘 CI 不覆盖须手动 scp,corpus 脚本走 CI deploy 的 repo 路径,搅进一条任务两头别扭
③06:00 起跑避开 03:00 链跑道(26G 库同步 IO+家宽带宽),且 00 时档公告(54%)凌晨已入库,
06:00 全吃到;DSM 加一条任务代价≈零,改 root 生产链脚本才是真风险:
`/volume1/stock/corpus/venv/bin/python -X utf8
/volume1/homes/admin/.sanguo_projects/sanguo_vnpy_v2/scripts/data_platform/corpus_download.py
--lane daily && 同解释器 --lane backfill --until 17:30`
(两 lane 串行=天然互斥;rc 聚合,任一 lane 失败 log 留痕)。**全程零 docker 依赖**。
**断点续传(用户钦点加固,所有 lane 的第一设计原则)**
- 粒度=unit(公告=(stock,year)/新闻=(stock,page)/全文/PDF=单 id),每 unit 一枚 marker(state/
下原子写 tmp+rename);进程被杀/断电/重启后,重启即从「未标 done 的最老 unit」续跑,**无任何
全局重启语义**;17:30 墙钟=完成当前 unit 即 checkpoint 退出,次日 06:00 自动接续。
- daily lane 幂等可重跑(短窗 id 去重,重复执行零副作用);漏日自愈=公告 T-1~T 两天窗,新闻
recent-100 页面天然覆盖数日缺口(冷门股 100 条跨数月)——某天整个任务没跑,次日一次执行即可
补齐,不依赖专门回补。
**daily lane(每日,总 ~4.5h,06:0010:30 前后)**(06:00 晨窗依据 09-06 实测:深市 600 条公告
发布时刻分布=盘中(09-15时)**0%**(3条)、盘后 15-20 时 46%、**00 时档 54%**(巨潮深夜批处理
披露)——公告主体在盘后+零点档,06:00 拉取 T+1 晨=前日公告 100% 入账,**优于任何傍晚方案**
(17:30 前收工的方案会漏 19-20 时 18%+00 时 54%);新闻当日条目盘中占 27%、盘后晚间 73%,
日频消费 T+1 晨拉零损失):
1. 公告增量(巨潮,~5400 req @1/s≈1.5h):每股 seDate=T-1~T 两天窗+`announcement_id` 短窗去重
(同 margin_sse 两天窗自愈模式,漏一天次日自动补上);
2. 新闻增量(东财 search-api=akshare stock_news_em 同款端点,~5400 req @1/s≈1.5h):带摘要,
每股最近100条,新 art_code 入 news_meta;
3. 新闻全文(东财文章页,@2/s,~1万 req≈1.5h):仅下载昨日新发现的 art_code 正文;
4. 当日 PDF(定期+业绩类 category 过滤,数量级 ~100-400 份/日,峰值在 4 月年报季)。
**backfill lane(每日 10:3017:30 剩余时间,断点续跑,顺序=因子价值优先)**:
① ann_meta 全量回补(2000→今,unit=(stock,year),~19 万 req,预计 36 天跑完);
② news_meta 回补(np-listapi 标题级,unit=(stock,page),翻到空页或 page≥200 止,~11 万 req,
24 天)——历史段 summary=null 是物理上限(search-api 只有最近100条),spec 如实约定;
③ news_fulltext 回补(①②清单里的 url,@2/s,~1000万 req≈12 个月慢车道);
④ 定期+业绩类 PDF 回补(年份**新→旧**,2026→2000,~34 万份/~300GB,慢车道数周–数月)。
**容量闸门**: /volume1 实测空闲 645G(2026-09-06);PDF 回补每落 50GB 自查 `df`,空闲<200G 即
暂停 PDF 段并 log 告警升级用户重拍(其余段不受影响——非 PDF 段总盘子 <60G)。
**失败语义(吸收 09-01/09-05 教训)**: fetch 失败→unit 不标 done 不写半截(parquet tmp+rename);
真空(该股该年 0 公告)→标 done 合法;确定性解析错→记日志跳过该 unit **绝不烧重试、绝不连坐后续
unit**(northbound 断路器饿死教训);域名级连续传输错(403/429/超时×10)→该域本日冷却、它域继续、
rc=1 留痕,次日自然重试。
**探测优先(用户追加指令①)**: 深度不预设上限——巨潮按年翻到空、东财按页翻到空/PAGE 硬顶为止,
PDF 按可得性实下(404 标 missing 不重试);每源每股记录 first_date 入 state/depth_summary.json,
实施期边探边记,实际深度以落盘数据为准(三摸底测得:巨潮≈2000 起渐密/1993 有零星,东财≈最热股 3 年)。
### 18.4 预算汇总(实测口径)
| 层 | 增量/年 | 回补累计 | 请求量级 |
|---|---|---|---|
| news_meta(标题+摘要) | ~1.3GB | +3 年标题级 ~1.5GB | 日 ~5400;回补 ~11 万 |
| news_fulltext | ~10.6GB | 3 年 ~32GB | 日 ~1 万;回补 ~1000 万(慢) |
| ann_meta | ~1.3GB | 2000 起 ~15GB | 日 ~5400;回补 ~19 万 |
| ann_pdf(定期+业绩) | ~45GB | ~300GB(**带容量闸门**) | 日 ~100-400;回补 ~34 万 |
| **非 PDF 合计** | **~13GB/年** | **<60GB** | — |
### 18.5 验收标准(实施完成的定义)
1. **daily lane**: T+1 晨抽查 5 股(超热/热/中/冷/ST)——show_time/ann_time∈[T-1,T] 的条目
全在且 id 无重复;日志限速合规(平均间隔≥设定值,零 429/403 连击)。
2. **ann_meta 回补**: 600519 年报 2001 起逐年可查;announcement_id 全局无重;year×count 曲线
单调合理(早年稀疏→近年 ~130 万/年)。
3. **news 回补**: 600519 最早条目落 2023-09±1 月(实测硬顶对齐);depth_summary.json 全量产出。
4. **PDF**: 抽 20 份跨年份可打开(%PDF 魔数+size>0+meta 可反查路径);索引行数=文件数。
5. **边界**: /volume1/stock/corpus 之外零写入;VPS 零改动(git diff 触及面仅 scripts+tests+docs);
容量闸门演练一次(临时阈值)证明会停;**docker 全停状态下手动触发 corpus-daily 照跑通**
(不绑容器的验收实证)。
5b. **断点续传**: 回补中途 `kill -9` 采集进程→重启后从未完成 unit 续跑,已完成 unit 零重拉
(marker 核对);某日整个任务停跑一天→次日单次执行把漏日补齐(T-1~T 窗+recent-100 覆盖)。
6. **测试**: tests/data_platform/ 新增 CI 测试(fetch 全 mock 零网络)——失败语义/短窗去重/
两天窗自愈/墙钟自停/unit marker,全套本地绿+CI 绿。
### 18.6 非目标(明确不做)
公告 PDF 全量(用户排除);因子加工层(factor session 职责,消费接口=18.2 的 parquet 契约);
新浪任何接口;VPS 侧任何东西;正文 NLP 解析/向量化;provider 出口(消费层稳定后再议,先直读
parquet);月度 compaction(数据量小,YAGNI)。
### 18.7 实施步骤概要(验收通过后,TDD)
T1 宿主机 venv 自举(`--copies`,锁 cp38 兼容版本 pandas/pyarrow/requests,清华镜像)+连通金丝雀
(每域 1 发)+目录骨架 → T2 corpus_download.py daily lane 四段+断点续传 state 机制+测试 →
T3 DSM 任务注册(admin 身份,零 docker)+首周人工盯跑 → T4 backfill lane ①② → T5 ③④+容量闸门
→ T6 验收清单执行+活文档本节补「实施终态」小节。每步一个 commit,标签 **[nas]**(VPS 零触及)。
### 18.8 全局下载方案与存放位置总表(回应「不想搞好几套」——本节=现势唯一完整说明)
**一条规则,不是几套方案**:每类数据**唯一权威源+唯一权威位置**(§14.2 既定原则),**采集发起位置
跟随权威位置**——数值类(行情/估值/报表/事件面板)权威=VPS,既有任务家族不变;文本语料类(新闻/
公告)权威=NAS(本节新增,用户三约束唯一决定:不上VPS+东财IP限流冲突+不绑docker)。两域方法论
同款:单脚本注册表红线/慢爬防封/断点 marker/schtask 语义/容量闸门。**「数值类权威=VPS」有
一个在跑的例外=5min,其权威在 NAS 副本库(见下表 sanguo-5m 行)**。§14.5 为 07-22 历史快照,
采集任务现势以本表为准(08-20 起 bs-eod+bs-fund 已并 sanguo-bs-daily、akshare 已拆
daily/weekly/monthly/events 三频率+ak-vintage 自检):
| 任务 | 机器 | 时刻 | 内容 | 权威落点 |
|---|---|---|---|---|
| sanguo-bs-daily | VPS | 18:05 | baostock 日线/15m/估值/财务 fund | dbbardata + valuation_baostock/ |
| sanguo-xt-eod | VPS | 18:40 | xtdata ETF+个股当日实时 | dbbardata |
| sanguo-idx-eod | VPS | 每日 | 指数点位 | SSE 表 |
| sanguo-ak-daily | VPS | 07:35 | akshare 低频日更 | static/ |
| sanguo-ak-events | VPS | 19:30 | A 档 15 类事件面板(时间守卫) | static/ |
| sanguo-ak-weekly | VPS | 周六 03:00 | gdhs/share_capital/top_holders/northbound | static/ |
| sanguo-ak-monthly | VPS | 首周六 | 三表全量马拉松(55h 跑道) | static/ |
| ak-vintage 自检 | VPS | 09:00 | 缺日/错标防线 | vintage_status.json |
| NAS sync 链(DSM id=2,root) | NAS | 03:00 | VPS→NAS 副本拉取(7 域) | /volume1/stock/… |
| sanguo-5m(DSM id=7,root) | NAS | 00:05 | baostock 5min 增量+全量回补(独立一次性容器 `docker run --rm` 跑 lock-aligned 镜像,08-22 治「CI 重启主容器杀在跑任务」;窗口 2020 起,含退市 5547 只,runner=/volume1/stock/sanguo_5m) | **NAS 副本库 dbbardata('5m')=5m 唯一权威** |
| **sanguo-corpus-daily(DSM,admin)** | **NAS** | **06:00** | **巨潮公告+东财新闻(本设计)** | **/volume1/stock/corpus/** |
**存放位置全景**:**数值权威=VPS `data/`**(dbbardata 26G+static/+valuation_baostock/),
**两个例外在 NAS**:①**5min——权威=NAS 副本库**`/volume1/stock/sanguo_vnpy_v2/data_backup/
quant_trading.db` 的 dbbardata('5m')(VPS 侧 '5m' 是空占位;§14.2「5min 占位/不设 schtask」
为 07-22 历史快照,08-20 起由 DSM 00:05 任务实际落地,**当时未回写本文档=文档债,本表现补**
——用户 09-06 验收总表时点名找回);②**语料=NAS `/volume1/stock/corpus/`(本设计)**。
NAS 其余=数值副本(sync 链产物)+大体积历史(minute_kline/ 2.1G=cfdaily 时代外部 1min/5min/
15min,无任务在跑,其中 **1min 为全体系唯一 1 分钟粒度**;A股数据/;LLM-Models 等非本项目)。
Mac=开发 fixture 无生产数据。corpus 不是第三种根——就是既有 `/volume1/stock` 数据根下的
新子目录,与 CLAUDE.md「NAS 部署目录」表一致。
## 参考(调查来源)
- xtdata 官方:https://dict.thinktrader.net/nativeApi/xtdata.html
- akshare 指数:https://akshare.akfamily.xyz/data/index/index.html
- akshare 基金:https://akshare.akfamily.xyz/data/fund/fund_public.html
- akshare 债券:https://akshare.akfamily.xyz/data/bond/bond.html
- baostock API:https://www.baostock.com/mainContent?file=pythonAPI.md
- 国证指数网(深证历史):http://www.cnindex.com.cn/module/index-detail.html?indexCode=399001
- 新浪历史成份:http://vip.stock.finance.sina.com.cn/corp/go.php/vII_HistoryComponent/indexid/000852.phtml
- QLib 数据层:https://qlib.readthedocs.io/en/latest/component/data.html
- 现有缺口设计:`docs/static_data_gaps_design.md`