Files
sanguo_vnpy_v2/docs/superpowers/specs/2026-07-21-data-source-fusion-design.md
T
claude_dev b24f90549f
CI/CD / test (push) Successful in 42s
CI/CD / nas-deploy (push) Successful in 5s
CI/CD / nas-verify (push) Successful in 9s
fix(data): 监控日历假定集剔交易所休市表日——连休假黄根治+CI 跨年强制年更 [vps]
根治 valuation_baostock/dbbardata_daily/dbbardata_index 三域国庆连休天天假黄:
- monitor_registry.EXCHANGE_HOLIDAYS 年度休市表(仅工作日): 2026 表=dbbardata
  000300 实证(至 1002)+交易所 2026-09-17 公告(中秋 0925~27/国庆 1001~1007 休,
  10-08[周四]复市——勘正全员「10-09 开盘」旧误记)
- data_monitor._calendar_days: 假定集剔休市日(已知假日=零期望当夜即绿);
  fail-safe=表缺年不扣(黄照旧绝不静默转绿); 确认集恒保留(表错不吞真相)
- CI 年更闸 test_holiday_table_covers_current_year: 当年无表即红(25063ca
  禁裸墙钟教条的故意例外); 场景日随休市表重定向三测(0925 已知假日走绿路径,
  未登记日容忍语义改 0924 钉)
- TDD 4 新测, data_platform 682 绿; spec §20.15.2+runbook 同步
2026-10-03 18:17:01 +08:00

178 KiB
Raw Blame History

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(逻辑融合)

接口:

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 — 策略增强

  1. 申万行业 SW1/2/3(xtdata get_sector_list)+ 历史变动
  2. 龙虎榜(xtdata get_longhubang)
  3. 合约信息涨跌停/ST(xtdata get_instrument_detail)全 A 入库
  4. 可转债(akshare bond_zh_hs_cov_min + 转股价调整)
  5. 研报/一致预期 EPS(akshare stock_research_info_em)

P2 — 按需

  1. 股东户数 / 除权明细 / 业绩快报 / 大宗交易 / 宏观 / 期货

融合层(贯穿)

  1. 归一化库(vt_symbol/exchange/factor/volume 映射)
  2. LocalUnifiedProvider(读权威表 + 归一化 + 网络兜底)
  3. 完整度监控报表(每类覆盖率/缺口,源退化早发现)

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/.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(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(列名已英文化 [name,code], akshare 版本演进; 列名零清洗契约下合法, 消费方勿按中文列名硬编码) 同上 ~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 原样落盘
  • 交易日闸门(2026-09-25 中秋休市实案/10-01 国庆预防): EM datacenter 事件类(dragon_tiger/block_trade/restricted)对非交易日查询返 NoneType 异常≠空 df→3 retry 耗尽 failed 计断路器+retry 班整晚空转;pledge_ratio 休市周五锚同理 failed 挂到下个真交易日才自愈。修=akshare_static_download 启动时载 sina 官方交易日历(trade_calendar.txt 当日缓存跨班共享),闸门两处——①事件类非交易日 unit 的 fetch 替换为空 df(走既有 empty 写空+done,零新代码路径,日历覆盖窗外 unit 不动防历史回补误伤)②pledge_ratio 枚举剔除非交易日周五。日历加载失败→None 降级直跑(闸门失灵只回到误报,不会漏采)。白名单含 margin/margin_sse(09-27 🟢-12:margin_sse 假 T-1=休市周五踩 NoneType)。
  • 字段形状类失败快速失败+断路器豁免(09-27 审计终局 P2): 源缺列/字段变更(KeyError/TypeError 族,含节假日 EM NoneType)为确定性失败——重试无益 1 次即抛 AkShapeError 透传 download 层标 soft: failed 计数保留(监控可见)、不计 consec_fail 断路器豁免、不写 marker 次周重试(防次新股未来有数据被空文件+done 锁死, gdhs 披露守卫同款坑)。实案=09-19/09-26(追认 09-05/09-12)share_capital 次新股『公告日期』KeyError 群 30 连熔断, 连坐跳过 top_holders(四周六零刷新)/financial_abstract(挪入后零刷新)。纵深第二层=ak-weekly 类型序 fa/top_holders 提到 share_capital 前(VPS schtask 动作,随部署班车)
  • 缺日防线(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) 保真底座:白名单 19 类统一通道(§15.2 per-date 全族+gdhs;10-01 二审勘正:09-12 四域漏同步已补齐,同步义务钉死 test_whitelist_sync),研究/因子探索用 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 已于 09-04 挂载入白名单(原「拍板后三处同步加」注记兑现;09-25 起采集迁 NAS 回推,§20.14)
  • 新数据类型接入=底座白名单加一行(零新方法)+test_whitelist_sync 钉死同步义务(10-01 二审:09-12 四域漏同步即此病);nb_hold=季频 asof 语义(快照仅季末变更日落文件)不进 exact-date 底座;某域有消费契约后再升格门面(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 回补 07220901(30/30 ok 59865 行, VPS+NAS 双端);②wrapper 拆 margin_sse 单独 **T-1T 两天窗**(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/archive/reports/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 侧永远不会被调度。**(09-17 修订,§20.11)**采集仍 100% NAS、VPS 零 schtask/零采集进程不变;唯一放宽=「零存储」→ VPS 持每日 只读镜像副本(corpus 四子域+dmsk,382M 级日更),推送任务在 NAS 侧调度。
  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-uid> → 输出文件 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/<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 身份跑,机制=与 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 <admin-uid> --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 留痕)。09-19 勘误(续走闸门):daily rc∈0|1|3 都续走 backfill,仅 rc=2(限流) 跳过——corpus_download.py rc() 优先级 failed>0>墙钟,「墙停+failed≥1(实盘 3~113/13000 噪声级)」报 1 不报 3,实证 11 个 daily 腿 10 天 rc=1;旧 0|3 闸门=backfill 饿 4 天(2025 积压 堆积+当日墙停残余无兜底)+尾部镜像推送永不触达(见 §20.11.2 同日勘误)。--name sanguo-corpus=运维锚点:杀进程=docker stop sanguo-corpus(admin 一条命令);--user <admin-uid>=输出文件 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-1T 两天窗+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 <uid> 跑通 镜像 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 全局下载方案与存放位置总表(回应「不想搞好几套」——分工总览;调度任务名/时刻现势以 §20.10.2 为准)

一条规则,不是几套方案:每类数据唯一权威源+唯一权威位置(§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-daily VPS 21:00(旧名 xt-eod/旧时 18:40,08-20 更名+09-12 错峰勘误归一) xtdata ETF+个股当日实时 dbbardata
sanguo-idx-eod VPS 每日 指数点位 SSE 表
sanguo-ak-daily VPS 19:00(10-01 二审勘正:07:35 为设计期旧值,VPS 实查 19:00) akshare 低频日更 static/
sanguo-ak-events VPS 19:30 A 档 per-date 全族事件面板(清单权威=采集注册表 PER_DATE_TYPES;hot_rank 09-25 迁 NAS §20.14;时间守卫) 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}/
                  <code>.<EXCH>_<domain>.parquet  (文件名/列名原样,零转换)
   补缺层: dmsk/{balance,income,cashflow,forecast,express}/dt=<REPORT_DATE>/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 树覆盖)。 09-20 勘误(§20.11.7): 新鲜度改由事件驱动补洗根治——基线层自身披露次日全列新鲜, dmsk 层角色收敛=披露雷达+forecast/express+RATIO 列+退市/北交段;「两层合并」设计取消。采集纪律: 东财 datacenter 1.5s/巨潮 1.0s/东财 search 1.0s/article 2.0s 慢爬,直连不走代理, 日间带 00:30-17:30 语义,baostock 同 IP 单连接 48000 次/天。

19.10 因子 P1 批五域支持(2026-09-08,factor 派单回执)

P1 二批 5 因子所需 5 域读取契约(真文件勘测 VPS+NAS,容器复验读通)。NAS 运行时根 /volume1/stock/sanguo_vnpy_v2/data/(static 树即 P0 --fund-data-dir 所指):

域 路径/命名 主键 PIT 列 覆盖与坑
dividend static/dividend/{code}.{SH|SZ}_dividend.parquet(5538 只) (code,分红事件行) dividPlanAnnounceDate(可空,回退链 PreNotice→AgmPum→Plan,全空丢行) baostock 静态快照 2020→2026-07,无增量 lane(2027 前开);code 列=sh.600519 小写格式;沪深含退市,无北交
gdhs static/gdhs/{YYYYMMDD}_gdhs.parquet(53 期) (代码,统计截止日-本次) 公告日期 2013Q1→2026Q1(09-08 补史 44 期/15.4 万行,源头边界 2013Q1 实测钉死,2012Q4 前东财无数据);「本次/上次」截止日不规则→增减比例≠统一季环比,消费方自建事件表自算 Δln;ak-weekly 滚动 3 年窗喂新期(披露守卫 90 天)
top_holders static/top_holders/{code}.{EXC}_{期}_top_holders.parquet(10.9 万文件) (code,期,名次) 无公告日列→法定披露截止近似(Q1→04-30/H1→08-31/Q3→10-31/年报→次年04-30) 2021Q3→2026Q2(09-09 修订:原 2020Q1 契约口径与 NAS 镜像实测不符——108,610 文件首期 20210930,5431 文件/期整齐步进;后果=fund_topholder_chg 首期无差分 2022 年中才生效,合成层 v1 已剔该源);增减列混「不变」字符串;占比=%单位;北交排除
financial_abstract static/financial_abstract/{code}.{EXC}_*.parquet(5559 只) (指标,报告期)——转置宽表(行=80 指标,列=报告期) 无 NOTICE_DATE,直接用有前视风险 1998→2026Q2;E08 已定改三表自算 CCC(复用 NOTICE_DATE PIT),本域只作对账源;ak-daily 19:00 日更
valuation_baostock data/valuation_baostock/{year}.parquet(static 兄弟目录) (symbol,date) 日频即点时 1990→2026 含退市(000003 实测在);2026 仅 08-13 起,H1 缺口=基线层 em valuation 补;亏损/净资负 peTTM、pbMRQ=NaN;date 为字符串

gdhs 补史实施: akshare_static_download.py --gdhs-start 20130331(040a39e,枚举外扩+marker 幂等,TDD 23 测绿),VPS 一趟 44/44 ok/154031 行/104s,VPS+NAS 双侧 53 期对齐。同步链同日 两修一加固: ①dir /b 枚举 CRLF 清洗(a37d324——此前 6 天文件名尾粘回车符 scp 静默失败, NAS 空目录) ②257bd3b 引入注释断行语法死(裸引号未闭合致整脚本 parse 失败,bash -n 抓出, 7195aa6 修回)——shell 改完必跑 bash -n,CI 只覆盖 pytest 救不了 shell ③skip-if-exists (期文件 write-once,53 文件无需每日重拉)。

19.11 P1 支持决策记录 + 可选 backlog 设计(2026-09-08 晚,用户拍板 compact 后执行)

决策记录(factor×data 双方落定):

  • gdhs 补史=做,已落地(§19.10);源头边界 2013Q1 实测钉死,更早无免费方案,如实记档
  • dividend 2027 增量=当期不做(YAGNI),方案留 backlog-c
  • E08 CCC=三表自算(DSO+DIO−DPO,复用 NOTICE_DATE PIT);financial_abstract 不作因子源 (转置宽表无披露日,直接用有前视风险),降级为对账源
  • E12 gdhs=消费方自建事件表 (代码,统计截止日-本次)→股东户数-本次,PIT=公告日期,自算相邻 Δln——现成「增减比例」列因本次/上次截止日不规则(每股不同)不能当统一季环比
  • 派生聚合边界: static 树只由采集层写;下游预聚合(如 top_holders 十大占比)一律落消费方 独立目录(factor_cache 类),绝不写 static 树
  • parquet 日线 lane(data/{raw,qfq},daily_update_xtdata.py)07-22 方案A 定稿日退役: dbbardata 唯一行情表;脚本保留作工具、无 schtask(09-08 勘误定性,迁移文档 §6.5 同步)

可选 backlog(已设计,执行序 a→b,c 轻量收编):

a. valuation_baostock 2026 H1 回补: 2026.parquet 仅 08-13 起(bs 日喂起点),H1 靠基线层 em valuation 覆盖(异源口径)。方案=baostock query_history_k_data_plus 按 (股, 2026-01-01→08-12) 拉 10 列估值字段→与现有 2026.parquet concat+drop_duplicates(symbol,date) →原子写回(窗止 08-12 与现有段零重叠,不用 keep-last 仲裁);股票名单=当前全列表∪ query_all_stock(2026-06-30) 时点列表(保 H1 退市股)。成本≈5200 发(48000/天预算内, 单连接单线程≈2-3h)。验收=行数≈5211×H1 交易日+600519 抽锚+(symbol,date) 键唯一。 价值=D14 长史 EP/BP 的 baostock 统一口径跨 2026 连续。

b. forecast/express 2020 前历史: 现状 26 期(2020Q1 起)。方案=fundamentals_dmsk_download.py DOMAINS 扩 forecast/express 两域(同 datacenter 骨架:pageNumber 翻页+按期 marker+账本, 族内扩展不破单脚本红线),backfill 补可得最早期→2019Q4。先探源头边界再定回补深度 (同 gdhs 2013Q1 探法);早期预告披露规则不同(主板触线才强制)行数天然少=正常,空期判定 走次新期金丝雀同款(空≠契约漂移须区分)。成本≈50 期×3-5 页≈250 发。验收=有货期行数>0+ 键唯一+披露日列非空;落 NAS dmsk 树(forecast/express 子域)与基线层按期文件并存,读法 =基线层为主、dmsk 层补缺(与三表同款双层口径)。

c. dividend 增量收编(轻量): legacy Day2b 快照(2020→2026-07)继续用;分红事件低频且 年度集中(4-7 月),年度刷新比每日增量合身——2027-01 再议把年度刷新挂进 baostock 年度任务;当期零动作。

19.11.1 backlog 执行记录(2026-09-09,三项闭环)

  • a. valuation_baostock 2026 H1 回补 ✅ (150465a): bs_eod.py --backfill-valuation START END——只拉估值 9 列(无 OHLCV,不动 dbbardata);名单=全A含退市∪query_all_stock (窗口中点日)时点快照;断点序=buffer 落盘先、done 后写(崩=整批重拉幂等);终局 merge_valuation_frames(keep='last' 同 upsert_daily 语义)+os.replace 原子写回;中间产物 落 data/_backfill_valuation/{tag}/(独立目录,避开 sync_valuation_daily 的 scp -r 整目录拉取面)。09-09 09:35 schtask 一趟 7545 发零失败 82min,merge 93,678→1,131,834 行键唯一;验收=600519 锚 165 行 peTTM≈20.2 对公开口径/H1 日均 7062 行(含退市名单, 大于现存 5216 属预期)/10 列 schema 不变。一次性 schtask 已删,buffer 已清;NAS 由 03:09 链自动传播(09-10 晨到)。
  • b. forecast/express 补史 ✅ (f78e8f1): DOMAINS 扩两域;边界探针实测 forecast 2003 年报起(458 行)/express 2005 年报起(133 行),2002 及更早东财返空——per-domain BACKFILL_FROM{balance:2009,forecast:2003,express:2005}+backfill_from_year() (--start-year 显式覆盖优先)。键分域: forecast 4 键 (SECURITY_CODE,REPORT_DATE, NOTICE_DATE,PREDICT_FINANCE_CODE)——同股同期同披露日多指标行(EPS 003+净利 004 并存)+多次修正史全保留,2019 年报 3646 行实测唯一;express 3 键(含 NOTICE_DATE, 2528 行实测唯一);两域 NOTICE_DATE 全期实测非空。verify_dmsk 同步五域键唯一。 09-09 11:51 手动触发 NAS run_dmsk.sh(日常 07:10 DSM 班次日自动接续);daily lane 识别 forecast 4897 行与探针精确一致。读法不变:基线层为主、dmsk 层补缺。
  • c. dividend 收编 ✅零动作备案: legacy Day2b 快照继续用;2027-01 再议年度刷新挂 baostock 年度任务。
  • 晨间三验收(09-09): xt_eod 09-07 缺口自愈绿(3353/4012/39 对齐 09-04 形态); 09-08 只补 30%(1040/1122/39)由 LOOKBACK=30 窗口当晚再扫自愈;dmsk 07:10 首个全自动 班绿(daily 178s/9 unit/108 发零失败);巨潮 504 连续三日抖动(failed 18→150→113, 全 ann 单元网关 504,<1%,不标 done 次日重试不丢数据)——已升级报用户待拍板。

20. 增补 2026-09-12:四域扩展(两融/申万/龙虎榜席位/北向)——用户拍板「本地数据越全越好」

20.0 拍板与勘测依据

用户 09-12 拍板(最高指令):「不用管因子,本地数据越全越好,怎么消费是其他 session 的事」—— factor 排序作废,四域全部融合进现有数据体系;北向做二次探针看能做到多细(已完成,见 20.4)。 实施顺序按 data 侧性价比:两融 > 申万 > 龙虎榜席位 > 北向。

勘测实测结论(2026-09-11/12 探针,venv310 直连清代理):

域 渠道(实测) 深度 单夜请求量
两融个股明细 东财 datacenter RPTA_WEB_RZRQ_GGMX(filter SCODE 600519 实测 3,979 行=2010-03-31→今 16 年日度;filter DATE 单日全市场 ~3,300 行/7 页) 2010-03-31 起 日采 7 页;16 年回补 ~3,900 交易日×7≈27k 发
申万行业 akshare sw_index_first_info(31 一级)+index_component_sw(31 发)(成分+最新权重+计入日期=部分变更史) 仅当前快照(计入日期带部分史) 32 发
龙虎榜席位 东财 RPT_BILLBOARD_DAILYDETAILSBUY/SELL(每日上榜股×买卖席位明细);主表 2020-01-01 起 1,748 日文件已在库 增量(全史席位=~50 万发不可行) ~120-200 发
北向 见 20.4 粒度极限 官方=季度频/12 个月窗 3 发

20.1 架构红线延续(对齐 §15)

  • §15.1 单脚本注册表零新采集脚本(用户钦定):四域全部注册进 akshare_static_download.py TYPES + fetch 函数,不新建任何脚本。
  • 全部落 data/static/<type>/ per-date parquet+marker → §16 泛型底座 get_event_panel 白名单一行即读(10-01 二审勘正:原写「零改动自动可读」落空—— 09-12 四域注册采集时漏同步 EVENT_PANEL_TYPES,本波补齐 margin/sw_industry/ dragon_tiger_seats/nb_daily 并以 test_whitelist_sync 钉死;nb_hold 季频 asof 语义不进底座)。
  • 不碰 dbbardata(非行情,事件/截面族);不碰 constituent_unified(不动守护库; 申万走快照域模式,变更史由逐日快照+计入日期列承担)。
  • 东财直连纪律:RPTA/RPT_BILLBOARD datacenter 家族串行、复用 session、 间隔 ≥1.2s+抖动(§15.3 墙模型:5 分钟 ≥300 发触发封禁,1.2s 间隔≈250 发/5min 在线下)。
  • 僵尸退役备案:PER_STOCK_TYPES 的 northbound(akshare stock_hsgt_individual_em, EM 已下线)——ak_eod wrapper 早已不跑该类型,零运行时影响,仅注册表注释标记 deprecated(2024-08 后 EM 个股级北向历史已无,见 20.4)。

20.2 新域清单(全挂 ak_events 19:30 夜班,快照域语义对齐 §15.2)

type 模式 来源 节律 文件
margin per-date EM RPTA_WEB_RZRQ_GGMX filter DATE,7 页×500 T-1~T 窗(margin_sse 同款;EM 两融 T 日晚间供应,当天失败不写不标次夜补) {date}_margin.parquet
sw_industry per-date 快照 sw_index_first_info+index_component_sw×31 T~T(快照,§15.2 快照语义:无历史无回补,date 仅命名) {date}_sw_industry.parquet
dragon_tiger_seats per-date EM RPT_BILLBOARD_DAILYDETAILSBUY/SELL 每上榜股 2 发 T-1T(与主表 dragon_tiger 的 TT 并存:席位供应晚,保守窗) {date}_dragon_tiger_seats.parquet
nb_hold 快照(季度实频) HKEX www3.hkexnews.hk/sdw/search/mutualmarket_c.aspx 两步 POST(沪默认/深 ?t=sz),全表单请求 每夜 2 发查询;内容 hash 与已存快照不同才写,文件名=数据所属季度末日 {quarter_end}_nb_hold.parquet
nb_daily per-date HKEX data_tab_daily_{date}c.js(成交总额/额度/十大活跃股) T-1 拉(当日 js 盘后才出) {date}_nb_daily.parquet

20.3 各域 schema(列名随 EM/HKEX 原字段直存,双层读法写死)

  • margin: 行=两融标的×日(2,000/日 2026-09 实测,历史均量更高中枢下移;monitor band 1,5002,500=现势口径,spec 旧值 ~3,300);列 DATE/SCODE/SECURITY_NAME_ABBR/ RZYE(融资余额)/RZMRE(融资买入)/RZCHE(融资偿还)/RQYE(融券余额)/RQMCL(融券卖出)/ RQCHL(融券偿还)/RZRQYE(两融余额)。16 年回补总量级 ~1,300 万行(~400MB parquet)。
  • sw_industry: 行=股票×一级行业(全市场 ~5,400);列 行业代码/行业名/股票代码/股票名/ 权重/计入日期。变更史消费法:逐日快照 diff + 计入日期列(2021-12-13 大搬迁类事件可考)。 派生映射表(2026-09-26, P3 归因契约): export_sw_industry_map.py 取最新快照导出 static/industry/sw_industry_map.parquet 三列[symbol(.SH/.SZ/.BJ 通用形,非 vt_symbol 形,消费端归一)/industry_code 1..31 (按 SW 行业代码升序稳定序数)/industry_name];表内只含 SW 已映射股,消费方 join 不中 → industry_code=0(未分类桶);已登记 data_manifest(sw_industry_map),成分变化罕见 按需重跑即可(幂等覆盖)。
  • dragon_tiger_seats: 行=股票×席位×方向(当日上榜股 ~60-100 只×top5 席位×买/卖); 列 SIDE/TRADE_DATE/SECURITY_CODE/OPERATEDEPT_NAME/BUY/SELL/NET(EM 原字段直存)。
  • nb_hold: 行=沪深股通标的(沪 2,039+深 ~2,269);列 MARKET(sh/sz)/股份代号/名称/ CCASS 持股量/占 A 股总数%/SNAPSHOT_DATE(=文件名季度末日)。
  • nb_daily: 市场合计行(成交总额/买入/卖出/额度)+十大活跃股行(代码/名称/买入/卖出/成交), 从 js tabData 解析,列 MARKET/ITEM/CODE/NAME/VALUE 原样长表。

20.4 北向粒度极限备案(二次探针终审,后续 session 勿再勘测)

  • 制度天花板(HKEX 官方页面原文):「由 2024年8月19日開始,滬港通及深港通下北向交易 (即滬股通和深股通)的市場信息披露…將調整於每季度第五個滬深股通交易日公布上季度末數據」 +「僅提供自 2017年3月17日 的持股紀錄,資料將按持股日期起計保留12個月」。
  • 实测证据:POST txtShareholdingDate=2026/09/11 → 单请求全沪股通 2,039 行 (工商銀行 91398=1,500,902,770 股/0.55%);查 2026/09/04 与 09/11 返回完全相同数值 → 任意日期查询均返回最近季度末快照(当前=2026Q2),日频个股明细 2024-08-16 起永久停发。
  • EM 通道:个股级 RPT_MUTUAL_STOCK_NORTHSTA 三连「服务器繁忙」+akshare 全系 hsgt 持股函数 NoneType → 已下线;参与者级 RPT_MUTUAL_HOLD_DET 存孤段 2024-05-16→09-30(61,777 行/日×~95 日,行粒度=标的×日×CCASS 参与者)。
  • 深股通:同端点 mutualmarket_c.aspx?t=sz(Northbound-SZ 页表单 action 实测)。
  • 回补窗:12 个月滚动=最近 4 个季度末快照(2025Q3/Q4/2026Q1/Q2,各查 1 个 窗内日期即可取到,共 8 发);更早历史无免费渠道。
  • 可选 backlog(按「越全越好」原则择机,排最末):EM 参与者级孤段全收 (95 日×124 页≈11.8k 发≈5h 周六马拉松,~587 万行)。

20.5 验收锚点

  • margin: 回补后 600519 首行=2010-03-31、行数 3,979±10;单日文件行数 ~3,300; 与既有 margin_sse(上交所官方)同日茅台 RZYE 量级一致(±5%,口径差在东财含深市)。
  • sw_industry: 31 行业、Σ成分 ~5,000±500;600519 所属一级=食品饮料 (代码实施时以 index_component_sw 实测为准写入测试锚)。
  • dragon_tiger_seats: 当日股票集⊆dragon_tiger 主表股票集;每股票 buy+sell 各 ≤5 席位。
  • nb_hold: 沪 2,039±50/深 ~2,269±100(20260630 实测校准,原锚 1,700 已过时);工行锚 1,500,902,770(2026Q2 快照)。
  • nb_daily: 解析行数>10 且含十大活跃代码。

20.6 实施顺序与记录

顺序(用户拍板):margin(日采+16 年回补) > sw_industry > dragon_tiger_seats > nb_hold/nb_daily(含 4 快照回补)。全走 TDD(./venv310/bin/python)+worktree 协议+ [vps] 标签(schtask 挂载位在 VPS);回补马拉松周六窗口执行。

实施记录:

  • 2026-09-12 全四域当日落地 (用户拍板当日开工):
    • spec §20 定稿 (96e373a)。
    • margin (f7fb7b7/f80ca2f/8f3ce48): 关键实测修正——DATE 视图服务端 universe 锁沪市 2,000 只 (深市被排除, TMC×DATE 组合查询被服务端拒), 深北走 TMC 段码 (精确匹配: 股票 12 位/ETF 9 位, 七段全集≈570 万行)。 日增量=沪 DATE 直查+深北 TMC 倒序最近两日块 (实测深段 T+1 供应); wrapper T-2~T 三天窗; --margin-backfill 全史回补 (七段倒序整段翻页 流式按日切块+断点 state+合并去重幂等), 每周六 ak-weekly 兜底重跑; 16 年回补 09-12 09:03 VPS 启动 (深主板段 3,517 页起翻, 完成态见 后续巡查记录)。
    • sw_industry (b24f72d): 实测 5,214 行/31 行业/37s; 锚点 600519∈ 801120 食品饮料 (权重 39.8866/计入 2021-12-13) 写入测试。
    • dragon_tiger_seats (55339fe): 实测 680 行/58 股/190s (榜列表 68 行 =同股多上榜原因去重 58); 逐股逐侧各自 30s 预算 (整日期 3 分钟超 AK_TIMEOUT); filter 日期必须单引号。
    • nb_daily + nb_hold (d979c90): nb_daily 长表化实测通; nb_hold 季度 快照检查器实测 0630 快照 4,308 行/19s; --nb-hold-backfill 当日 完成 12 个月窗 4 季回补: 0630=4,308/0331=4,108/1231=4,014/0930= 3,820 行 (VPS data/static/nb_hold/)。
    • 僵尸退役: northbound (EM 个股北向持股, 2024-08 下线) 从 ak-weekly --types 移除 (原每周六 2,883 空跑单位); PER_STOCK_TYPES 注册表保留 仅注释级。
    • 测试: 新增 33 测试 (margin 14+sw 6+seats 4+nb 9), 全量 349 绿。
  • margin 全史回补通道改判 (09-12 上午, 三启三修复): TMC 整段翻页实测 服务端 5.7→20s/页递增惩罚 + 「服务器繁忙」限流 (全程≈70h 不可行) → 终态=per-stock 快速通道 --margin-backfill-ps (SCODE 视图 0.2s/页, universe 读本地 valuation markers 5,563 码零网络, 逐股包 retry+重试耗尽 跳过不杀马拉松, 19-24 点避让夜班, 股级断点; ~2.5s/股≈4h); TMC 慢通道 降级退市史专用; 周六兜底改 --margin-backfill-gaps gapsonly 连续 5 完整 日早停 (分钟级)。过程中根除两个存量真 bug: ①call_ak_with_timeout 的 with 块 exit 隐式 join 挂死线程 (瞬态挂起变永久卡死, 威胁全部 akshare 调用); ②EM 无数据双形态 (result=None+「返回数据为空」=合法空)。 8446098 部署后第 4 次启动巡航 (09-12 10:37 idx=14 推进中)。
  • 首夜观察 (2026-09-12 19:30 ak-events): margin/seats/nb_daily/nb_hold 四域首航 + sw_industry 首夜; 09-13 晨锚点=五域文件行数验收。

20.7 增补 2026-09-13:数据实体抽查修正(覆盖 §20.2/§20.6 相关结论)

用户质询「看 log 还是抽查了数据」触发实体抽查(读 parquet + EM 活体 3 发对账),三项修正:

  1. 「DATE 视图服务端锁沪 2,000」系结算时序假象,非宇宙锁:已结算日(09-08)实测 count=4443 全市场(SCODE 升序首页 000001/000002…全深主板);未结算当晚同视图只回 沪段 2,000。深段 EM 侧 T+1 且跨周末顺延(000002 周日夜最新仅 09-10)。 → 日采无需 TMC 段舞步,结算后 DATE 单查即全市场。
  2. 日采窗口修正(09-11 洞的机制):原 T-2T 当晚拉 T → 沪半截落盘即标 marker → 深段永久洞(09-11 实例:文件沪2000/深0)。修=ak_events_wrapper margin 段改 **T-3T-1 仅工作日**(拉的全是已结算日),周六 gaps 兜底保留;09-11 marker 待 重跑 flush 后删除,周一晚窗口自愈。
  3. ps 马拉松半场事故(记录):10:31 手动实例 18:32 挂死(475 万行困内存未 flush)+ once 任务 23:59 计划时刻二次触发(手动 /run 不消费计划)续完后段 1,746 股/140 万行 → 磁盘一度只有半场。09-13 08:05 全量重跑(两段:白天 ~9s/股 + 避让窗睡眠), ~01:45 收口。验收锚点:09-08 文件 ~4,400 行、000002/300750/600519 在档、dup=0。

抽查实录(数据非日志):000001@09-08 RZYE 46.26 亿(值 sane,EM 对账 000002 22.77 亿 一致);flush dedup 实证 dup=0(TMC 883→502 即重复行吸收);16 年抽样 000001/600519 命中 0/10 = 半场实锤;nb_hold 4,308=sz2269+sh2039;seats 680=68 股×10 席位(buy/sell 各 340)。

20.8 增补 2026-09-14:margin-ps 马拉松 OOM 根因与分段落盘修复

09-13 08:05 全量重跑「~01:45 收口」预期未发生——进程 16:17:59 即被系统强杀(昨晚 22:03 巡检读 idx=4272 误判「避让窗睡眠」,实为尸体;教训:判推进必看 state mtime 是否 随墙钟走)。事件日志铁证(Resource-Exhaustion-Detector 2004):马拉松 python(pid 19552)commit 达 32.6GB(16G 内存机)→「页面文件太小」→ WER 自身停止 + sanguo-frps 句柄错误 crashloop(系统级窘迫连带)→ schtask 记录 0xC00000FD。两次「8 小时死」非时间 规律,是内存累积曲线(都死在 ~4272 股/510 万行):by_date 分桶存 1 行 DataFrame ≈510 万个 pandas 对象 ×~6KB ≈ 32GB。docstring「570 万行 16G 实测可行」评估作废。

修复(commit 同日):①行 dict 替代 1 行 df 分桶(同信息量内存 ~1/5);②每 PS_FLUSH_EVERY=300 股分段调 _flush_margin_by_date 落盘(与 TMC/日增通道同键 DATE,SCODE merge+dedup keep-last,幂等可重复吸收);③state 只在段 flush 成功后推进 (crash 最多重做 ≤300 股;旧版每股写 state 是半场事故的共因)。TDD 3 例钉死: 段边界后强杀 → 前段在盘+state 停边界;crash 后续跑全量落齐;段 merge keep-last。

验收锚点随修复重设:重跑完成 = 全史日文件行数恢复(09-08 ~4,400)、000002/300750/ 600519 在档、dup=0、且 python commit 峰值 < 2GB(事件查看器无 2004)。09-11 自愈 改由重跑覆盖(marker 删除因远端删除被权限拦,改待用户点头的窗口自愈或重跑吸收)。

20.9 增补 2026-09-16:五新域首两晚生产四病五修(用户拍板全批)

09-14(周一)起五新域进入生产首跑,09-16 联合巡检+诊断探针实测定性四病 (margin_sse 窗口缺陷为第五项),用户全批修复(infra 转达口令批次):

  1. margin 深段 TMC 代码级必然超时(09-14/15/16 三晚全灭,从未成功过): 原实现把沪 DATE 直查+4 段 TMC 翻页整体包一个 AK_TIMEOUT=30s 预算,而 VPS 实测单段两日块 26.3s(883×2 行/4 页)→ 整体必超时。修=逐层各自预算 (dragon_tiger_seats 同款):沪直查 AK_TIMEOUT + 每 TMC 段 MARGIN_TMC_SEG_TIMEOUT=60s,任一层 failed → 整体 None 不写残缺; 段成功但请求日不在最近两块 → 跳过(旧日语义不变,backfill 兜底)。 09-11 自愈(仍 3,896 行缺前段股)被此病挡住,修复后由 T-3~T-1 窗重拉。
  2. sw_industry 一级清单源被反爬:akshare sw_index_first_info 走乐咕乐股 legulegu.com,VPS IP 被其反爬(带 UA=200 JS 挑战页/裸 403,两晚 'NoneType' find_all)。修=一级 31 行业清单改 SW_FIRST_LEVEL_STATIC 静态表(2021-12 版,Mac 出口实测校准;清单变更频率=年级,下次申万 一级大改需同步此表——Mac 出口仍可拉权威清单);成份源 index_component_sw 走申万宏源官网 API(swsresearch.com)不受影响, 保留网络拉取(Mac 实测 801120 食品饮料 122 行/600519 在档)。 VPS 出口对 swsresearch 可达性=部署后首跑验证项。
  3. nb_hold 日增查当天必空(与 margin_sse T 日同构的窗口 bug):HKEX 持股记录 T+1 供应,run_nb_hold_snapshot 原查 d_today 当天永远空页 → 09-13 起每晚 raise 出码 2 拍 ak-events rc=1。修=查询基准日改 T-1 (显式 today 参数仍可覆盖);_hkex_hold_query 加 strict 参数—— 日增路径 strict=False(无数据行返 [],走既有 skip 分支不抛), 回补路径保持默认 strict=True raise 语义(查询日=q_end+45 必有数据)。
  4. financial_abstract 新浪源每晚 5.5k 连发撞限流:源=新浪 quotes.sina.cn(非 EM),09-14/15 断路器 30 连败 FATAL rc=2;单发实测 通(200/2.6MB JSON)→ 非持续封禁是批量频率触发。fa 是 ak-daily 最后 一个类型,断路器无后续连坐。修=fa 从 ak-eod 每日挪 ak-weekly 周六 03:00(季度频数据周更足够,sina 风控面 -87% + 错峰;schema/路径 不变仅频率降)。
  5. margin_sse 窗口含 T 日每晚必 1 failed:EM 沪 DATE 视图 T+1 供应 (本条与 §20.7 09-13 修正同源——TMC 深段已改 T-3T-1,margin_sse 漏改)。 修=wrapper 窗口 T-1T → T-2~T-1(每晚全 settled 数据全绿;窗内 重试自愈保留——漏掉的 T-1 次晚变 T-2 仍在窗内)。

监控口径坑(09-16 备案):ak-events 类型级 failed 不抬出码(margin 两晚 failed 各自日志仍「全部完成 出码 0」),只有未捕获异常/断路器才抬 rc—— 判健康必须看每类型统计行 ok/failed,不能看 schtask rc 或「出码 0」。

验收锚点(部署后首个 19:30/周六):margin 深段 09-14/15 双日文件落盘 (各自 ~4,400 行全市场)+09-11 补至 ~4,443;sw_industry 首落 (20260917_sw_industry.parquet ~5,200 行/31 行业/600519∈801120);nb_hold rc 不再抬 1(T-1 查询或 skip);ak-events schtask rc=0;fa 下个周六 (09-19)ak-weekly 段绿。

20.10 增补 2026-09-17:数据面全景定稿(口径四原则+管线清单+归属表)——本节为数据面唯一权威查询入口

背景:09-17 双机全量盘点(NAS du/DSM 调度/VPS 探针三源交叉)。目的=此后查 「有什么数据/在哪/谁更新/多大」直接读本节,不再用代码/探针回溯。

20.10.1 口径四原则(用户 2026-09-17 拍板,覆盖此前所有归属表述)

  1. LLM-Models 639G 忽略:NAS 上 cfdaily 账号 2026-05-12 的 ModelScope 批量 下载(6 模型仅 GLM-5.1-Int4 有内容,目录内有 download_log.txt/教程取证), 非本项目资产。
  2. VPS 采集 → NAS 必须同步(统一铁律):VPS=下载主体(公网出口直连各源), NAS 每日定时同步=原始设计常态,「双份」不是差异;活的采集面在 NAS 缺 同步=缺口必须修正(当日修正两例见 20.10.4)。停更归档层除外(原则 3)。
  3. 搁置不管清单:分钟线分置(NAS 5m 独有腿在 90G 库/VPS 15m 在主库)=已知 问题先搁置;归档件不管(qfq 0.81G/raw 0.77G=07-22 方案A 定稿日退役、VPS minute_kline 2.98G/minute_15 1.01G 散文件=07-18/20 退役尸体、_deprecated 3.94G、csindex_raw/constituent_baostock=停更采集中间层、cfdaily 旁路三件= A股数据 3.0G+minute_kline 2.1G+LLM-Models,均非我方管线)。
  4. 消费不跨机:NAS 因子读 NAS 镜像,VPS 消费(实盘/回测)读 VPS 本地。 (09-17 拍板)NAS 独有域迁移定案:corpus/dmsk 建 NAS→VPS 每日镜像=§20.11 (VPS 侧消费届时读 VPS 副本,本原则自动满足);5m 留 NAS 分置(原则 3)。

20.10.2 活跃管线全景(15 条,2026-09-17 实测+§20.11 镜像链+§20.11.7 补洗[09-20 上线])

VPS 夜班(Windows schtask,9 条):

任务 时间 内容 源 落点
sanguo-bs-daily 18:05 日 个股日线+15m 增量→dbbardata;拆估值列→年 parquet;fund 腿回灌 baostock quant_trading.db 39.85G+valuation_baostock 0.68G+fundamentals_baostock 21M
sanguo-idx-daily 18:30 日 9 指数日线 新浪 dbbardata
sanguo-ak-daily 19:00 日 valuation ~5,570 股逐股 --force(新上市数缓增,2026-09 实测 5,569 采/5,570 文件) akshare/EM static/valuation
sanguo-ak-events 19:30 日 per-date 全族(清单权威=akshare_static_download.PER_DATE_TYPES,现 18 类;事件主表 2020 起 1,751 日;lag 窗 margin T-3T-1/margin_sse T-2T-1/seats T-1T/nb_daily T-1T/nb_hold 季)。(hot_rank 09-25 起摘除迁 NAS 采集,§20.14;xueqiu_hot 同批改 curl 版) EM/新浪/同花顺/雪球/HKEX/申万宏源 static/ 各域
sanguo-xt-daily 21:00 日 ETF/基金日线+个股补缺 xt 桥 dbbardata
sanguo-ak-vintage 09:00 日 vintage 一致性自检(防线,不下载) — vintage_status.json
sanguo-ak-weekly 周六 03:00 gdhs(53 期,2013Q1 源头边界)/share_capital/top_holders(10.9 万文件)/financial_abstract(09-16 挪入,新浪限流对策)+margin 缺口回补+§20.13 三域(09-22): pledge_ratio 周五快照(--start 20210108)/pledge_detail 月桶全量/research_report 周窗(--start 20210701) EM/新浪/reportapi static/
sanguo-ak-events-retry 周一至五 20:30 起每小时×4 发(09-25 建;首版 /sc hourly 被建成一次性跑完即死,当日重建 weekly 版,runbook §7.5) 重跑 ak-events wrapper(marker 幂等,兜 EM 当日未出数时序失败) 同 ak-events static/
sanguo-ak-monthly 财报季首周六 02:00(下次 11-07) 三表+forecast/express 全量洗库(balance/income/cashflow 各 5,555 股,Q2=2026-06-30) EM datacenter static/
sanguo-index+idx-monthly 每月 16 日 19:50 成份股 merge→constituent_unified(14,496 行)+index_const_hist(44 文件) baostock+EM dbbardata+data/index_const_hist

NAS 侧(DSM 调度,6 条+周日):

任务 时间 内容 源 落点
sanguo-5m 容器 00:05 日 5 分钟线全市场 5,558 股(94min 完赛) baostock data_backup/quant_trading.db 90G(=VPS dbbardata 日增量+5m 独有腿合库,已超 VPS 主库)
03:00 同步链 03:00 日 五段:①dbbardata 增量(sync_dbbardata)②constituent_unified+bs_adjust_factor 两表 REPLACE ③per-date 18 类 7 天窗单文件拉(sync_parquet_daily)④valuation/financial_abstract 两整目录+valuation_baostock/fundamentals_baostock/index_const_hist 三根级目录 scp -r(sync_valuation_daily) 从 VPS 拉(NAS→VPS SSH 22 出站通,光猫只拦 80/443) 90G 库+sanguo_vnpy_v2/data 镜像树
sanguo-corpus 容器 06:00 日 新闻标题/正文+公告元数据+业绩 PDF 东财/巨潮 corpus/ 302M(news_meta 116M/ann_meta 37M/state 131M…)
run_dmsk 07:10 日 按期财务五域(balance/income/cashflow/forecast/express,披露次日新鲜度补丁层+退市/北交覆盖) EM datacenter fundamentals/dmsk 222M(dt=期分区,最新 2026-06-30)
sanguo-static-overlay(§20.11.7,09-20 上线,挂 dmsk wrapper 第三 lane) dmsk 班后 ~07:2x 事件驱动补洗三表:dmsk NOTICE_DATE 雷达命中股逐股 F10 全史全列重写 per-stock 文件(披露次日全列新鲜);月度全量洗保留兜底 EM f10(emweb) static/ 三表+变更清单(晚间镜像车推 VPS)
周日全量 周日 04:00 static+valuation_baostock+fundamentals_baostock 整树 scp -r 6.24G/70min(慢变 per-stock 域兜底) 从 VPS 拉 static 镜像
sanguo-vps-mirror(§20.11;09-18 起挂 corpus 任务尾部) corpus 完赛即推(典型 ~10:1x;backfill 日 ~17:3x) corpus 四子域+dmsk 分区粒度增量推送(journal 指纹 diff,只增不删;dmsk 07:15 早完同车携带;rc 隔离=corpus rc∈0/1/3 才推[09-19 勘误:rc() 把「墙停+噪声 failed」报 1,旧 0/3 闸门 11 天只推 1 天;仅 rc=2 限流不推]、推送失败只记日志不进聚合 rc);§20.11.7 起 static 三表变更文件按补洗清单同车(09-20 上线,独立 manifest lane 整单归档幂等) 推 VPS C:\sanguo_vnpy_v2\data{corpus,fundamentals\dmsk}

同步新鲜度分级(修正后):per-date 18 类+两表+dbbardata 增量+valuation/ financial_abstract/vb/fb/index_const_hist=日级;forecast/express(月更 洗库)/share_capital/top_holders/gdhs(周六产)=周级(周日全量+gdhs 日级段); 三表=日级(§20.11.7 事件驱动补洗,09-20 上线;此前月更洗库=≤5 周); corpus/dmsk 的 VPS 镜像=日级(§20.11;09-18 起挂 corpus 完赛尾部即推,典型 ~10:1x)。

20.10.3 数据归属与体量总表

数据 位置 体量 性质
dbbardata 行情主库(日线+15m,含 ETF/指数/退市) VPS+NAS 39.85G / 90G 双份日级(原则 2 常态)
5m 分钟线 仅 NAS 并在 90G 库 独有腿(原则 3 搁置)
corpus 语料四件套 NAS 权威+VPS 日镜像(§20.11 随实施上线) 302M(载荷 171M) §18 采集+§20.11 镜像
dmsk 五域 NAS 权威+VPS 日镜像(同上) 222M §19 采集+§20.11 镜像
factor 产物(topn_results/cross_section/eval_fundamental) 仅 NAS ~450M 因子批产物(NAS 消费)
static 33 域 VPS 原始+NAS 镜像 6.85G / 6.7G 原则 2 常态
valuation_baostock/fundamentals_baostock/index_const_hist 双份 0.68G/21M/MB 级 原则 2 常态
quant_trading.db 本体/universe_cache 0.23G/backtest_files/strategy_code_versions 仅 VPS — 生产运行时(实盘+VPS 回测读,原则 4)
qfq/raw/分钟散文件/_deprecated/csindex_raw/constituent_baostock 仅 VPS ~5.6G+3.94G 原则 3 归档不管
cfdaily 旁路(A股数据/minute_kline/LLM-Models) 仅 NAS 3.0G/2.1G/639G 原则 1/3 忽略

20.10.4 当日修正两例(缺口实例,模式备案)

  1. sync_parquet_daily TYPES 13→18 类+nb_hold 季度段(e0f5730):09-12 四域 扩展与 09-04 hot_rank 挂载后清单未跟上,margin/sw_industry/nb_daily/seats/ hot_rank 在 NAS 仅周日全量兜底周级滞后(NAS margin 停 0911 实锤)。教训: 新增 per-date 域必须同步扩 sync_parquet_daily TYPES,纳入域上线检查单。
  2. index_const_hist 补入 sync_valuation_daily 根级目录段:每月 16 日整文件 重写(44 文件 MB 级),此前 NAS 完全没有,按统一铁律补链。

20.10.5 半截文件防线(用户点名「别总出现半截文件」)

  • margin 0911 案根因链(已闭环):旧代码沪 DATE 直查成功+TMC 段超时仍部分 concat 写盘(3,896 行、深段缺)+marker 锁死永不重拉。修复=新代码任一层 失败整体返 None 不写不标(75af7f2 五修①)+marker 只在完整写入后落——半截 写入通道已从语义上关闭。
  • margin 0924/0930 案(二代同族,10-03 修):深/北 TMC 块滞后发布(10-03 探针 feed 最新=0929、0930 未发布;0924 块曾滞后 8 天)→ 段成功但请求日全空 仍 concat 单沪腿残缺(2,002/2,001 行 vs 满腿 6,051/6,054)+marker done 永不重跑。修复=未发布守卫:请求日比段最新块还新且沪有数据 → 整体 None 不写残缺(fail-loud 次夜重跑,pledge_ratio 未发布周五同款);旧日语义 (请求日 < 段最新块)不变仍走 backfill。存量 0924 块已发布由周六 gapsonly 补齐;0930 待 EM 节后补发后 35 日窗内 gapsonly 兜底;全仓零 RZRQ 消费方 (纯监控域)。
  • 提前补齐前提=根因已闭环:0911 补齐走 --margin-backfill-gaps(gapsonly 早停,分钟级),09-17 晚 ak-events 跑完后手动触发(不等 09-19 周六自愈)。
  • 同族防线既有:ak-quarter 洗库撕裂=ak-vintage 09:00 自检+ALERT rc3(09-01 事故防线④);快照族节假日拉上一交易日态=消费方按交易日历过滤(§15.2)。

五修首跑验收(09-17 晚)+新病六修(TMC 块翻页漂移 dup):首跑四看全过 (ak-events rc=0 首次、margin_sse 新窗 T-2~T-1 全绿无 T 日 failed、nb_hold 「已是 20260630 期跳过」不再抬 rc、sw_industry 首落 5,217 行/31 行业/ 600519∈801120 权重 39.9007 计入 2021-12-13 与锚点一致、seats 620 行、 nb_daily 62 行、valuation 5,565 股满贯)。但 margin 0915/0916 行数 6,890 (预期 4,443)——探针解剖实锤:fetch_em_tmc_recent_blocks 翻页在 EM sortColumns=DATE 同日内排序不稳定时页边界行漂移,同一 (DATE,SCODE) 行进 两页(069001002001 块内 883 行 dupSCODE=382;四段 universe 跨段 overlap=0 排除段重叠假说;0914 干净=漂移是页边界概率性)。by_date 通道自 44d3ab9 有 (DATE,SCODE) merge dedup 防线,五修①重构 recent_blocks 通道漏抄。修复= _fetch_tmc_block 块出口 drop_duplicates(容错键列),TDD +1 例 372 绿。 存量脏数据:0915/0916 文件 dup2,445 行/日(消费端两融余额会翻倍, 勿在修复前消费)。处置终态(09-17 晚更新):六修 d94936c 已上 VPS(run#1265, 21:43 生效);直接洗文件被本机分类器拦(写生产数据),改由 09-19 周六 gapsonly(七修版)merge keep-last 自动重写洗净——0917 在 09-18 晚 19:30 两日窗内也会被新代码重拉洗净。代价=NAS 副本 dup 躺到周日晚 03:00 同步 (margin 零消费方,无实害)。0917 当晚文件同为部署前旧代码所写,同病同治。

七修(gapsonly p101 服务墙,09-17):0911 半截补齐首跑两次同点挂 [backfill TMC 069001002001 p101]: 服务器繁忙——非短暂限流(同点复现= 确定性),根因三病:① 早停「行数相等」判定(旧文件该段行数==新块行数)在 新块带翻页漂移 dup(len 虚高)/旧文件 ps 通道行数微差时恒 False → 连续 5 完整日永不触发 → 一路裸翻;② EM 对单 TMC 段深翻页存在 ~100 页/5 万行确定性 服务墙(p101 起 result 缺失),且 TMC×DATE 组合过滤被服务端拒(§20 实测), 无法换锚深翻——此墙同时宣告 full 模式 TMC 整段翻页对 176 万行大段永不可达, 深史回补只能走 per-stock 通道(已为主力);③ gapsonly 复用 full 模式 state 断点,挂死残留 state(page=100) 毒化下次续跑(从 p100 起立即再撞墙), 且单段早停跨段 break 跳过其余六段(各段夜间失败模式独立)。修复=四件: 键集判定(旧文件该段 SCODE 键集 ⊇ 新块去重键集=完整)+ 日期下界 MARGIN_GAP_LOOKBACK_DAYS=35 自然日(≈24 交易日≈深主板 ~55 页,远离墙;更深 缺口归 ps 通道)+ 翻页硬上限 MARGIN_GAP_MAX_PAGES=90(到顶停段不 raise, 03:00 无人值守不炸)+ gapsonly 无视 state 恒从 p1(重翻由 merge 去重吸收, 段末清 state)+ 删跨段 break(七段全查)。TDD +5 例(键集扛行数差/下界+stale state/硬上限不 raise/缺口日 merge 补齐/段间独立),376 绿。

20.10.6 已知问题登记簿(观察中,勿重复排查)

问题 状态
hot_rank 采集成率 <50%(挂载 9 交易日落 4 文件,emappdata 夜间开墙断续) 用户已知晓,观察;单 unit 失败不触断路器次夜重试
margin_sse 曾停 0911(在 TYPES 内) 09-17 手动触发后直达 0916,定性=VPS 侧文件产出节奏非链路故障;持续观察 03:00 班新鲜度
快照族上线日恰逢周末=连续多夜零落盘无告警 §20 坑备案:看目录前先看日志「工作日N天」行
三表季频新鲜度=披露后最多 ~5 周(ak-monthly 月度洗库) 已拍板根治(09-20):§20.11.7 事件驱动补洗=全列披露次日(原「dmsk 补新鲜度」双层读法经探针证伪收益后改道;09-20 上线)
NAS 独有三域(corpus/dmsk/5m)VPS 侧消费 已拍板(09-17):corpus/dmsk 迁 VPS 日镜像+通用分区读取接口(§20.11.2/20.11.3,双机各读各的);5m 留 NAS;语义层 PIT 视图接口(pit_view)归数据线(§20.11.7,09-20 拍板)、情绪/事件因子加工留因子线消费方
VPS dbbardata 内嵌 5m 冻结腿 60,209,424 行(止 2026-07-17,bs_5m_eod 退役尸体;09-27 审计 🟢-1) 已登记:现无消费方(原则 4 口径 VPS 不消费 5m);任何 interval='5m' 查主库行为会拿到静默过期数据——清理/归档为写操作随部署班车择机;死基金 cohort 零值 bar(🟢-2,封闭在 501/502/158-161 LOF+清盘基金段)同批决策
sanguo-index 与 sanguo-idx-monthly 双任务同脚本同日(每月 16 日各跑一次,09-27 审计 🟢-5) 知情登记:merge 幂等无实害;退役其一=schtasks /delete 随部署班车择机;corpus 根残留空目录 zz_slash_test/ 清理(🟢-9)同批

20.11 增补 2026-09-17:corpus/dmsk NAS→VPS 每日镜像链(迁移评估落地,用户拍板)

拍板背景:用户问「当初因数据量巨大只放 NAS 的,现在评估哪些可上 VPS,1 年内 不撑爆盘(一年内会扩容)」。实测评估后拍板:corpus+dmsk 两族迁(本节), 5m/factor 产物/LLM/停更尸体不迁。本节修正 §18.1 硬约束 1 的「零存储」(采集 仍 100% NAS、VPS 零 schtask/零采集进程不变,仅新增只读镜像副本)并关闭 §20.10.1 原则 4 挂起项。

20.11.1 评估底数(09-17 深夜实测)

  • VPS 预算:C: 180G 总盘剩 63.9G(D: 无盘),主库 39.85G;主库年增保守 估 5-15G(常态 15m+日线增量 ~12MB/天;今年夏天 26G→39.85G 的大头是一次性 历史回灌,已完成)。
  • corpus 有效载荷 171M(news_meta 116M/ann_meta 37M/news_fulltext 17M/ ann_pdf 1.2M;state 131M+logs=管线内部件不迁),日增 ~4MB(3 天实测 12.1MB)→ 1 年 ~1.7G。
  • dmsk 211M(五域按期分区,最新 dt=2026-06-30),年增 ~20M(季度补分区)。
  • 不迁四项:① 5m 库 89.4G>63.9G 放不下且 VPS 无日内消费(原则 3 分置, 扩容后也留 NAS);② factor 产物=派生数据各算各的(NAS 调研产物 450M/VPS 自有 factor_eval.db,拷贝=两份互相漂移说不清权威;研究结论走代码晋升不走 数据搬运——用户 09-17 原话确认);③ LLM-Models 639G(原则 1);④ A股数据 3.0G+minute_kline 2.1G 停更尸体(原则 3)。
  • 结论:迁移集 1 年总占用 ~2G ≪ 64G 预算(3%),撑爆风险零;VPS 盘的主 导增长项是主库自身有机增长,扩容主要为它。

20.11.2 镜像链设计

维度 设计
方向/通道 NAS→VPS 推送(SSH 22 出站通=03:00 链每天在用的反向;复用同账号同 key)
载荷 corpus 四子域(news_meta/news_fulltext/ann_meta/ann_pdf)+ fundamentals/dmsk 五域;排除 state/logs/cron.log/run_*.sh(管线内部件)
VPS 落点 C:\sanguo_vnpy_v2\data\corpus\{四子域} + C:\sanguo_vnpy_v2\data\fundamentals\dmsk\(镜像 NAS 目录结构,消费方按 dt= 分区直读)
调度 09-18 用户确认:复用 sanguo-corpus-daily DSM 任务,挂 runner 尾部(run_corpus_standalone.sh EXIT trap)完赛即推(典型 ~10:1x,同日新鲜度优于独立 16:00;dmsk 07:15 早完同车携带;rc 隔离=corpus rc∈0/1/3 才推[09-19 首验勘误:rc() 优先级把「墙停+failed≥1 噪声」降级为 1,实证 11 天 10 天 rc=1,旧 0/3 闸门=镜像永不触达;rc=1 天照推,缺单元指纹幂等次日自愈补推;仅 rc=2 限流不推]、推送失败只记日志不进 corpus 聚合 rc;原「新 DSM 任务 16:00」方案作废——评估见 §20.11.6 遗留①)
增量策略 分区粒度(dt= 目录/ann_pdf 年目录):本地 journal 记每分区指纹(聚合 bytes+max mtime,/volume1/stock/vps-mirror/journal.tsv),diff 出新增/变化分区→scp -r 整分区覆写推送。幂等可重跑;journal 删除=全量重建;语义=只增不删(远端不镜像本地删除,分区重写靠指纹变化触发重推吸收)
脚本 repo scripts/nas_sync/push_vps_mirror_daily.sh(基建线→runbook 同步登记;支持 --dry-run 打印将推送清单不传输)
水位线 每次推送成功后在 VPS 两族根写 _mirror_watermark.json(last_push 时刻+各 domain max_dt);读取器 get_watermark() 暴露,消费方晨检对表(策略线 09-17 要求,回执见 20.11.5)
日志/监控 append /volume1/stock/vps-mirror/push.log(每次一行摘要:日期/推送分区数/字节数/耗时);独立任务失败不伤采集本体,无断路器需求(次日 diff 自愈)

通道细节备案(09-18 首推实测):Windows OpenSSH 作 scp 目标直接可用(正斜杠 C:/... 路径,无需 -O);远端建目录用 PowerShell New-Item -Force(cmd 无 mkdir -p 且逐级链有解析坑);重推已存在分区必须替换语义(先 Remove-Item 再 scp 显式全路径目标——scp -r 依赖 basename 推断,重推落父级散文件)。 任务账号=admin(key 同 03:00 链;避开 root 属主坑,journal/push.log admin 属主)。

20.11.3 消费接口(用户 09-17 补充拍板:和其他数据一样,双机各有数据和接口)

原则:同一套读取代码,双机各读各的本地副本——代码随 repo 部署两机,路径 经 config 解析后各喂各的本地数据;与 dbbardata/static 的消费模式(口径 4)完全 一致。现状勘测:repo 内尚无任何 corpus/dmsk 读取器(grep 零命中;因子侧 fundamental_pit 读的是 static 基线层镜像),本节为新件。

件 设计
路径解析 两族独立根+env 覆盖(同 SANGUO_DATA_ROOT 模式,不改部署态配置):SANGUO_CORPUS_ROOT(默认 posix=/volume1/stock/corpus,win=C:\sanguo_vnpy_v2\data\corpus)、SANGUO_FUND_DMSK_ROOT(默认 posix=/volume1/stock/fundamentals/dmsk,win=C:\sanguo_vnpy_v2\data\fundamentals\dmsk)
读取核 corpus 与 dmsk 同构(dt= 分区 parquet 直存,§19.3)→ 抽通用分区读取核 sanguo_data/partition_reader.py:list_dates(domain) / read_partitions(root, domain, start, end)(扫描分区内 *.parquet 拼接);ann_pdf 按年目录特例只给路径定位不拼 DataFrame。核内零语义(因子线 09-17 契约):不做 as-of/PIT(因子侧 fundamental_pit=唯一正确性模型,两处实现会漂且 PIT 错是静默错)[09-20 勘误:PIT 视图接口 pit_view 归数据线(§20.11.7)建在核之上,核零语义不变;「两层合并」取消,因子 fundamental_pit 继续跑变新鲜 static,单一实现原则不变];零静默去重(幂等去重是写路径职责,镜像重放/分区重写出重复行消费方要看得见,取哪行=语义决策);dmsk 可选 noticed_by=None 纯过滤参数(文档写明 filter 非 merge)
corpus 薄封装 sanguo_data/corpus_reader.py:get_news_meta(start,end,symbols=None) / get_ann_meta(start,end,symbols=None)(符号过滤下推,事件因子逐股截面;news↔股票若多对多则映射表一并暴露——实施时勘测)/ get_news_fulltext(ids)(按 id 批量:因子回访高信号条目+LLM 分块天然按 id;meta↔fulltext join 键契约落文档)/ ann_pdf_dir(year);ann_meta 透传公告类型/标题(源有页数更好——消费方选择性抽取不盲抽)——列名随源直存零转换(§15.2 双层读法惯例)
容错语义 根/分区缺失→空 DataFrame 带 schema 返还,绝不 raise(同 akshare top_holders 空 df 带 schema 惯例;「数据失败≠交易信号」——消费方沿用上次快照,策略线生产铁律);get_watermark() 无水位线文件时返 None。失败分级:缺数据→空 df;数据在但形状错(schema 漂移)→fail loud(见数据契约④)
数据契约(因子线 09-17 四条,文档级) ① dmsk 五域每行 NOTICE_DATE 必在——实施时逐域实测落 reader docstring,系统性缺域明示(因子侧对缺 NOTICE_DATE 期整期弃用=宁缺毋假红线);② corpus 稳定去重 id(内容 hash)——meta+fulltext 保证或给文档配方,因子幂等计算依赖;若现数据无 id 由 corpus 采集侧补=另一工序,不进镜像链;③ 每域 schema 契约落文档:列名/类型/单位(万元 vs 元)/代码格式(600519 vs 600519.SH)——无文档的零转换逼消费方逆向猜;④ schema 冻结+fail loud:跨分区列集缺失/类型漂移读取核报错不静默 coerce
dmsk 薄封装 sanguo_data/fund_dmsk_reader.py:get_domain(domain, start, end) 五域原始分区读取。语义层留白:「static 基线为主+dmsk 新鲜度补丁」的 PIT 合并(§19.3 下游读法)与情绪/事件因子加工=因子线消费方业务,届时基于本读取核演进,不进数据线[09-20 勘误:PIT 合并取消,新鲜度改由 §20.11.7 采集层根治,本行留白撤销;dmsk 角色=披露雷达+forecast/express+RATIO 列+退市/北交段];as-of 截断(按 NOTICE_DATE/披露时刻防前视)=消费方语义,读取核只保证 NOTICE_DATE 等源列直存+水位线可查
测试 fixture 造 dt= 分区 tmp 树(env 覆盖 root),TDD 覆盖:日期过滤/跨分区拼接/空分区容忍/ann_pdf 年目录/缺根缺分区返空不 raise/水位线读取与缺失返 None/symbols 过滤/ids 批取/noticed_by 过滤/重复行直通(零去重实证)/跨分区类型漂移 fail loud

仍不做:5m/factor 产物不迁(20.11.1 备案,不再议)。

20.11.4 实施与验收锚点(实施时回填记录)

  1. TDD:journal 指纹/diff 抽纯函数进 pytest(新增/变化/不变三态+ann_pdf 年 目录粒度);shell 改完必 bash -n。
  2. 消费接口(§20.11.3):config 根解析+partition_reader+两薄封装+数据契约四条 落 reader docstring(NOTICE_DATE 逐域实测/schema 表/id 配方),fixture TDD(Mac ./venv310);默认根即双机各读各的,零部署配置。
  3. 部署:先探针确认 03:00 链脚本在 NAS 的实际生效位(homes/admin 安装树 vs /volume1/stock),新脚本放同位同款分发;DSM 建 sanguo-vps-mirror 16:00 (与 03:00 链同账号)。
  4. 验收:①首推后对账=VPS 侧四子域+dmsk 分区数与总 bytes 逐项对齐 NAS; ②紧接着 --dry-run 清单为空(收敛证明);③次晨 16:00 后新 dt= 分区自动 到 VPS;④journal 与 push.log 各就位;⑤双机读取冒烟=NAS 容器内与 VPS venv 各跑 get_news_meta/get_domain 最近 1 日非空+get_watermark() 返到昨夜 16:00 水位。
  5. 收尾:runbook 登记任务(调度全景+非代码资产清单)+ CLAUDE.md「VPS 零参与」 表述补镜像注记。

20.11.6 实施记录(2026-09-18 凌晨首推战役回填)

commit 链:7e5e720(runner+lib+runbook 登记,TDD 15 例)→ 1b942c0(读取器 三件,TDD 23 例,全套 414 绿)→ 1900be2/8095404/66d450f/efe883b(首推四修) → e97f845(类型兼容精化,416 绿)。

首推五 bug 战役(一夜全踩全修,daily 增量路径从此全部踩实): ① bash 循环 case 守卫把协议 tag=PUSH 误当 fam 全部跳过(bash -n 不验行为—— 部署侧必须先 --dry-run 全链);② mkdir 预扫 while-read 管道内 ssh 不带 -n 吃光 stdin(仅首条链执行);③ scp -r basename 推断在重推已存在分区时落父级 散文件(对账解剖实锤 4 stray)→ 替换语义(Remove-Item+显式全路径目标); ④ EM 源全空列写 arrow null 型、同域 part 文件 null↔double 漂移合法 → 读取核 类型兼容类精化(全空列通配/数值族互通,真冲突收窄 text↔num+列集增删); ⑤ ${DRY:+--dry-run} 恒展开(:+ 判非空不判真值)→ plan 永远 dry → journal 永不落 → 显式 DRY_FLAG。

验收终态(09-18 00:39):424 分区 / 393,217,524 字节分毫不差(VPS= NAS 载荷 corpus 173,003,124+dmsk 220,214,578,另 +2 个 _mirror_watermark.json); 域级散文件归零;瞬时连接超时 1 次被 3 重试吸收;收敛证明=修复后重跑 PLAN push=0 bytes=0 → DONE pushed=0 fail=0(2 秒),journal 落位 /volume1/stock/vps-mirror/journal.json;NAS 真数据读取冒烟绿(news_meta 0917=5,077 行 / fulltext 按 ids 3/3 命中 / dmsk balance dt=2026-06-30 含 noticed_by 过滤 5,572 行、NOTICE_DATE max=披露当日)。

遗留:①每日调度待接 已闭环(09-18 用户确认):挂 run_corpus_standalone.sh 尾部(EXIT trap _mirror_push_tail,rc 隔离=corpus rc∈0/1/3 才推[09-19 勘误,仅 rc=2 限流不推]、失败只记日志), 完赛即推同日新鲜度;已 scp 部署到 /volume1/stock/corpus/run_corpus.sh,调度行见 §20.11.2;②VPS 上线已闭环(09-18 晨):vps-deploy run#1280 (sha=a024afa,用户原话「现在推」,08:32 promote 落位)+VPS 真数据冒烟绿—— news_meta 0917=5,077 行 / dmsk balance dt=2026-06-30 noticed≤0918=5,572 行 / 水位线 2026-09-18T00:39 四域 0917 / ann_pdf_dir 2026 存在,双机同数与 NAS 侧分毫不差(镜像链端到端实证);③CLAUDE.md 注记已同步(corpus 口径改 「NAS 唯一权威+VPS 每日镜像」);④backlog:fulltext(ids) 大载荷时加 分区定位;稳定 id 内容 hash 若现数据无则采集侧补(另一工序)。

20.11.5 消费方征询回执(09-17,讨论制:按合理性采用)

  • 策略线(回执入 session 档):硬阻塞诉求=无。真实增益两条——① dmsk T+1 对 value 月度调仓有实质意义(月初 09:30 开火撞财报密集披露期末尾,现最长 5 周延迟=滞后截面;ROE 配对公共报告期交集直接受益;非阻塞,value 一直带 现延迟在跑);② 新闻/公告事件过滤当前零消费方,未来若做=买入前负面黑名单 剔除、候选池级日终粒度即可,现不加策略逻辑(YAGNI,与 20.11.3 留白一致)。 读取形态=日终批量 DataFrame(16:00 推+次日盘前读=天然快照,无需盘前快照 通道)。三点工程要求全部采纳:水位线可查(→20.11.2 水位线行)/断供 降级不 raise 沿用上次快照(→20.11.3 容错语义行,「数据失败≠清仓信号」生产 铁律)/数据截止时点暴露(水位线+NOTICE_DATE 等源列直存;as-of 截断本身留 消费方按各自 PIT 语义做——与因子线分工一致)。另:9-18 miniQMT 停服在即, 语料/财务全落 VPS 本地=交易时点零跨机依赖,方向赞成。
  • 因子线(回执入 session 档,先读 spec+自家 fundamental_pit 再答):总评= 方向对不动骨架。a) dmsk 保持原始区间扫描,读取核不内置 as-of——as-of 合并已活在因子侧 fundamental_pit.py 且有测试(NOTICE_DATE≤决策日 asof 前向 填充,NOTICE_DATE 缺失整期跳过=宁缺毋假红线),读取核再做一份 PIT=两处实现 漂移、PIT 错是静默错(前视偏差旧案在档);且 dmsk 按 REPORT_DATE 分区, 「as of D」无法靠分区剪枝、必须行级 NOTICE_DATE 过滤,内置反而掩盖双日期 语义→采纳:核内零语义。两契约级保证(文档非逻辑)NOTICE_DATE 必在/ 零静默去重→采纳:数据契约①②;noticed_by 纯过滤参数→纳(标注 filter 非 merge)。b) corpus 三诉求→全纳:fulltext 按 id 批量(接口改 get_news_fulltext(ids))/meta 符号过滤下推(symbols 参数,多对多映射表 实施时勘定)/稳定去重 id(内容 hash,无则采集侧补=边界限定:另一工序 不进镜像链);ann_pdf 路径定位够+ann_meta 透传类型/标题,文本抽取/缓存 归因子算力域。c) 零转换 OK 但要 schema 契约文档(列/类型/单位/代码格式, 历史吃亏多次)+跨分区 schema 冻结或 fail loud→采纳:数据契约③④ (选 fail loud 并入失败分级;实施精化=全空列通配/数值族互通,见 20.11.6 ④)。镜像链本身无异议。

实施版 review 回执(09-18,双线闭环):策略线通过(三点工程要求逐项 核验落地;两条非阻塞观察入 backlog:get_news_fulltext(ids) 全分区扫描随语料 增长线性变贵→量大时加 start/end 或按 meta 定位分区;列序漂移误报→已顺势改 按列名比对不再误报)。因子线精化认+必修 1+记录 2:契约④精化认可(按原 字面执行会拒掉全部合法数据);必修#1 null 桥接洞(因子线实测复现:首文件 全空列把 num 与 text 桥接,两具体类型从未直接对撞→concat 静默混装零 raise, 恰是契约④要防的静默 coerce 被绕过)→已修:每列维护 resolved=首个非空具体 类型、null 永不推进 resolved、后续非空类型冲突即 raise、列集按名比对(列序 漂移不误报),+3 测试(三段桥 raise/null 隔离后续冲突仍 raise/列序漂移 tolerated)共 419 绿;记录②NOTICE_DATE 空值行被 noticed_by 滤除=有意 宁缺毋假语义(docstring 已写明勿当 bug 修);记录③fulltext 扫描成本同策略 线观察,入 backlog。

20.11.7 增补 2026-09-20:fund PIT 新鲜度采集层根治(事件驱动补洗+pit_view,用户拍板;「两层合并」设计取消)

拍板链:09-19 晚 factor 移交「static 基线+dmsk 补丁两层合并」规格 v2(用户拍板 归数据线统一实现防接口爆炸,四规则 NOTICE_DATE 仲裁+D 护栏,三方讨论闭环)→当夜 数据线表头探针证伪合并收益→09-20 凌晨用户三选一拍板采集层根治,两层合并 (规则 A-D/列映射表/D 护栏/换源迁移)整体取消——「数据问题找数据层根治」。

探针证据(NAS 容器实测茅台 600519/万科 000002/平安 601318,09-20 在案):

  • 两层值列交集极薄:income 18/balance 20/cashflow 15;dmsk 三表域 47/58/49 列即 vendor 全集(fundamentals_dmsk_download.py columns="ALL"),不可扩。
  • 因子 40 原料列仅 19 个 dmsk 供——TOTAL_PARENT_EQUITY(ROE 分母)/IBD 五件/ 折旧四件(DA 族)/RESEARCH_EXPENSE/BASIC_EPS/FE_INTEREST_EXPENSE/三减值全缺 →D 护栏下因子多数计算单元退纯基线=合并后仍 ≤5 周旧,合并白建(改道根因)。
  • static 每股 schema 分行业(银行 170/保险 253/正常 203-319-254 列)——合并层 还得吃 schema 变体。
  • 两层终值快照:dmsk income 全史 280,476 行零重复键、三表域无 UPDATE_DATE(仅 express 有);static 每股每期一行(抽样 29 文件零重述多行)——更正中间态两层皆无。
  • express/forecast 两层异源零交集(static=akshare 中文列按期全市场文件 vs dmsk= EM datacenter),本就不可合并。
  • F10 源头接口单股全史全列带 NOTICE_DATE(akshare stock_*_sheet_by_report_em (symbol="SH600519") 实测 103 期×319 列,~5s/表/股、21 页分页)——根治可行性根。

设计两件:

  1. 事件驱动补洗 job(static_overlay_wash.py,新鲜度目标本体,09-20 上线)
    • 雷达:dmsk 日班(07:10)近 8 分区×NOTICE_DATE≥T-14 窗→(code,域,报告期) →notice;与本地 static 同期值比对(per-REPORT_DATE 轴,09-20 factor review MINOR-2 精化——期级新披露 notice 旧于该股全局 max 亦命中);static 缺文件=dmsk-only 覆盖段跳过(不为北交/老退市造文件);static 文件损坏→ 全期命中→重写自愈。
    • 动作:命中股逐股 F10 全史三表重写 per-stock 文件(复用 akshare_static_ download.py 洗库函数+限速/容错/零行不写不标纪律);拉完校验 F10 max NOTICE_DATE ≥ 雷达触发值,不等=pending 队列次日重试(吸收 F10 落库晚于 dmsk 的时差)。
    • 调度拓扑(实施定稿):挂 run_dmsk.sh 第三 lane(dmsk daily/backfill 后 ~07:2x 起跑,--until 15:00 墙停,rc 隔离只记日志不进 dmsk 聚合)——免新 DSM 任务;变更清单落账 data_backup/static_overlay/manifests/,晚间镜像车 (§20.11.2)独立 manifest lane 按清单推 VPS(整单成功归档 pushed/,文件级 幂等重推)——不双拉,与 corpus/dmsk 同款「单点采集+镜像分发」。VPS 侧 新鲜度口径(strategy review m4):披露 D→D+1 晨 NAS 洗→D+1 晚镜像→ D+2 开盘 VPS 引擎可见;月频 value 无碍,事件驱动场景上 VPS 前须知此延。
    • 兜底:ak-monthly 月度全量洗库保留(扫雷达漏网+深史对齐)。周日 sync_parquet.sh 全量 scp -r 为覆盖式(09-20 factor review MAJOR-2 勘误, 此前「mtime 单向无回冲」表述错误):正常路径 VPS 内容已由晚间 manifest 推 送对齐→覆盖无害零回退;仅当该周推送失败时产生内容回退→雷达 14 天窗内 自愈重洗,窗外回退归月度全量洗兜底。
    • 峰值预估(factor 建议点):披露潮单日几百股(年报季峰值 ~800 股)×3 表× 限速 ≈3-8h,~07:2x 起跑午前完赛;淡季几十股分钟级(每股拉近 12 期≈10 发)。
    • vintage:ak-vintage 09:00 自检扩补洗账(洗了多少/pending 深度/雷达命中未洗)。
  2. pit_view 接口(sanguo_data/fund_pit.py,视图语义层,09-20 上线 2f274e3)
    • pit_view(domain, asof_dates, periods=k, symbols, columns):多期 asof 视图, 第 k 期=截至 asof 已披露的第 k 个报告期(NOTICE_DATE≤asof 含端点);asof 列表入参不预设调仓节律(回测/实盘边界一致性)。
    • 伴生:coverage 元数据(每 report_date 已披露家数/覆盖率 as of 各 asof——治 披露潮中段样本偏差,消费方披露率不足沿用上期快照;分子=首披露到达口径 =组内 NOTICE_DATE 最小≤asof——重述只推迟终值可见性不撤销到达,与视图终值 口径之差=快照窗口损失可量化,09-20 实现定稿);审计快照(按 asof 落 每票所用 report_date+NOTICE_DATE 小 parquet,月度量级,复盘回放)。
    • 失败分级照读取核契约:缺数=空 df 不 raise+原因标签;形状错 fail loud。
    • 建立在静态读取/partition_reader 之上,核零语义原则不变。

PIT 语义边界(两案相同,入档):

  • 终值快照 PIT:static/dmsk 皆无更正中间态,NOTICE_DATE=终值披露日(重述把 NOTICE_DATE 推进)——重述公告日前的初值窗口内该期不可见(宁缺毋假),asof 由 更早期前向填充兜底;与真实公告流 PIT 的差异=窗口内拿不到初值,inherent 于快照 源,审计关卡量化发生频率。
  • 拼盘态=常态:补洗后 static=各股最近一次洗库时刻的拼盘(股 A 今晨/股 B 上 月月度洗)——这正是实盘每日所见状态,回测/实盘同底座反而更真实;月度全量洗= 拼盘周期性收敛点。

消费方影响:

  • factor 零改动:fundamental_pit/_load_statements 跑在自动变新鲜的 static 上, 原「换源 merge_pit」迁移取消;dmsk 角色=披露雷达+forecast/express 快报事件+ RATIO 列直读+退市/北交段(§19.9 层间读法同日勘误)。
  • 回测/实盘同底座:LocalUnifiedProvider value 出口(get_value_metrics/_ex)内部 切 pit_view 或直读 fresh static——出口语义不变消费方无感(实施时定)。 切换纪律(strategy review M3,09-20 入档):value 实盘现行源=桥 get_fundamentals/PershareIndex,切 pit_view=换 vendor,L1~L6 分布必变—— 接入期必须同日双源漏斗对照(旧源 vs pit_view 的 L 计数 diff)+回滚预案就绪 后再切,防 final=0/非 0 语义跳变无人能解释。

验收(用户 09-20 原话「做完记得找因子验收」):

  • fixture 六条(factor 出,spec 定稿即交付):①null 公告日弃用②重述可见性 notice_eff=max(8-20 原始+9-15 重述的 9-14/9-15 分界)③决策日=公告日当天可用 含端点④空结果带原因标签⑤多期 asof「第 k 期」序列语义⑥coverage 元数据正确性。
  • 关卡②(factor 跑):补洗前 vs 补洗后 static 同窗同因子集 IC 不恶化为闸——对照 窗口选披露潮周(新鲜度差异最大化,闸门最灵敏)。
  • 关卡③(factor 跑):补洗后 static vs dmsk 交集列同键同值一致率 99%+(跨 vendor 互检,19 个交集列当镜子)。

坑:emweb F10 每股=21 页分页 ~5s/表;手搓 datacenter HTTP 探针必挂(filter 引号/括号编码),验证走 akshare 真实调用;static 探针样本别用金融股(000001 银行 schema 特殊低估交集教训);限速纪律沿 §19.9 采集纪律表;VPS 部署照铁律等口令。

实施记录(2026-09-20 回填):

  • commit 链:354b2a4(spec §20.11.7+四处勘误)→ 2f274e3(pit_view 实现+factor fixture 六条收编,全套 426 绿+NAS 真数据冒烟三股过;coverage 分子=首披露到达 口径由 fixture ⑥ 期望倒逼定稿,factor 确认=其本意)→ 本次(补洗 job TDD 16 例 +run_dmsk 第三 lane+镜像 manifest lane,全套 442 绿)。
  • 部署:wash 脚本随 CI nas-deploy 落 /app;run_dmsk.sh+push_vps_mirror_daily.sh scp -O 执行位 diff SAME 收口。
  • 首跑锚点:次日 07:2x dmsk 班后看 wash lane 三行(radar candidates/worklist/ summary)+manifests 落账;晚间 push.log 出现「static manifest lane: files=N」。
  • 双域背靠背 review(09-20 用户令,factor 3M/2m/4n + strategy 1B/3M/5m): 已修=strategy B1(GroupBy.last 拿组内最后非空值=重述行 null 静默回退旧值, 改 nth(-1) 排序末行原样取)+factor MAJOR-1(UPDATE_DATE null 排序两引擎语义 相反,na_position='first'+kind='stable' 对齐 polars)+MAJOR-3(列下推投影)+ MINOR-2(雷达 per-REPORT_DATE 比对轴)+strategy M1(行级容错跳过股 attrs['skipped_symbols'] 暴露)+M2(UPDATE_DATE 新鲜度列)+m5(no_data/ filtered_empty 边界断言)+m1/m2/m3/n4(docstring 钉死 attrs 首读纪律/columns 必须显式/dtype 标注);factor MAJOR-2=spec 周日回冲表述错误已勘误(wash docstring 原本正确);MINOR-1(emweb str 数值污染疑虑)缓至首个非零 wash 日 实测 dtypes;strategy ③补正认知入档:补洗不解决披露潮样本偏差(样本完整性 仍靠 coverage 门)。新增用例 7 条,28 测(11+17)绿。

20.12 增补 2026-09-22:UZI-SKILL-astock 源情报收编——应急备份源(DR)+快讯补充域+仲裁探针(用户拍板「备份源入档备查/补充类都采纳/对照类探针化」)

20.12.0 来源与定性(调查底账)

  • 对象=Gitea sanguo/UZI-SKILL-astock(=github gosinkx/UZI-SKILL-astock,wbh604/UZI-Skill v3.9.1 防封专项 fork,2 commit)。它是读路径工具(交互式单股分析+TTL 文件缓存+读时 fallback 链),无写库/增量/水位线——管线架构零可借,可收编的只有源情报+防封工程确认(其 em_get() 限流漏斗≡我们补洗 job emweb 1s 节流+low-freq 断路器,已有同型;「不封 IP 直连前置」链排序原则≡我们直连纪律)。
  • 本节源全部经 Mac 直连活性探针(2026-09-22,茅台锚点数据新鲜到 09-21 收盘)。探针是一时的,用时先复测。

20.12.1 应急备份源速查表(DR 预案:权威源长时间死时的切换底牌,非日常路径)

我们现有 fallback=「单一权威源落库+事后自愈」(gapsonly 回补/vintage 自检/周日全量兜底/pending 队列/xt-daily 补缺腿),没有「权威源停服 N 天」的灾难预案——本表补这个空。按权威域分组:

权威域(现源) 备份源 端点(零 key 直连) 切换成本/坑 探针
日线 OHLCV(baostock) 新浪 K 线 money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sh600519&scale=240&ma=no&datalen=N(scale=240 日线;分钟端点已 301) 不复权;JSON 日/开/高/低/收/量;symbol=sh/sz 前缀 ✅09-22
日线 OHLCV 腾讯 ifzq qfq web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=sh600519,day,,,500,qfq(fqt 空则 raw) 前复权口径需与 bs_adjust_factor 对照校准后才能入 dbbardata ✅
日线 OHLCV akshare 新浪 ak.stock_zh_a_daily(symbol="sh600519", adjust="qfq") akshare 聚合器,慢 库内已有
实时快照(xtdata 桥) 腾讯 qt qt.gtimg.cn/q=sh600519,sz300750(批量逗号;GBK;~分隔字段位:3=价 32/33/34=涨跌/高/低 39=PE(TTM) 44=流通市值(亿) 45=总市值(亿) 46=PB) 裸字段位无 schema 文档,接前逐位对照校准;中文 mojibake 不影响数值 ✅
实时快照 新浪 hq hq.sinajs.cn/list=sh600519(必须带 Referer: finance.sina.com.cn) 2026 间歇 403(flaky) 探针未过(未测)
估值 PE/PB 序列(baostock 拆列) 百度股市通 `ak.stock_zh_valuation_baidu(symbol, indicator="市盈率(TTM)" "市净率" "总市值", period="近一年")`
估值快照 雪球 akshare 后端 ak.stock_individual_spot_xq(symbol="SH600519")(52周高低/股息率TTM/总股本/流通股/PE静动动/周转率)+ ak.stock_individual_basic_info_xq(F10:行业/主营/实控人/上市日期) akshare 内部走雪球 API 面非爬虫,稳定性较好 未探
基本面三表(dmsk+static) 新浪财报三表 quotes.sina.cn/cn/api/openapi.php/CompanyFinanceService.getFinanceReport2022?paperCode=sh600519&source=lrb|fzb|llb&type=0&page=1&num=8(需 Referer;page/num 翻页) 103 期按报告期结构化(rType/币种/审计状态);中文行项 item_title vs 我们英文列名,需行项映射表;见 §20.12.4 仲裁定位 ✅
公告元数据(corpus ann=东财/巨潮) 东财公告流 np-anotice-stock.eastmoney.com/api/security/ann?sr=-1&page_size=N&page_index=1&ann_type=A&client_source=web&stock_list=600519(art_code/notice_date/title/codes) 它方自注「参数不稳定·先拉全量再客户端过滤」;对照定位见 §20.12.4 ✅
快讯流(无→§20.12.3 新增) 金十 jin10.com/flash_newest.js(JS 变量抽 JSON;id/time/type/content/important/channel) 快照型仅最新 ~70 条,日频快照落盘才有全量 ✅
快讯流 东财快讯 newsapi.eastmoney.com/kuaixun/v1/getlist_102_ajaxResult_50_1_.html(JSONP LivesList 50 条/页可翻页) id 去重键=newsid ✅

20.12.2 fallback 机制现状定位(自查结论,回应「我们是否有 fallback」)

  • 我们的模式=权威源+自愈,不是读时链式切换:日线缺失次日 sanguo-xt-daily(21:00) xt 桥补缺腿;margin/静态域 gapsonly 回补(七修版 merge keep-last 洗净);ak-quarter vintage 09:00 自检;慢变域周日全量 scp 兜底;补洗 pending 队列 30 天老化;镜像链 rc∈0/1/3 才推(rc=2 限流让路)。
  • 空档=权威源连续多日死(baostock 拉黑>1 天=日线空窗到自愈;EM datacenter 域死=dmsk/ak-events 停摆)——§20.12.1 表即为此预案。触发纪律:源死 ≥2 天才启用备份源(防日常抖动走旁路污染权威层),启用时按「staging→验证→合并」铁律走,schema 映射与复权校准前置。

20.12.3 补充域采纳:corpus flash_meta 全市场快讯域(用户拍板「都采纳」,容量评估通过)

  • 语义定位:现 corpus news=news_meta/news_fulltext 为个股新闻(东财个股面);金十+东财快讯=全市场宏观/政策/突发流(财联社类)——语义互补非重叠。东财公告 np-anotice 不入此类(ann_meta 已采公告元数据,它是对照源,见 §20.12.4)。
  • 容量评估(2026-09-22 实测底数):VPS C 盘剩 68.0G/总 193.2G;VPS corpus+dmsk 镜像现 264M;NAS corpus 权威 415M(news_meta 121M/ann_meta 119M/news_fulltext 20M/ann_pdf 1.2M/state 173M)。快讯增量估 <1M/日(金十 ~70 条快照+东财 50×N 翻页,meta 级)→ 年 <0.4G/机,双机 <1G vs 剩余 68G=无压力。
  • 设计要点(实施时 TDD 细化):新子域 corpus/flash_meta/dt=YYYY-MM-DD/(title/content/publish_time/source∈{jin10,em_kuaixun}/dedup 键=id/newsid);采集挂 run_corpus.sh 班内(06:00 顺带,两源独立 try/except 互不影响主 rc);镜像车 corpus 四子域扩为五子域(journal 指纹 diff 同机制);消费接口 corpus_reader 加 flash 域入口(空 df 带 schema)。
  • 实施记录(09-22 当日 TDD 落地):corpus_download.py --lane flash(金十 _parse_jin10_payload JS 变量抽取+东财 _parse_em_kuaixun_payload JSONP;norm_flash_row 归一 flash_id=源前缀+源站 id;fetch_em_kuaixun 翻页 20 页硬顶+页内最老条目<昨日 00:00 停界;当日 marker 幂等;源级隔离单源失败不炸另一源;rc 语义照旧 failed>0=1);run_corpus_standalone.sh 第三 lane(rc 隔离不进聚合,独立跑不 gate 于 daily/backfill——两主 lane 全让路也不漏当天快讯);vps_mirror_lib FAMILIES corpus 五子域(新域=指纹全新首跑自动全量推一次);corpus_reader.get_flash(start,end,sources)+FLASH_COLUMNS 空 schema 兜底。TDD +13 例(parse 垃圾兜底/norm title-null 截 80/lane 落盘/账本去重复跑/marker 当日跳过/源隔离/翻页停界×2/reader 读+空 schema+日期窗/mirror 子域+指纹),全套 465 绿。Mac 真网络冒烟:金十 50 条+东财 884 新(跨页 dup 16 批内去重拦截),21s 完赛 1.2s 域节奏,dt 跨度=昨日 20:24→今晨(T-1 边界实证);幂等复跑 units=0 零请求。首班锚点=次日 06:0x cron.log「flash lane exit=0(隔离)」行+当晚 push.log corpus 段含 flash_meta 分区。

20.12.4 对照类终版:xcheck 跨 vendor 对账域(09-22 用户拍板「落盘+定期探查+及时仲裁+全程可追溯」)

独立子域 corpus/xcheck/,只读对照、永不 merge 进权威层(独立性的关键是永不合并,不是不落盘)。载体=scripts/data_platform/xcheck.py(域唯一入口,static_overlay_wash.py 同款设施脚本先例)。

时机=两档(事件驱动主档+漂移兜底档):

档 触发 照什么 窗口
主档·写后即照 权威层变更事件:corpus daily 完赛(ann 增量)/wash 重写完赛(manifests 命中股) 只照变更单元 当天
兜底档·漂移检测(Phase 2b) 周期:估值周度/三表月度 全市场抽样+分布分位数跨源对比 抓口径级慢性漂移(单点对照的盲区)

主档三 lane:--lane corpus_side(ann_em 拉取+公告披露日对照+腾讯 qt 全市场估值快照落盘,挂 corpus 班尾部);--lane fund_side(读 wash manifests 当日命中股→新浪三表近 12 期拉取落盘+三表对照,挂 dmsk 班尾部);--report(人工查询汇总)。

内容=四层漏斗+按需收窄+阈值分档:①键完整性(行有没有,零拉取纯本地)→②PIT 披露日(NOTICE_DATE,factor 生命线)→③数值列(只照消费方声明列,factor 40 原料列起步;阈值 <0.1% 静默 / 0.1~1% 记录 / >1% 或披露日差≥1 天报警)→④分布漂移(兜底档专用)。首期实施范围=①②+估值数值对照(qt 字段位 vs valuation parquet peTTM/pbMRQ,列少且明确);三表数值列对照 Phase 2b 已实施(09-22 深夜,见下方实施记录);NOTICE_DATE 对照首期即含 dmsk vs static 两源本地比对(零拉取)。

Phase 2b 实施记录(2026-09-22 勘测→TDD→实数冒烟当日闭环):

  1. 映射表 SINA_FIELD_MAP:新浪行项自带 item_field 英文代码(比中文行项稳,中文有「利息收入」两现歧义)→ EM 声明列。覆盖 income 13/14 + balance 15/15 + cashflow 7/11 = 35 列;消费方 41 声明列(fundamental_schema._TABLE_RAW+_BALANCE_COLS)全覆盖或入 SINA_UNMAPPABLE(扣非不在三表;DA 折旧摊销四件=间接法补充资料,openapi getFinanceReport2022 仅直编法主表,type/source 参数面已全扫无此面——老 vDOWN 通道挂 backlog)。
  2. 行业变体按值非空回退:同 EM 列分普通/银行(600036)/保险(601318)三套字段(PARENT_NETPROFIT←PARENETP|NETPARECOMPPROF|NETPARESHARPROF 等 5 组),四股(+格力 000651)数值级 EQ 锚定;EM 用统一列名、新浪分行业字段是两源 schema 根本差异;static 缺列=变体跳过非 finding。FE_INTEREST_EXPENSE=其中:利息费用 INTERESTEXPENSE(非财务费用全项 FINEXPE,值差 108% 勘误排除)。
  3. 层③ compare_statement_values:近 12 期交集 × 映射列,阈值沿用估值域;单侧空/static=0 → L1 coverage(vendor 稀疏档案:EM CREDIT_IMPAIRMENT_LOSS 对茅台整列死 0/103、OTHER_RECE 70/103、ACCEPT_INVEST_CASH 12/99,非数据丢失)。
  4. 两枚预跑 bug 修复(勘测抓到,首班前消灭):①期键格式——新浪 20260630 vs static 2026-06-30 永不相交,层①层③空转,_norm_sina_period 归一;②层①窗——新浪 12 期对 static 全史 103 期必刷 91 条 static_only 噪声,改并集最近 12 期窗。
  5. 兜底漂移档落地:估值=周一(复用 corpus_side 同班 qt snap/vb 零额外请求,全市场 peTTM/pbMRQ 中位数偏差>1% → 单条 __MARKET__ L2);三表=月初 7 天窗(fund_side 班尾抽 30 股×三表对照,L2 率>5% → 单条 __SAMPLE__ 聚合 L2 不逐股刷屏,按日 seed 确定性抽样);XCHECK_DRIFT=0 总关。零新 schtask 零 wrapper 改动。
  6. 新浪原料升级:旧 periods.json → sina_fin/dt=YYYY-MM-DD/{symbol}_{domain}.parquet 全行项长表(report_period/item_field/item_value),证据快照可回放。
  7. EM 死列发现:SHORT_FIN_PAYABLE 为 2019 准则合并前旧列(茅台 0/103、格力 null 全实证),真数据在 NOTE_ACCOUNTS_PAYABLE(格力 EQ 实证)——映射表附加该声明外行(factor IBD 观察供料);factor _IBD_PARTS 含 SHORT_FIN_PAYABLE,2019 后 IBD 静默缺应付票据组件(已单向提醒 factor 线)。
  8. 首班预期(实数冒烟 519/036/318 三股预告):正常股 L2=0;银行 ISSUE_BOND/PAY_DEBT_CASH 与保险 ACCEPT_INVEST_CASH 存在系统性口径分歧(新浪>EM,疑似同业存单/保险投资现金口径)→ 真实 findings 攒 root_cause 档案,不预设降级。

结果五级路由:L0 三方一致→静默计数;L1 舍入级(<0.1%)→记录(攒 vendor 习惯差异档案,反向解释口径);L2 实质差异→报警+suspect 清单(晨检可见);L3 两源同第三源异→多数派仲裁→写 wash pending 队列(复用 §20.11.7 补洗重试通道,次日 wash 重洗=修正不直改数据;L3_AUTO 开关默认 0=只报告不触发,稳定后用户口令开);L4 三方互异→人工裁。

可追溯机制(09-22 用户点名「初期一堆问题须可查根因」):

  1. 证据快照内嵌:findings 每行携带对照时刻的三方原始值(values JSON 列)——出问题可回放「当时三家各说了什么」,不依赖重拉。
  2. trace_id 贯穿:xc-YYYYMMDD-NNNN 递增;发现→仲裁→wash 重洗→复验对照,同一 id 串全程;wash 侧 manifest 反链 trace。
  3. 报告不可变追加:xcheck/reports/dt=YYYY-MM-DD/findings.parquet(列=trace_id/level/domain/symbol/report_date/column/values/deviation/root_cause/action/status);status 流转 discovered→queued_wash→reverified/closed。
  4. 根因分类学:root_cause∈{schema_drift, unit_scale, timezone, mapping_error, source_bug, real_data_error, unknown}——初期问题打标签攒统计,为映射表迭代供料。
  5. 干跑模式:--dry-run 只出报告零触发(首跑观察用)。
  6. 半截防线同款:报告 tmp+rename 原子写;对照读权威层只读。

消费方终态(09-22 用户问「消费方拿到什么」的定稿答复):主消费路径零变化(pit_view/static/dmsk 照旧);差异在质量时间维度(错值修正窗口从月度洗库缩到当天/次日);新增可选质检元数据(xcheck 状态可查,不进主 df);xcheck 原始镜像=仲裁原料不直接消费。xcheck 域不推 VPS 镜像(NAS 侧质检设施,非消费数据,省链路)。

20.12.5 备档不采纳(防重复调查)

港美股线(yfinance/etnet/HKEXNews/AASTOCKS);efinance(akshare 同型多一依赖);Playwright 浏览器源全族(雪球需登录 cookie 6h 过期/同花顺 F10/iwencai/乐咕——服务端采集纪律不容);monkey-patch requests 全局超时(CI 三连挂教训:勿 patch 共享库本体);net_timeout_guard/TTL 文件缓存/读时 fallback 链(读路径工程,我们是落库权威层);hot_rank 间歇断供已收口(09-22 调研:0917/18/21 三晚 emappdata RemoteDisconnected 服务端掐连接,09-22 自愈三重实证;病因两假说未定论=服务端间歇故障 vs VPS IP 间歇风控,断供窗内缺第二 IP 对照;复发判别树+证据位+换源决策线[连续≥3 晚才动]=运维 runbook §7.5 数据源间歇断供档案;快照型断供晚=该日永久丢,无自愈窗是防污染正确设计);hottrend 六平台社会热榜(微博/知乎/百度/抖音/头条/B站,语义≠个股人气榜,抖音有签名反爬);tushare(token 积分制,三表深史/top_list 深度/北向机构级——未来需要再启);MX 妙想 API(东财官方 NLP,免费 key dl.dfcfs.com/m/itc4,管线化采集意义小);期货/现货域(99 期货网库存/仓单/基差、生意社 100ppi、三大商品所+INE 日报——factor 商品因子需要时再勘测);官方宏观域(中债国债收益率曲线[WACC 锚]/统计局/央行/Shibor——估值贴现率需要时再勘测);baostock query_profit_data(季频 roeAvg/npMargin/gpMargin/netProfit/epsTTM/MBRevenue——factor 线 fa 类季频指标的官方源备选,与 PershareIndex 重叠,需要时对照定权威)。

20.13 增补 2026-09-22:因子 P1 数据类增量(研报共识+质押两新域;六项联合勘测定案)

背景:factor 七项目调研的 P1 数据类(用户令「数据类先联合数据 session 做现状调研和联合设计」),09-22 当日联合勘测定案。六项归属终表:

项 终态
③龙虎榜月度聚合 存量零新采——因子直读 static/dragon_tiger/ per-date 文件(fundamental_statements 直读 static 树同款先例),数据域不加接口;上榜原因+上榜后 1/2/5/10 日表现现成
④北向个股级 终局定案(09-22 用户拍板):维持季频,付费源先不上——§20.4 终审:日频个股明细 2024-08-16 起永久停发(HKEX 制度),仅季末快照(nb_hold 既采零成本);factor 按季频约束设计不入 P1,backlog 挂免费备选
⑤dividend 存量直接支持——static/dividend/ baostock per-stock 5538 股×15 列(dividOperateDate 除息日/dividPlanAnnounceDate 公告日/dividCashPsBeforeTax 每股税前);factor E14-16 已定稿(div_ttm 滚动 12 月除息日窗),零新采集
⑥股吧情绪 砍——corpus news_meta 88 万条量维度首验覆盖门;flash_meta 记 S05 扩展候选
①研报共识 新域 research_report(本节)
②质押 新域 pledge(本节)

20.13.1 research_report 研报共识域(东财 reportapi 直连)

  • 源:reportapi.eastmoney.com/report/list(qType=0 个股研报周窗流)直连薄客户端(不走 akshare——其 stock_research_report_em 封装缺目标价/评级调整字段);1s 限流+翻页(pageSize=100)。实测:周窗 hits=111/2 页 0.3s,3 年回填≈312 发≈5 分钟。
  • 字段直存(§15.2 列随源):stockCode/stockName/orgCode/orgName/orgSName/emRatingName/sRatingName/ratingChange/publishDate/predictThisYear{Eps,Pe}/predictNextYear{Eps,Pe}/predictNextTwoYear{Eps,Pe}/indvAimPriceL/indvAimPriceT(目标价低/高,部分研报带值)/title/infoCode/emIndustryCode。
  • PIT=发布日(publishDate 条目级);采集组织粒度=周窗(新 PER_WEEK 类目:周六班拉上周窗全市场,文件 YYYYMMDD_research_report.parquet=当周窗全部条目;marker 同款断点幂等;回填 --start 20210701 逐周窗)。
  • 消费面(factor 定稿 5 因子):评级分布(买入+增持占比)/覆盖券商数(近 N 月研报数)/consensus forward EP(与 D13 公司预告版独立源互证)/目标价溢价(有值样本 median(indvAimPriceT)/close−1,空值不算分母)/ratingChange 共识拐点(窗内净升级次数)。

20.13.2 pledge 质押域(周频快照)

  • 源:ak.stock_gpzy_pledge_ratio_em(date=周五)(个股级周频快照,2,200+行/期:质押比例[总股本口径]/质押股数/市值/笔数/无限售vs限售拆分);走 call_ak_with_retry 既有模式。回溯实证 2021-01-08=2,445 行(factor 评估窗 2021-07 起全覆盖)。
  • 降级备案(09-22 晚撤销):初判「实控人质押免费面无」只勘了 3 个函数名;全枚举 gpzy 族后发现 stock_gpzy_pledge_ratio_detail_em()(无参全量快照)——126,713 行股东级质押明细:股东名称/质押股份数量/占所持股份比例/占总股本比例(双口径)/质押机构/预估平仓线/质押开始·结束日期/状态(未解押/解押史)/公告日期(PIT 锚)。实控人质押比例=股东名称×实控人名单(static F10 actual_controller)join 可算,降级撤销。
  • 域形态升级=两子数据:①pledge_ratio 周频快照(原设计不变,快速聚合口径);②pledge_detail 股东级明细全量快照(~12.7 万行/次≈25MB,月频留存[factor 定];实控人质押原料+平仓线风险字段白送;stock_gpzy_individual_pledge_ratio_detail_em(symbol) 为 per-stock 版备查)。
  • 历史时序=消费侧区间重建(factor 设计要点):detail 是无参全量当前快照,asof∈[质押开始,结束) 且公告日期≤asof 即在押——PIT 干净。解押史留存深度已实测(09-22 晚):开始日期最早 1997-02-27(近 30 年全史),已解押 107,021 条中 2022 前解押 73,645 条/2024 前 87,676 条全留存(2016/2018 年老质押样例在案)→ 候选③④可回测全窗立即可用,非前向积累;采集侧=首拉一次即得全史底座+月频增量留存。
  • PIT=快照周(asof 取 ≤asof 最近一期);采集=ak-weekly 周六拉上周五快照,回填 --start 20210108 逐周五。
  • 消费面(factor 09-22 定格 2 主+2 候选):主①pledge_ratio 总股本质押比例(负向);主②pledge_ctrl 实控人质押比例(主口径=实控人质押/其所持=个人压力,变体=占总股本);候选③pledge_margin_dist 平仓线距离(现价 vs 预估平仓线安全垫,需 close join);候选④pledge_net_chg 存量质押净变化(解押−新质押净流)。

20.13.3 实施记录(2026-09-22 块一当日落地;原实施清单已兑现并按实测两处改良)

  1. 注册表三类型(akshare_static_download.py,§15.1 单脚本红线零新脚本):
    • pledge_ratio=per-Friday 枚举(非 PER_DATE 全工作日!实测 09-22:周五 20260918=2,212 行,周一 20260921 EM result=None → akshare 抛 NoneType 错——若走全工作日枚举 Mon-Thu 全 failed 必触断路器)。未发布周五同款异常 → failed 不写 marker → 下周班窗口重含该期自动补拉(滞后最多一周自愈)。
    • pledge_detail=改走 fetch_em_dc_pages 节流通道(对 akshare 封装 memo 的实测改良:RPTA_APP_ACCUMDETAILS 全量 126,713 行=254 页×500,akshare 封装内部连发无间隔必撞 §15.3 300发/5min 红线;节流通道 1.2s/页≈6 分钟)。MXID 唯一键去重防页边界漂移(margin 六修同型防线);raw 字段白捡 IS_CONTROL_SHAREHOLDER(控股股东直标列,pledge_ctrl 因子比股东名 join 更干净)。月桶留存=unit {YYYYMM}_pledge_detail,每月首班落盘月内 marker 幂等。
    • research_report=PER_WEEK 新粒度类目(anchor=周五,窗=所在周周一..周五;周六班 end=今天 → anchor=昨日周五窗完整收口);reportapi 直连薄客户端 _report_get(1s 节流+session 复用,同 _em_dc_get 形态)+_fetch_report_pages(TotalPage 停界)。EM 空值表示='' 统一转 None(ratingChange 混 int/'' pyarrow 转型炸,Mac 冒烟实锤当日修)。
  2. sync 侧=listing 段(sync_parquet_daily.sh 新增三域循环,有意不走 TYPES 滚动窗——红线 §20.10.4 的意图是 NAS 覆盖不滞后,形态选更强的:三域文件 write-once(marker 语义)且锚不在滚动窗形态;若某周五首班失败次周补落=文件龄 8 天已滚出 7 天窗,TYPES 必漏而 skip-if-exists listing 必追上;同 gdhs/nb_hold 先例)。
  3. 调度挂载=sanguo-ak-weekly(周六 03:00 ak_stock_wrapper.ps1 追加两条独立命令:--types pledge_ratio,pledge_detail --start 20210108 + --types research_report --start 20210701;不带 --force——与首段 per-stock 马拉松的 --force 语义隔离,marker 幂等增量)。ak-events(19:30)显式 --types 不受影响零变化。
  4. TDD 20 例(周五枚举×2/月桶×3/detail 节流参数+MXID 去重/周窗锚×3/翻页停界×2/混型写盘/registry/幂等),503 全绿;Mac 冒烟双绿(pledge_ratio 2,212 行 + research_report 103 行/51 列原生直存、目标价 4/103 带值、publishDate 恰为窗周一..周五)。
  5. 回填=pledge_ratio --start 20210108(~300 周五)+research_report --start 20210701(~275 周窗)+pledge_detail 首拉一次(254 页≈6 分钟即得 1997 起全史解押底座)。
  6. fixture:factor 侧两组 RED(研报五因子+质押 2 主 2 候选)为块二验收,数据域已备全窗重建语义原料。

20.14 增补 2026-09-25:hot_rank 采集迁 NAS(emappdata 云 IP 断连定论)+ xueqiu_hot TLS 反爬修复

背景定论(哨兵双 IP 对照实证):emappdata.eastmoney.com(人气榜)对 VPS 云 IP 间歇断连——0923/0924/0925 三晚 RemoteDisconnected 3/3,同分钟窗 Mac/NAS 家宽 IP 全 200(09-24 夜 20:30:00 Mac ok vs 20:30:09 VPS 断,四发重试同签名);假说 A(服务端故障)排除、B(云 IP 被针对性断连)成立。东财其余三域(datacenter/push2ex/reportapi)同期 VPS 正常,断连精确锁定 emappdata 一域。用户拍板(09-25):采集迁 NAS 家宽出口,数据维护在 NAS/VPS 双机之间(Mac 只留纯观测探针不留数据)。

hot_rank NAS 采集链:

  • 采集=scripts/data_platform/hot_rank_nas_fetch.py(一次性容器 sanguo_vnpy_v2:lock-aligned,corpus 同款模式):排名源 emappdata getAllCurrentList(与 akshare stock_hot_rank_em 同端点同参数,Top100=产品全量)× 行情 join 源腾讯 qt.gtimg(akshare 原用 push2 ulist——09-25 实测该端点对家宽出口恒空响应、对 VPS 可用,本脚本跑 NAS 故换源;腾讯无风控)。
  • 列 schema 与 akshare 历史产物同款 6 中文列;口径注记:涨跌额/涨跌幅取腾讯交易所口径(akshare 为 最新价×涨跌幅/100 公式口径,两者差<0.01)。
  • 调度=corpus 班尾(run_corpus_standalone.sh 尾挂 run_hot_rank_nas.sh,~17:35 执行;DSM 零新任务注册);产物 NAS 正本 /volume1/stock/hot_rank_nas/YYYYMMDD_hot_rank.parquet + scp 推 VPS static/hot_rank/ 合并(vps-mirror 同 KEY 通道);推送幂等(.pushed marker,未推日期下班自动补推);rc 隔离恒 exit 0 不进 corpus 聚合。
  • VPS 侧 ak_events_wrapper.ps1 同批摘除 hot_rank 类型(防双写冲突);VPS retry 班(sanguo-ak-events-retry,weekly MON-FRI 20:30 起每小时×4 发)保留——兜 dragon_tiger 等 EM 当日未出数的时序失败。
  • 历史缺口 0923/0924/0925 三天:断供期数据不可回补(人气榜快照型),消费方为零现役因子(S05 候选观察),接受。

xueqiu_hot TLS 反爬修复(同批):xueqiu.com 09-21 起上线 TLS 指纹反爬——requests/urllib3 指纹恒 HTTP 418 空体(Mac/VPS/akshare 1.18.88 三方实测同挂),curl 指纹放行。fetch_xueqiu_hot 弃 akshare 封装改 _xq_screener_rows(subprocess curl 翻页 29 页×0.3s,极简头 UA+Referer),列 schema 同历史 4 列(股票代码/股票简称/关注/最新价),失败返 None 语义不变。缺口 09190925 快照型不可回补,接受。

20.15 增补 2026-09-25:数据面监控体系(用户拍板「监控内容越多越好」+告警通道=vnpy 前端运维告警页)

定位与原则(用户四令):①VPS/NAS 分开监控各看各的(本节先落 VPS,NAS 侧 v2 同款后做);②只读体检不修数据(产出报告+告警,处置归晨检 agent/人);③「下载完全与否」以数据本体为最终证据(log/marker 只证过程,见四层证据链);④告警通道=vnpy 前端「运维告警」页(四类告警统一入口:数据/策略/因子/运维——各域 session 按同一事件 schema 写入,页面零改造自动呈现)。

20.15.1 被监控对象注册表(本 spec §18.8/§20 调度表为权威源,监控脚本不自行维护清单)

频率语义五类:日频(期望最新=最后交易日 T)/周频(=最后周五 F)/季频(报告期日历)/月桶(YYYYMM)/快照型(当天采当天有,缺=永久缺)。行数带宽 10-01 起改滚动分位带(见表后段)。

域 频率/期望最新 路径(VPS data/) 行数带宽 班次
dbbardata 日线+15m 日/T quant_trading.db 按 symbol 最新交易日抽样 bs-daily 18:05(马拉松~21:50)
valuation_baostock 日/T valuation_baostock/ 年 parquet 当年文件 mtime=T 同上(拆列腿)
valuation(ak 逐股族) 日/T static/valuation/ ~5,570 文件 统计行 ok 数 ak-daily 19:00
dragon_tiger/block_trade/restricted 日/T static/<域>/YYYYMMDD_*.parquet (0,400)/(30,300)/(0,60)=registry 现值 ak-events 19:30
dragon_tiger_seats 日/T static/dragon_tiger_seats/ (200,2000)=registry 现值(1010 校准, 实测 670810; spec 初值 0300 已废) 同上独立命令
zt_pool×3 日/T static/zt_pool*/ ~30-80/5-15/5-20 同上
fund_flow_industry/concept 日/T static/fund_flow_*/ =90/~350-450 同上
ths_industry/concept、sina_sector、sw_industry 日/T static/ =90/~375/49/31 同上
xueqiu_hot 日/T(快照) static/xueqiu_hot/ 5,600~5,700 同上(curl 版 §20.14)
hot_rank 日/T(快照) static/hot_rank/(NAS 采推来 §20.14) =100 恒 NAS 班尾~17:35+scp
margin(T-3T-1)/margin_sse(T-2T-1) 日/T-1、T-2 static/margin*/ (200,8000)=registry 现值(1010 校准: 两融标的逐年扩容, margin 实测 6051 破旧 4000 上限 0929/30 连黄实案; SSE 子集 ~3300 同步) 同上+weekly 回补
nb_daily 日/T-1~T static/nb_daily/ 50~80 同上独立命令(seats 行已上移 1010 校准)
nb_hold 季/报告期快照 static/nb_hold/ 快照未变即 skip 同上
ETF/基金 xt 腿 日/T dbbardata 同日线抽样 xt-daily 21:00
9 指数 日/T dbbardata(SSE 表) 9 行/日 idx 18:30
fundamentals_baostock 日(增量) fundamentals_baostock/ fund 统计行 bs-daily 尾腿
gdhs/share_capital/top_holders/financial_abstract 周/季混合 static/ 报告期枚举 ak-weekly 周六 03:00
pledge_ratio 周/F static/pledge_ratio/ ~2,200/期 同上
research_report 周/F 窗 static/research_report/ ~100-600/窗 同上
pledge_detail 月桶/YYYYMM static/pledge_detail/ ~12 万/桶 同上
三表 marathon 季(财报季首周六) static/ 5,555 股/表 ak-monthly(下次 11-07)
constituent/index_const_hist 月/16 日 dbbardata+index_const_hist 14,496/44 文件 idx-monthly 19:50
vintage 自检结论 日 vintage_status.json 读结论字段 ak-vintage 09:00
磁盘水位 日 — 剩余>20G —

行数带宽=滚动分位带(10-01 用户拍板「监控问题统一处理」,P2-6 根治):注册表 row_band 语义升格 (floor, fallback_hi)——floor=绝对下限永不下调(采集缓降不「带内绿掉」);带内判据=P1P99(窗口=最近 30 个 prior 文件、剔 0 行真空与被测观测,非 0 观测<10 回退静态整带=冷启动;实现 monitor_checks.rolling_rows_band)。静态上限三次被真实增长涨破的手动校准史(0be832d seats/3f675ed margin/4755e8d margin_sse 同步)即滚动化论证;上界失控由 trailing-P99 机理兜住(双写翻倍 Day1 即黄)。已知形态:公告驱动缓涨(两融标的扩容)窗口吸收期连黄数日数周=非静默信号,按公告核对后可容忍。month_bucket(月桶观测稀)恒静态不滚动。表内「=registry 现值」诸数自此=floor+冷启动回退值。

调度层另含:19 个 schtask 在岗检查(下次运行≠N/A、上次运行=预期班次、上次结果;主动禁用 Disabled 跳过——1010 二审 P2-6,qmt-relogin 检修暂停误红实案;strategy-monitor morn/eve 两班 1010 补入名单——监控自身死亡全链静默缺口;data-monitor eve/morn 两班 10-01 二轮审计 P1-10 同款入岗,两班互盯盖单班机械故障,双班全死盲区由 strategy 域 health 文件 mtime 反盯补)——retry 任务「一次性跑完即死」案即此类。

20.15.2 四层证据链与分类学

「完全与否」四层(弱→强,以④为准):①任务 exit 码(类型级失败不抬码,最弱)→ ②类型级统计行 {"ok":N,"failed":M,"rows":R} 解析+失败签名分诊(RemoteDisconnected=断连族红/NoneType=源当日未出黄/TLS 418=源改版红/KeyError=源字段变更红/断路器触发=熔断连累红)→ ③marker 按日比对(标了≠数据对,0×0 案)→ ④数据本体(存在+行数带宽+schema+值域)。

分类学四层:调度层(任务在岗+班次延迟)、过程层(统计行分诊+熔断连累检测——周班某类型熔断会跳过后续整批类型)、结果层(注册表逐类型新鲜度+行数带宽+交易日历对齐防节假日误报)、衍生层(前夜红项自愈回看+xcheck findings 趋势消费[ NAS 侧 ]+磁盘水位)。

结果层缺失分级(定案,09-26 中秋反转案):交易日历=确认集(dbbardata 000300 实证)∪近 15 日工作日假定集(防 dbbardata 晚间源滞后塌全体期望)。缺失遇未确认日=黄(节假日/合并窗/源滞后三态容忍),不因时间升红——2026-09-25 周五中秋休市实案(9-259-27 连休):时间基线升级(越过次日 ready 即红)会在 09260927 晚把全 per_date 域连坐误红,三源(baostock/sina/EM)同缺一日本就是休市形态而非源滞后;确认日缺失=红(跨域互证=真是交易日)。真漏采兜底=确认集推进(市场恢复交易后 exp 随 confirmed 前移,latest 落后已确认 exp → 确认日红接手)+调度层 schtask 在岗+过程层统计行,纵深分工。09-27 审计终局 P1 四修:①kind 归并修复——绿路径统一返 stale key 而 rows key 只在黄时存在,rows 类黄绿班永不 resolve(sw_industry/block_trade 悬死实案)→ 绿班 passed 恒收 data-{name}-rows(全 kind);②row-band 豁免——未确认日 0 行空文件(节假日闸门产物)不告 rows(block_trade band 下限>0 误黄实案),交易日 0 行仍黄保持感知;③weekly 锚 confirmed 过滤——expected_weekly 周五锚须在确认集(假定集假周五 0925/1002 免疫,锚自动回上一真周五),confirmed 空集降级不过滤防 exp=None 静默假绿;④health 拆 checks_overall/alerts_overall(overall 保兼容取最坏)——防 checks 全绿而 alerts 层 26h 窗旧红回声时晨检被 overall=red 误导航。09-28 开盘巡检三修(monitor 口径噪声根治):①row-band 豁免改按文件日期(latest)判而非 exp——lag 型 per_date(margin/margin_sse T-1,registry lag=1)的 exp=ok[-1-lag]=确认日,旧豁免条件对闸门空写的非确认日 0 行文件(0927 20260925_margin_sse.parquet 假黄实案)永不成立;weekly 同型(假周五空写文件)。②schtask weekday 限 26h→72h——weekday 任务(ak-events-retry 20:30/qmt-probe0915 09:15)周五晚跑完→周一晚班次跨度 69h,26h 限周一早班必假黄(0928 实案 57h/71h);真死 >72h 仍黄+next_run=N/A→red 兜底。③NAS nas-dmsk mtime 80h→季频披露锚——dmsk 五域季频披露驱动(无新披露不写盘,Q2 报告期水位 06-30 停滞属正常节奏),改「最新 dt= 分区 ≥ 最近已过法定披露截止的季末」(Q1→04-30/半年报→08-31[1010 二审 P2-1 勘正:法定=上半年结束后 2 个月内,原写 09-30 向宽松错 30 天]/三季报→10-31/年报→次年 04-30;五域取 max,三表法定必披露为门槛主体,express/forecast 条件披露只助推 latest 不抬门槛;分区名只认 ISO YYYY-MM-DD 格式防紧凑格式静默错序)。另:bs-daily last_result=1(0927 eod 腿 baostock 网络错误 10002007,fund 腿独立照跑、窗口无新交易日无数据损失)与 ak-weekly rc=1(share_capital failed 群)为正确告警非口径问题,不改。10-03 休市表根治(连休假黄):假定集剔 monitor_registry.EXCHANGE_HOLIDAYS(年度交易所休市表,仅工作日休市日)——已知假日=零期望,0925 中秋/10011007 国庆类连休当夜即绿不再假黄;fail-safe=表缺年不扣(黄照旧,绝不静默转绿);当年无表 → CI test_holiday_table_covers_current_year 红强制年更(25063ca「禁裸墙钟」教条的故意例外——此测试职责就是墙钟敏感);确认集恒保留(数据本体是真相,表错不吞真相);错登真交易日会掩盖真缺失 → 只登 dbbardata 实证+交易所公告日(2026 表=000300 实证至 1002+2026-09-17 公告:中秋 092527 休/国庆 1001~1007 休、10-08[周四]复市——勘正全员「10-09 开盘」旧误记)。

20.15.3 两班调度与产物

sanguo-data-monitor(VPS schtask,python 纯 stdlib+pyarrow 读 parquet 元数据):23:50 当晚终检(当晚班次全收尾,红项当晚出)+ 08:05 晨间全量(补过夜项+前夜自愈回看)。产物双轨:data/monitor/health_YYYYMMDD.json(机器消费——晨检 agent 首读,绿一行收口)+ 告警事件写 alerts 汇聚(人消费——前端页)。

实施态(2026-09-25 落地):任务名 sanguo-data-monitor-eve(23:50)/sanguo-data-monitor-morn(08:05),wrapper 恒 exit 0(红态由 alerts/health 承载,防污染调度层自检);health 产物=data/monitor/health_YYYYMMDD_<shift>.json+health_latest.json;告警库=env SANGUO_ALERTS_DB 缺省 data/alerts.db(监控单写、sanguo_api 只读+ack);注册表落 scripts/data_platform/monitor_registry.py(与 ALL_TYPES 交叉核对测试钉死防漏登记,含 schtask 在岗清单 §20.10.2);NAS v2=挂 sanguo-vps-mirror 16:00 班尾(scripts/nas_sync/run_monitor_nas.sh,corpus 双 lane/dmsk/hot_rank 三查/mirror 完成度/xcheck/磁盘六族),事件 JSON(零事件也写,带 generated_at 供 VPS 静默检测)scp 至 VPS data/monitor/inbox/ 由两班摄取;前端路由 /ops-alerts(导航红点=GET /alerts/summary 的 open_red)。

退出码表(09-27 补登,zcode 体检线):data_monitor 0=绿/黄不抬码(黄态由 alerts 承载)|3=有红(wrapper 恒转 0,红态由 alerts/health 承载防污染调度层自检)。采集器 akshare_static_download 0=完成|1=致命错误(akshare 装载/股票列表失败)|2=断路器触发(可重试,字段形状类失败豁免不计 §15.4)。ak-vintage 3=有发现(设计退出码非故障,schtask OK 集 {"0","3","267009","267011"} 含之)。health JSON 字段:overall=兼容聚合(checks×alerts 取最坏)|checks_overall/alerts_overall(09-27 拆分,防 checks 绿而 alerts 旧红回声时晨检误导航)。

20.15.4 告警事件模型与汇聚(vnpy 前端「运维告警」页)

汇聚点=VPS sanguo_api(sqlite data/alerts.db;选 VPS 因外网可达+NAS→VPS 推送通道现成,反向不通):VPS 监控直写;NAS 监控(v2)同 schema scp 推送。四类告警(data/strategy/factor/infra)统一 schema:

{"alert_id": "<source>-<域>-<异常>-<YYYYMMDD>",  // 确定性 ID=幂等去重
 "source": "data|strategy|factor|infra", "host": "vps|nas",
 "severity": "red|yellow", "title": "...", "detail": "...",
 "evidence": {...监控 JSON 切片...},
 "first_seen": "...", "last_seen": "...", "count": N,
 "status": "open|acked|resolved", "resolved_at": null}

生命周期:监控每晚重评——持续异常 count++(连续 N 晚标题自动标「第 N 晚」=升级);检查转绿自动 resolved(附恢复时刻);人工只能 ack。resolved 留 30 天滚动,黄项留 14 天。API:GET /alerts?source=&severity=&status=、POST /alerts/{id}/ack;前端页=控制台新增「运维告警」(四类 tab+红黄/状态筛选+evidence 详情渲染,红项角标)。

20.15.5 实施步骤

①alerts 存储+API(sanguo_api 路由)→ ②VPS 监控脚本+告警接入(注册表从本节表导出+akshare_static_download.py TYPES 交叉核对防漏登记)→ ③前端告警页 → ④NAS 监控 v2(同 schema 推 VPS;含 NAS 侧特有项:corpus 双 lane/vps-mirror 水位线/03:00 sync 链/xcheck findings)。数据面监控+事件模型=data session 域;策略/因子告警生产方=各自 session 按 schema 接入。

20.16 增补 2026-10-02:漏斗分诊+事件快照+完整性门(P4-3 收官刀,流水线 spec §4.8 F1-F7 的数据线细节版)

产物=corpus 族两新城(append-only dt 分区=采集日,永不重算;cd.ID_KEYS 两行):

  • events_in:LLM 候选输入切片(content_hash 内容寻址+src 域/id+event_date+title+text_snippet≤500 字)——防编数快照:喂模型的确切文本先落盘,可回放对拍;词表件不入(确定性层零成本可重放)。
  • events_llm:事件判读统一域(event_id=hash(content_hash+type+code+direction)/content_hash 外键/event_type 八类枚举/direction/confidence/model=lexicon 或模型名)。

采集件(scripts/data_platform/):

  • funnel_lexicon.py:第一层词表(八类+否定前缀守卫,sentiment_lexicon 范式;分类学扩充=词表加行)。
  • corpus_funnel.py:夜批(自有 flock state/funnel.lock);水位 state/funnel_watermark.json(news_meta/ann_meta 各自只前向);LLM 候选持久队列 state/funnel_pending.jsonl(预算停摆残余次夜续,marker=content_hash);LLM 契约=stock_code/event_date 系统侧注入+确定性后检(单项违规丢弃计 parse_fail);Ctx 复用(token 预算=rc3 checkpoint;--limit=LLM 调用数;--llm-cap 每夜新鲜候选 200);卡片需求面(data_check 态 dataNeeds)记录进 stats 不驱动;stats 行 [funnel] 完成 统计: {...} 兼容监控过程层解析。
  • integrity_gate.py:三层门(L1 profile 域存在性——新鲜度归监控不归门;L2 字段四元组 12 项 6 critical 行级有效率≥0.95;L3 充实度空率≤50%);profile-aware 分母(default=corpus 五域/events=两新城);exit 1(crit)/2(warn)/0;SANGUO_SKIP_INTEGRITY=1 唯一后门;单查隔离。

挂点:run_corpus_standalone.sh xcheck 段后两段(funnel→gate,rc 隔离不进聚合;LLM env 三件+SANGUO_PIPELINE_DB 条件传递,缺 key 且有候选→rc=1 fail loud)。读出口:corpus_reader.get_events(start,end,models)(照 get_flash 容错契约);manifest 已登记两域。

已知语义:词表层 v1 接受残余噪声(否定前缀守卫拦大头)换确定性;LLM abstain=空数组合法;pending 积压=预算停摆的显式信号(stats pending_after 可观测)。

参考(调查来源)