# 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) | 1990–2026 | 待 #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/.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/.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//,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.={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-deploy 到 `/volume1/homes/admin/.sanguo_projects/sanguo_vnpy_v2/`(= 采集容器的 `-v` 只读挂载 `/app`, 与 5m 同款分发通道),VPS 侧永远不会被调度。 2. **采集进程=一次性容器,与 sanguo-5m 统一**(用户终拍板 2026-09-06「统一到5min吧」)。方案 演进:初版按用户「不要和docker绑定,避免docker重启就失败」设计为宿主机 venv 零 docker; 验收中用户权衡「不想搞出多种下载方法」,比较两方向后拍板 **corpus 向 5m 的 `docker run --rm` 模式统一**(反向统一有硬阻塞:5m 写入的 data_backup 库为 03:00 链 root 属主产物,admin venv 写不进;且需重验 baostock@py3.8、动在跑系统)。**被治的痛点不变**——主容器重启不再杀任务 (08-22 5m 被 CI 杀三案后的同款根治);**保留的弱依赖**=docker daemon 在跑+镜像 tag 不改名 (与 5m 同款,已跑一个月实证;daemon 停一天,数据次日自愈)。**两项 corpus 专属改进**:①DSM 任务以 **admin** 跑(09-06 实测 admin 可执行 docker 命令);②容器加 `--user ` → 输出文件 admin 属主(root 文件坑不复发),**杀进程=`docker stop sanguo-corpus`**(admin 一条 命令)。镜像环境完整+版本自动跟随 CI 部署,零 venv 自举/锁版本/漂移问题。家宽出口 IP ≠ VPS 公网 IP(49.232.102.198),与 VPS 侧 ak-daily/ak-events 的东财限流**零冲突**。09-06 实测 佐证:np-listapi/巨潮/东财文章页 ~35 发连续探测自家宽 IP 全成功、零限流。**统一后全图** (机器内一种,物理下限):VPS=Windows schtask 家族(数值类)|NAS=DSM→bash wrapper→ `docker run --rm`(5m+corpus 同款,对外爬取)+sync 链(内部搬运)。 3. **时间带**:全部采集限于 **00:30–17:30**,避开 18:05–23: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/.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 身份跑**,机制=与 sanguo-5m 完全同款的「bash wrapper → 一次性容器」(wrapper=`/volume1/stock/corpus/ run_corpus.sh`,宿主文件 CI 不覆盖,改后手动同步——同 5m 的 run_5m.sh 部署纪律)。 **为何 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 属主);**admin 可执行 docker 命令** (docker ps 实测通过)→ wrapper/容器/`docker stop` 全程 admin 可运维;读 admin 家 CI 部署 路径无障碍(初版 venv 方案及其 /tmp 坑实测,已随「统一到 5m」拍板作废,记录在 git 历史)。 设计内无任何一步需要 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 生产链脚本才是真风险: wrapper 内部(同 5m 结构+corpus 两改进): `/var/packages/Docker/target/usr/bin/docker run --rm --name sanguo-corpus --user --entrypoint python -v /volume1/stock:/volume1/stock -v /volume1/homes/admin/.sanguo_projects/sanguo_vnpy_v2:/app:ro sanguo_vnpy_v2:lock-aligned /app/scripts/data_platform/corpus_download.py --lane daily` 成功后同款第二发 `--lane backfill --until 17:30`(两 lane 串行=天然互斥;rc 聚合,任一 lane 失败 log 留痕)。**`--name sanguo-corpus`=运维锚点:杀进程=`docker stop sanguo-corpus`(admin 一条命令);`--user `=输出文件 admin 属主**。镜像 tag 与主容器同源,CI 部署自动 跟随;tag 若将来基建重建改名,wrapper 跟着改(与 5m 同款注意事项)。 **断点续传(用户钦点加固,所有 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 条跨数月)——某天整个任务没跑,次日一次执行即可 补齐,不依赖专门回补。 - **从 sanguo-5m 借鉴三件**(用户问「断点续传是否一样/可否互借」后盘点 bs_5m_eod.py):① **单实例锁**(bs_5m.lock pid 活性检测同款——防 DSM 定时与手动补跑撞车双进程竞写 state, corpus 原设计缺口,采纳为 state/corpus.lock)②**退出码细分**(对齐 5m 语义并适配: 0=完成,1=致命,2=限流让路,3=墙钟自停让路——rc 即运维信号)③**state 损坏降级路径** (5m「state 坏→幂等重头无伤」思想;corpus=marker 坏→该 unit 重拉,append-only+id 去重 保证幂等无伤)。**5m 反向无需借鉴改造**:其整片推进粒度粗(半年片 3-4h,中断=整片重拉), 但回灌已完结、OR REPLACE 幂等无害、每日增量 LOOKBACK=7 独立自愈,改造无未来收益—— **5m 不做结构性改造**,仅两个顺手项下次动 run_5m.sh 时一并(docker run 加 --name 便于 定向 stop;头注释 DSM 时点 19:05→00:05 过时修正),不专门跑。 **股票池口径**(用户 09-06 拍板「都按你说的来」):**全 A 含退市**(~5547 只),清单源=NAS 副本库 data_backup/quant_trading.db 的 distinct symbol(本地零网络、天然含退市,同 dbbardata 治幸存者 偏差原则);退市股新闻层自然为空不浪费,公告层=事件因子回测原料。**PDF 类别=六类**(同日拍板): 年报/半年报/一季报/三季报/业绩预告/业绩快报(≈45GB/年;权益分派/增发等不进,元数据层仍全量有)。 **daily lane(每日,总 ~4.5h,06:00–10: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:30–17:30 剩余时间,断点续跑,顺序=因子价值优先)**: ① ann_meta 全量回补(2000→今,unit=(stock,year),~19 万 req,预计 3–6 天跑完); ② news_meta 回补(np-listapi 标题级,unit=(stock,page),翻到空页或 page≥200 止,~11 万 req, 2–4 天)——历史段 summary=null 是物理上限(search-api 只有最近100条),spec 如实约定; ③ news_fulltext 回补(①②清单里的 url,@2/s,~1000万 req≈1–2 个月慢车道); ④ 定期+业绩类 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); 容量闸门演练一次(临时阈值)证明会停;**主容器 restart(nas-deploy)不影响在跑的 corpus 容器** (一次性容器与主容器互不相干,5m 已实证同款);手动 `docker stop sanguo-corpus` 即停, 再触发从断点续跑。 5b. **断点续传**: 回补中途 `docker stop sanguo-corpus`→重启后从未完成 unit 续跑,已完成 unit 零重拉(marker 核对);某日整个任务停跑一天→次日单次执行把漏日补齐(T-1~T 窗+recent-100 覆盖);**单实例锁实证**:DSM 定时在跑时手动触发→让路退出(退出码=2/3 类),双进程零竞写。 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 wrapper+连通金丝雀(run_corpus.sh 按 5m 同款结构编写;`docker run --rm --user ` 跑通 镜像 python+每域 1 发出网验证+目录骨架)→ T2 corpus_download.py daily lane 四段+断点续传 state 机制+单实例锁+测试 → T3 DSM 任务注册(admin 身份)+首周人工盯跑 → T4 backfill lane ①② → T5 ③④+容量闸门 → T6 验收清单执行+活文档本节补「实施终态」小节。每步一个 commit,标签 **[nas]**(VPS 零触及)。**时长预期**(用户知悉):T1–T3≈1–2 个 session 工作日;ann_meta 回补 ~1 周后即可供 factor 做事件因子回测;全文/PDF 为月级慢车道自然推进。**用户已批开工** (2026-09-06「都按你说的来吧」)。 ### 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** | **巨潮公告+东财新闻(本设计,一次性容器同 5m 模式)** | **/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 部署目录」表一致。 ### 18.9 实施记录(2026-09-06/07 开工夜,T1/T2/T4/T5+T6 可自主项已验) commit 链 62a3a65→308d493(全 [nas],CI 绿,终版已部署 NAS /app)。两 lane 真数据冒烟 rc=0: daily 431s/205 unit(news +100×2 股、全文 199 篇均值 3584 字、复合键零重、 --limit 零 marker);backfill 13s/8 unit(①2026 层真公告 59+125、④真 PDF 1.09MB+索引)。 verify_corpus.py(只读验收器,晨检一条命令)真数据 PASS:三域 dups=0、账本=唯一键数、 PDF 索引=文件数。文件全 admin 属主;容器时区 CST 与 NAS 对齐。 **与 §18.3 字面的四项实施偏差(均为实测倒逼,语义不劣化)**: 1. 股票池源=巨潮 `szse_stock.json`(6247 含退市 000003+北交 920001→A 前缀过滤 6168), 非 NAS 副本库 distinct symbol——orgId 是按股查询硬前提且退市覆盖实测更全。 2. 单实例锁=flock(非 5m 的 pid 活性同款)——docker run --rm 各容器独立 PID namespace, pid 检测跨容器失效;flock 内核级经 bind mount 同 inode 跨容器互斥,进程死自动释放 无陈旧锁(让路契约同款,实测二实例 EXIT=3)。 3. 业绩快报无服务端类别码(category_yjkb_* 无效码被服务端**静默忽略返回全量**,官方 history-notice.js 码表无此项,单股对照实测)——PDF 六类=五服务端码+客户端标题谓词 「业绩快报」(announcementType 数字码 012111 仅作参考);announcementTypeName 恒 null, ann_meta.ann_type 存原始数字码串。 4. backfill ①年序=新→旧(字面「2000→今」与 §18.7「回补~1周后即可供 factor」自相矛盾, 翻转后 day1 即近年数据;全量完结不受影响)。 **§18.5 验收进度**: 5/5b/6 已过——主容器 restart 期间 corpus 容器存活且 marker 在涨 (实测);docker stop 断点冻结 27 unit→重启从 000028_2026 精确接续零重拉(实测);单实例 锁二实例让路 EXIT=3(实测);容量闸门真卷演练(临时阈值 99999G>free 644G→段首暂停 零下载+capacity_paused.json,工件即清);测试 270 绿+CI 绿。**待数据累积后补**: 验收 1(5 股抽查)/2(600519 2001 起)/3(news 2023-09 硬顶)/4(PDF 抽 20 份)+限速 合规 stats 复核——依赖 DSM 任务注册后数日运行。 **运维要点**: wrapper=repo `scripts/nas_sync/run_corpus_standalone.sh`→NAS `/volume1/ stock/corpus/run_corpus.sh`(scp -O 手动同步);容器必带 `--user 1024:100 --group-add 101` (Synology ACL 只授权 administrators 组,漏组=Permission denied)+`--name sanguo-corpus` (杀=docker stop);东财 search-api 无 UA 返 200 空 body(全 fetcher 统一带 UA); --until 语义=完成当前 unit 后停(首 unit 必跑);day-1 全文洪峰由 daily --until 10:30 墙钟+backfill ③账本反扫兜底。 **首跑日实录(2026-09-07)**: daily 全量(ann/news 各 6168/6168 unit+fulltext 2478 洪峰 墙钟截断)→backfill ①ann 到 5542/6168 时巨潮 502 连击(15:45~15:47,服务端故障 rate_limited=False)触发域冷却——fail-closed 不标 done,无缝切 ②news(eastmoney 不受 波及)跑至 17:30 墙钟,rc=1 由次日自愈(设计内行为)。当日落库:ann_meta 43.0 万行/ news_meta 87.8 万行/news_fulltext 2673 行/PDF 2 份;news depth 已见 2015-05-11(np-listapi 实际可达远深于 2023-09 预估)。**首跑揪出并修复第五项偏差**: 巨潮单次响应同 announcementId 可挂两条(整行相同或 ann_time 差 1 秒),`_filter_new` 批内不比对→双双 落盘成重键行(3 行,verify FAIL)——修=批内 seen 截留(a889b2f)+存量 3 part 原子去重, 修后 verify_corpus 全域 PASS(rows=uniq=ledger)。 **T3 注册收口(2026-09-07 晚)**: 用户 GUI 完成 DSM 任务 `sanguo-corpus-daily` 注册 (每日 06:00/admin/`bash /volume1/stock/corpus/run_corpus.sh`;esynoscheduler.db mtime 18:47 佐证,admin 无权限直读 root 属主 db 属预期)。**至此 T1-T5 全部落地+部署(终版 16f00ff,CI #1134 全绿),采集进入生产节律**: 次日 06:00 首班自愈接力——首跑日 backfill 遗留(ann ①缺口 626/6168 unit+news ②余量)由断点机制自动续拉,502 域冷却随新进程解除。 T6 剩余=多日累积后验收 1-4(5 股抽查/600519 2001 起/news 硬顶/PDF 抽 20 份)+限速 stats 复核+本节完结行。 **首班前夜第六修正(52756e3, day-2 致命坑)**: 复查发现 daily ann/news 增量 marker 无 日期维度——首跑日已写满 6168+6168,次日 06:00 首班将**整段跳过增量采集**(backfill 仍在 跑会掩盖症状,静默断供)。修=增量段 unit 名挂 `dt=YYYY-MM-DD/` 子目录(断点续传只保护 当日)+日初清旧日目录与历史平铺 marker;fulltext/pdf 段键=内容 id(公告/文章不可变, 一次永逸)保持平铺。契约测试三连: 次日重新拉窗承接新数据/当日断点续传语义不变/旧日 目录日初清(274 绿)。教训: **增量型 marker 必须带日期维度,且要在「首个完整周期结束 前」推演第二天行为**——同日幂等测试全绿掩盖了跨日语义。 **首班实录(2026-09-08, 第六修正的实战验证)**: DSM 06:00:01 自动起(功能确认)。 ①day-2 修复生效: ann/news 增量真实拉窗, 新 marker 全落 `dt=2026-09-08/` 下, 昨日平铺 marker 日初清理零残留; ②news 6168/6168 全量扫完(含北交 920 尾段); 全文段 +985 篇 (article 域静默无逐篇日志, 进度信号=marker 数); ③ann 2564/6168+150 失败=**巨潮 cninfo 连续第二日服务端抖动**(昨 502 连击/今 504×150), 触发域冷却 fail-closed, PDF 段随之 跳过; daily rc=1 → backfill 让路(设计内)。**零永久丢失双兜底**: 未标 done unit 明晨 重拉, 窗内漏掉的公告由 backfill ①(股,年) 全年扫终会收; ④同晨 dmsk(07:33)与 corpus (06:00-10:14)并行无扰=东财端点分域假设实证。观察项: 巨潮抖动若持续数日→升级源端 健康度问题(备选: ann 增量段错峰避开其故障高峰)。 ## 19. 增补 2026-09-07:财务数据域(财务136)——存量搬运+同步增量架构(本节为最新,覆盖本节初版「全 NAS 自采」方向) ### 19.0 背景与方向修正 factor session goal「完成财务136,部署在nas上,并验证成功」(用户 2026-09-07 设),数据层归数据 session。初版方向「全 NAS 自采」被用户当晚纠偏推翻:原话要点「这些内容数据 session 已经下载 过了,先问清楚哪些下载过了哪些没下载过,**不要上去就全量下载新的数据**」——VPS static 七域 本就是本 session 建的 akshare 体系。「零 VPS」重定义=**运行时形态**(NAS 本地 parquet 独立 可用,策略/因子读 NAS 不经 VPS),不否定存量复用与 VPS 作为上游采集器。 ### 19.1 存量盘点(2026-09-07 只读实测,VPS C:\sanguo_vnpy_v2\data\static\) | 域 | 覆盖 | 最新 | 质量 | |---|---|---|---| | balance | 沪深 5215 只(319 列,银行 221 模板)回溯 1989 | 2026-06-30 ✓ | **北交 340 文件全空 (0,0)=09-01 空 dump 残留** | | income | 同 5215(203 列) | 2026-06-30 ✓ | 北交同采集器同命运(搬运时逐文件过滤) | | cashflow | 同 5215(254 列) | 2026-06-30 ✓ | 同上 | | financial_abstract | 5559 含北交 343 **有数据**(80 指标×期宽表,回溯 1998) | 20260630 ✓ | 无 | | valuation | 5559 含北交 343 **有数据**(13 列中文名,日频~2100 行/股) | 日更(ak-daily 19:00 喂) | akshare 改名列,非 raw 22 列,原样搬 | | forecast | 26 期按期全市场文件(2020Q1→2026Q2) | 2026-06-30 ✓ | 2020 前无(可选补) | | express | 同 26 期 | ✓ | 同上 | **采集机制现状**: valuation/abstract/事件域=`sanguo-ak-daily` 每日 19:00;三表+forecast/ express=`sanguo-ak-monthly` 首个周六全量洗库(下次 11/7 02:00,55h 跑道=09-01 事故根治) → **三表季频新鲜度=披露后最多~5 周**(Q3 数据 11/7 入库)。若因子批需披露周可用,VPS 侧 加密(10 月底补跑/改 NOTICE_DATE 增量)——**挂起决策,因子侧与用户定,本 session 不擅动 VPS 调度**。 **真缺口清单**(对 corpus 池 6168=沪深 5570+北交 598,差 613 拆解): 1. 沪深退市 **355 只**全周期缺(F10 实测拉 000003 也空,按期接口是唯一源); 2. 北交退市 **258 只**同缺; 3. 北交现役 340 只三表=空文件(数据在按期接口可取); 4. forecast/express 2020 前历史(可选,按期接口顺手)。 ### 19.2 接口契约(11 发实测保留,定位重排) | 域 | 接口 | 实测要点 | 新定位 | |---|---|---|---| | dmsk 按期 | datacenter `RPT_DMSK_FN_{BALANCE,INCOME,CASHFLOW}` `filter=(REPORT_DATE='单期')` | 全市场单期≈5223 行,pageSize500≈12页;2009 年报 2520 行(akshare docstring「2010 起」过时);57 列含 NOTICE_DATE;**含彼时在市后退市股** | **补缺层**(§19.4) | | f10 按股 | emweb PC_HSF10 | 319/203/254 列全史;dates=5 期/发服务端硬顶;回溯 1992;老退市股空 | **全量回补作废**(VPS 存量已有,增量走同步) | | valuation | datacenter `RPT_VALUEANALYSIS_DET` | 按股全史 1 发+全市场单日快照~5556 行 | 不采集(VPS 日更存量+同步) | | abstract | 新浪 `CompanyFinanceService` | 按股 1 发全史 | 不采集(VPS 日更存量+同步) | | forecast/express | datacenter 按期全市场(ak yjyg/yjkb 契约) | 26 期形态已按期 | 2020 前可选补(同 dmsk 族) | ### 19.3 架构定稿:存量搬运+phase3 同步增量+按期补缺 ``` VPS(上游采集器,ak-daily/ak-monthly 继续喂,零改动) │ ①一次性搬运 4.22GB(跳过北交空文件) │ ②phase3 03:00 链扩域:七域增量 rsync(月度洗库整文件重写天然被 mtime 增量捕获) ▼ NAS /volume1/stock/fundamentals/ ← 运行时 NAS 独立可用 static 原形态: {balance,income,cashflow,financial_abstract,forecast,express,valuation}/ ._.parquet (文件名/列名原样,零转换) 补缺层: dmsk/{balance,income,cashflow,forecast,express}/dt=/part-*.parquet state/ (补缺层 marker+账本) ``` **增量分工三线**: ①VPS 侧零改动(ak-daily/monthly 继续喂全列基线,月度洗库 5 周延迟= 因子验证零影响,factor 需求方已确认);②phase3 03:00 链扩域=基线层同步(七域 rsync,月度 洗库整文件重写天然被 mtime 增量捕获);③**dmsk daily 重扫=新鲜度补丁层**(见 §19.4,DSM `sanguo-fundamentals-daily` 07:10,错峰 corpus 06:00——东财端点分域+各自限速,并发重叠 安全依据同 corpus)。北交空文件在搬运时过滤(shape==(0,0) 跳过,防下游误读)。「VPS 零参与」 让位于「VPS 零新增负担」:miniQMT 09-18 停服不影响 akshare 线,ak-daily/monthly 健康 运行(事故均已根治)。**下游读法**: 基线层(全列,≤5 周延迟)为主,dmsk 层(57 列核心科目, 披露次日)做新鲜度补丁与退市/北交覆盖。 ### 19.4 dmsk 层双用途(`fundamentals_dmsk_download.py`,corpus 骨架复用) **用途一·补缺(一次性 backfill lane)**: 全期回补 2009→今 ~66 期×3 表(≈2200 发≈1.5h, 可断点续跑)——补沪深退市 355+北交退市 258+北交现役三表 340 空档;forecast/express 2020 前历史=**可选 backlog 不阻塞 goal**。北交所含性实施首日验证(filter 的 SECURITY_TYPE_CODE 集合,不含则北交补缺单列说明)。 **用途二·新鲜度(daily lane,DSM 07:10)**: 近 3 期重扫+`NOTICE_DATE>=T-7` 增量行(~40 发 /日,季报月自然加密)——披露次日即可用(57 列核心科目够选股),不等 VPS 月度洗库。增量 unit=REPORT_DATE 一次永逸按期 marker;行键 (SECURITY_CODE,REPORT_DATE) 幂等去重; 批内去重/失败不写不标/账本+marker 次序等 corpus 六修正全带入。 ### 19.5 验证三维(factor 持 goal 验收,锚点=factor session `fund136-acceptance-anchors.md`) ①覆盖: NAS 侧七域文件数/期数分布/NAS 与 VPS 逐域 count 对账(搬运完整性)+dmsk 补缺后 corpus 池 6168 覆盖率(北交三表从空→有,退市股从缺→有);②正确性: 600519 锚点(balance 103 期/2024 归母权益 2331.06 亿/归母净利 862.28 亿)+VPS 存量抽样只读对照(派单已约定 豁免);③可用性: NAS 容器内单股全历史读取秒级(7 域各抽 1 股)。 ### 19.6 实施步骤(每步一 commit 标 [nas]) W1 搬运通道: VPS→NAS 一次性 rsync 七域(跳空文件)+逐域 count 对账 → W2 phase3 扩域: 同步链加七域增量(每日 03:00) → W3 dmsk 脚本双 lane+测试(全 mock 零网络)+wrapper+DSM 07:10 注册 → W4 dmsk backfill 全期回补(1.5h)+北交所含性验证+daily lane 首跑 → W5 三维 验证+factor NAS 实测验收+本节实施记录。预期: W1-W2 当日完成=NAS 立即可用;W3-W4 一日 内;总量级 4.22GB 搬运+2200 发一次性+40 发/日,无 2-3 周长尾(初版 f10 全量回补 21 万发 已作废)。语料库首班(09-08 06:00)全程绝对优先,财务 W1 起步于首班巡检绿之后。 ### 19.7 基准反转补丁(2026-09-07 深夜,用户二次纠偏「假设 NAS 最全,盘点 NAS 看差多少」) **NAS 全景实测**(只读): ①`data/static/` 16.5 万 parquet=**phase3 镜像树**(04:00 链, valuation 今日刚同步/三表 09-06 全量),七域覆盖≡VPS(沪深 5215 有效+北交 340 空+零退市) ——**§19.3 的「一次性搬运」与「phase3 扩域」两项取消**(镜像已在且日更,搬运本来就 免费发生在链上); ②**`data/valuation_baostock/` 按年 1990→2026 日频估值=NAS 独有深度** (10 列 peTTM/psTTM/pcfNcfTTM/pbMRQ/turn/pctChg/isST;**含退市股**——000003 存活年份 478 行/年实测;新鲜到 T-1,bs-daily 日喂)=用户「NAS 比 VPS 全」直觉的真实来源,纳为 第 8 验证域; ③`data/fundamentals_baostock/` profit+dupont 季频指标 5357 股 2015Q1→**2023Q4 断更**(七域外,数据 session 单列待查,不动本 goal scope); ④`A股数据/ 财务数据/`=v1 死残留(1438 深市估值+年度空骨架),不采信;`#recycle/` 排除。 **修订后唯一新工作**=dmsk 补缺层(§19.4 不变)+三维验证(§19.5 改在 NAS 镜像路径 `/volume1/stock/sanguo_vnpy_v2/data/static/` 验,+valuation_baostock 第 8 域)。 缺口结论不变: 沪深退市 355+北交退市 258 三表缺(其日频估值已被 baostock 树覆盖)+ 北交现役 340 空+forecast/express 2020 前可选。 ### 19.8 实施记录(2026-09-08 凌晨) - **W1' 镜像对账全绿**: 七域 count(三表各 5555=5215 沪深有效+340 北交 920xxx 零行空档,挂 .SZ 后缀=09-01 空 dump 残留;abstract/valuation 5557;forecast/ express 26 期)+600519 四锚点容器内复验逐位一致+读取 0.99s。第 8 域 valuation_baostock: 1990→2025 完整(2025 实测 1.25M 行/243 天/5211 股,含退市); **2026 文件仅 08-13 起**(bs 日喂起点)→ 2026 H1 估值缺口由基线层 valuation 覆盖,H1 回补列可选 backlog。 - **W3' dmsk 双 lane 落地**: `fundamentals_dmsk_download.py`(单脚本红线,corpus 骨架复用+六修正全带入)+21 测全 mock 绿+`run_dmsk_standalone.sh`(DSM `sanguo-fundamentals-daily` 07:10,一次性容器 sanguo-fund-dmsk,corpus 同款 --user 1024:100 --group-add 101)+`verify_dmsk.py`(键唯一硬门只读验收)。 落库=/volume1/stock/fundamentals/dmsk/{域}/dt=期/part-*.parquet,**绝不写镜像树**。 - **§19.4 marker 语义修正**: 原文「daily 增量 unit=REPORT_DATE 一次永逸按期 marker」有 day-2 同款坑(次日重扫被跳过漏新披露行,corpus 52756e3 教训)——实施 改为 daily marker 按日折叠(dt=子目录+日初清理);backfill 期 marker 才是一次 永逸(期内容历史不可变)。marker 键=域+期(域缺席会让后续域被首域 marker 连带 跳过,首测抓出)。 - **次新期金丝雀**: 东财把「filter 契约失效」与「合法空期」都回 result=None 无法区分→次新期(全市场已披露 3+ 月)空=契约漂移按失败处理不标 done,防整段 静默空跑标 done。 - **profit/dupont「断更」系误诊,09-08 晨撤回**: 09-07 深夜读到 NAS 副本止于 2023Q4 判为「一次性回补从未接日喂」——错。实况=bs_fundamentals.py P2 按季回灌 **在行军中**(state next_quarter 逐夜推进,昨夜至 2024Q3 指针, NAS 副本随 04:00 链日同步滞后一拍),剩 2024Q3→2026Q2 共 10 季 ≈5 晚(≈09-13)自愈,之后 P1 增量 (当季+上一季每晚 sweep, 幂等 keep-last)自动接管。**教训: 判「断更」前必须先读 生产脚本的续喂设计与 state 文件 mtime——「数据末端=快照」≠「管线已死」**。 原批「5.2 万发季度追赶」取消(重复采集+并发撞 baostock 双连接红线,有害无益)。 **W4' 完成终态(2026-09-08 02:18)**: backfill 210 unit/1771 发/5680s/零失败 rc=0,70 期×3 表全落库(27.1万/28.0万/28.0万行);**verify PASS=键唯一 0 重键** (硬门),BJ 行 1.04万-1.15万/域(北交所含性实证);**净新增 383 只**镜像外代码 (dmsk_codes=5598 vs 镜像有效 5215)=2009 年后退市+镜像空档股,补缺目标达成。 daily lane 首跑(00:42)符合设计: 近3期重扫 2 分钟,+10/+7/+7 晚披露入账, NOTICE_DATE 5569/5569 非空最新至当日。**已知边界**: 2009 年前退市股(如 000003, 2002 年退)dmsk(2009 起)与 F10(拉老退市也空)双源皆无=源头缺失, 无免费方案,如实记档。翻页坑: 东财 datacenter 用 `pageNumber`(cninfo 才是 pageNum),误用被静默忽略=12 页全回第一页,冒烟 +500/6000 实锤后修(d71ee55)。 DSM `sanguo-fundamentals-daily` 07:10 已由用户 GUI 注册(09-08 晨)并手动首跑验证: 07:33 start → daily `units=0 rc=0`(昨夜 00:42 手动 wrapper 已采过当日, 按日幂等跳过 语义正确)→ backfill `units=0 rc=0`(210 期 marker 全 done 纯 no-op)→ 容器干净退出。 明起 07:10 自动班。 ### 19.9 基本面数据链运行节律总览(2026-09-08 终态速查,细节见各节) | 层 | 源/接口 | 下载方式 | 增量机制 | 新鲜度 | 自愈/兜底 | |---|---|---|---|---|---| | 三表基线层
§19.1/19.3 | akshare f10(emweb)按股全史
(319/203/254 列,沪深 5215) | VPS `ak-monthly` 首个周六全量洗库(55h 跑道) | 月度整文件重写;phase3 04:00 链按 mtime 增量同步 NAS 镜像树 | 季频≤5 周(验证场景可接受) | 洗库失败返 None 不写不标(09-01 事故根治);valuation/abstract 另有 ak-daily 19:00 日更 | | 三表补缺/新鲜层
§19.4 | 东财 datacenter `RPT_DMSK_FN_*` 按期全市场(57 列含 NOTICE_DATE,含退市+北交) | NAS 一次性 backfill≈2200 发(**09-08 完成**:210 unit/1771 发/零失败) | daily(07:10):近 3 期重扫+`NOTICE_DATE>=T-7` 客户端过滤,账本键幂等 | **披露次日** | marker 按日折叠(daily)/一次永逸(backfill 期);批内去重;次新期金丝雀防契约漂移(都回 result=None 不分) | | forecast/express | datacenter 按期 | 26 期按期文件(2020Q1 起) | 随 ak-monthly 洗库 | 同三表 | 2020 前历史=可选 backlog(dmsk 族同接口可补) | | profit/dupont
(baostock) | bs `query_profit/dupont_data` 按股按季 | VPS `bs-daily` 18:05 fund 腿:P2 按季回灌(state 逐夜推进,~2 季/晚,**≈09-13 跑完**)→P1 接管 | P1=每晚拉当季+上一季 sweep;幂等键 (code,pubDate,statDate) keep-last(重述后写胜) | 季频次日 | DAILY_CAP=30000(与 eod 合计≤41k<48k 铁律);P3 forecast/express 月首周日全区间 | | valuation_baostock
§19.7 第 8 域 | bs 日频估值(peTTM/psTTM/pcf/pbMRQ/turn/isST,1990 起**含退市**) | bs-daily fund 腿日喂 | 每日追加当年按年 parquet | T-1 | **2026 文件 08-13 起**(日喂起点,H1 缺口由基线层 valuation 覆盖;回补列可选) | | 语料库
§18 | 巨潮公告+东财新闻 | 首跑+backfill 四段(ann 43 万/news 88 万/PDF 六类) | daily 四段:ann T-1~T 窗/news recent-100/全文(当日新稿)/PDF(五服务端码+快报标题谓词) | 当日/次日 | 按日 marker+域冷却 fail-closed 其他域继续+backfill (股,年) 全年扫终兜;flock 单实例 | **层间读法(双层口径, §19.7 写死)**: 回测全历史=基线层为主(全列)+dmsk 补退市/北交段; 季频选股要新鲜=dmsk 层近 3 期优先,基线层兜全列。**已知边界**: 2009 年前退市股(000003 等) 三表 dmsk 与 F10 双源皆无=源头缺失(其日频估值仍被 baostock 树覆盖)。**采集纪律**: 东财 datacenter 1.5s/巨潮 1.0s/东财 search 1.0s/article 2.0s 慢爬,直连不走代理, 日间带 00:30-17:30 语义,baostock 同 IP 单连接 48000 次/天。 ## 参考(调查来源) - 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`