docs(data): 基本面语料库NAS采集设计spec§18+三摸底实测报告 [nas]——用户拍板六项范围(除公告PDF全量):新闻标题+摘要级/全文级/历史回补+公告元数据回补2000起/每日增量/定期业绩类PDF;硬约束=存储采集全NAS不上VPS(家宽IP与VPS东财限流零冲突)+采集限于00:30-17:30+慢爬;设计=1脚本corpus_download.py+1调度入口sanguo-corpus-daily 06:00(daily+backfill两lane串行,--until 17:30墙钟自停);数据模型=id键控(dt=发现日分区,无today文件名语义,天然免疫0902/0904式错标)+append-only短窗去重;回补顺序=公告meta→新闻meta→新闻全文→PDF(新→旧,容量闸门:/volume1实测645G空闲,每50GB自查,<200G暂停升级);失败语义吸收09-01/09-05教训(确定性错跳过不烧重试不连坐);探测优先能拿多深拿多深+depth_summary记录;附三摸底报告(聚宽136字段原料层≈100%已有/巨潮2000年起130万条年/东财3年硬顶/存储大头PDF 520G年) [nas]
CI/CD / test (push) Successful in 23s
CI/CD / nas-deploy (push) Successful in 0s
CI/CD / nas-verify (push) Successful in 8s

This commit is contained in:
2026-09-06 13:49:46 +08:00
parent 90b37ce27f
commit 92e63ee27c
2 changed files with 224 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
# 基本面+语料库联合调研·数据 session 三摸底报告(2026-09-06
> 应 factor session 需求:纯调查,未实施任何东西、未建任何表、未跑生产。所有数字为当日实测或由实测推导(推导过程标注)。
> 探测方式:Mac 直连(不走代理),单线程,共 ~35 发只读请求,未触发任何限流。
---
## ① 聚宽 finance 136 字段 vs 我们现有数据 —— 结论:**原料层我们≈100% 覆盖,缺口在「加工」不在「原料」**
**前提修正:基本面原料不是真空。** VPS 实测 parquet600519C:\sanguo_vnpy_v2\data\static\):
| 我们的表 | 实测列数 | 内容 | 期数 |
|---|---|---|---|
| balance(东财 datacenter | **319 列** | 全科目资产负债表 + ~150 科目自带同比(_YOY) + NOTICE_DATE + 审计意见 | 103 期(2000 至今回溯) |
| income | **203 列** | 全利润表:营收/三费/研发费用(RESEARCH_EXPENSE)/扣非(DEDUCT_PARENT_NETPROFIT)/持续+终止经营净利润/信用+资产减值 + 同比 | 103 期 |
| cashflow | **254 列** | 全现金流量表 **+ 间接法补充资料段**NETPROFIT/折旧摊销/INVENTORY_REDUCE/OPERATE_RECE_REDUCE/递延税…)| 99 期 |
| valuation(日频) | 13 列 | 收盘价/涨跌幅/**总市值/流通市值/总股本/流通股本/PE(TTM)/PE(静)/市净率/PEG/市现率/市销率** | 2106 行 ≈ 8.5 年日频 |
| financial_abstract | 105 列 | 财务摘要(宽表:指标×99 个报告期,回溯到 1998) | 99 期 |
| 另有 | forecast/express | 业绩预告/业绩快报(ak-quarter 已采集,同东财源) | — |
**对照聚宽**[JQData 官方文档](https://www.joinquant.com/help/api/doc?name=JQDatadoc&id=10547)、[数据字典](https://www.joinquant.com/data/dict)、[jqdatasdk](https://github.com/JoinQuant/jqdatasdk);官方字典需登录,字段数取公开资料口径,±10% 不确定):
| 聚宽表 | 字段数(约) | 我们覆盖 |
|---|---|---|
| STK_BALANCE_SHEET 资产负债表 | ~161 | ✅ 319 列超集(科目更细+免费同比) |
| STK_INCOME_STATEMENT 利润表 | ~70-90 | ✅ 203 列超集(扣非/研发/减值分列) |
| STK_CASH_FLOW_STATEMENT 现金流量表 | ~90-97 | ✅ 254 列超集(**含间接法补充资料=应计项原料,聚宽反而没全给**) |
| valuation 估值表(get_fundamentals | 12 | ✅ 13 列全对齐且多 PEG,日频 8.5 年 |
| indicator 财务指标预计算表 | ~25 | ⚠️ **唯一真缺口**ROE/ROA/毛利率/EPS/BPS/增速/负债率…——全部可从三报表推导;xtdata PershareIndex 现成有 ROE/毛利率/EPS 一层 |
| STK_PERFORMANCE_LETTERS 业绩快报 | 17 | ✅ express 同源已有 |
**点名你举的三个例子**ROE 趋势(income.PARENT_NETPROFIT + balance.TOTAL_PARENT_EQUITYNOTICE_DATE 列在前视偏差修正中已治理)✅;盈利质量(NETCASH_OPERATE/PARENT_NETPROFIT)✅;应计项(cashflow 补充资料段整段在)✅ —— **全部已有原料,缺的只是因子加工代码**
聚宽两个真劣势:单季度口径(我们 REPORT_DATE 累计值差分即得,一行 pandas);分析师一致预期(聚宽也要另加钱,不在 finance 库)。另外聚宽 2026-08-01 起禁非大陆 IP + 本身是付费订阅(年费千元级)——**买聚宽=买加工层,原料不值得买**。
---
## ② 巨潮 cninfo 公告 API —— 结论:**可回补到 2000 年附近(90 年代稀疏),全量翻页无硬顶,字段含摘要+类别+PDF,落地成本极低(akshare 已封装)**
实测(hisAnnouncement/query,平安银行):
| 探测 | 结果 |
|---|---|
| 1991 年 | 0 条 |
| 1993 年 | **3 条**(「深圳发展银行93年配股重要提示」——真能翻到 90 年代) |
| 1996/1999 年 | 0 条(早年数字化稀疏,不全) |
| 2003 年 | 27 条 |
| 2008 年 | 92 条(totalAnnouncement 全年计数) |
| 2015 年 | 满 30/页 hasMore(现代全量) |
| **深度结论** | **≈2000 年起渐密,2010 后全;再早只有零星** |
| pageSize | 服务端封顶 30/页(传 500 实返 30 |
| 翻页上限 | pageNum=500 仍返数据无封顶;akshare 的 stock_zh_a_disclosure_report_cninfo 就是 totalAnnouncement/30 全量翻页在用 |
| 配额 | 本次 ~25 发零限流,无官方配额文档;建议按慢爬纪律(防封约束) |
| **返回字段(23 个)** | secCode/secName/orgId/orgName/**announcementTitle**/**announcementContent(摘要文本!)**/announcementTime(epoch ms)/**announcementType+TypeName(类别)**/**adjunctUrl(PDF 路径)/adjunctSize(PDF 字节数!)/adjunctType**/important(重要性标记)/shortTitle/associateAnnouncement(关联公告)/columnId/batchNum… |
| **category 过滤** | ✅ 可用:年报类深市 2025=11,187 条(≈2800 家×4 份定期报告,自洽);支持 年报/半年报/一季报/三季报/业绩预告/权益分派 等中文类别 |
| PDF 正文 | adjunctUrl → static.cninfo.com.cn/finalpage/…PDF,直接可下 |
**全市场年公告量(存储估算关键数)**:深市 2025 `totalAnnouncement=718,628`(沪市查询返回同值疑似 column 参数未生效,判为深市口径);按沪市 ~2300 家推算 **全 A ≈ 130 万条/年**。单股现代口径 ~100-300 条/年(平安银行 2008=92)。
---
## ③ 东财/新浪新闻 —— 结论:**东财 np-listapi 单股可回补 ~3 年(1-2 万条硬顶),前向增量无限;新浪免费线不可依赖**
**东财 np-listapi(个股 F10 新闻列表,与 akshare stock_news_em 的 search-api 是两个接口)**
| 探测 | 结果 |
|---|---|
| 字段(7 个) | Art_ShowTime/Art_Title/Art_Url/Art_OriginUrl/Art_Code/Np_dst/Art_SortStart —— **无摘要字段** |
| 单股日条数实测 | 茅台 5-9 条/日;宁德 7-40 条/日(峰值40);冷门(镇洋发展) 0-4 条/日;中游(东鹏) 2-8 条/日 |
| 翻页深度 | pageSize=100pageIndex=100(第 1 万条)→ 2023-09**pageIndex=200 → 空=到头** |
| **深度结论** | **单股历史上限 ≈1-2 万条;最热股≈3 年,冷门股库存小不受限**。回补天花板 3 年,前向增量无限制 |
| 平均标题 | 71 Butf-8100 条实测均值) |
| 摘要来源 | np-listapi 无 content;摘要级需 search-apiakshare stock_news_em 已封装,**仅最近 100 条**→适合每日增量不适合回补)或逐条抓正文页 |
| 单篇全文实测 | HTML 69KB**提取正文 ≈4.1KB4150 字符)** |
| 内容形态 | Np_dst=CMS=东财资讯流,多为提及该股的市场稿/资金流稿,非公司特定新闻——做舆情因子够用,做「公司事件」要靠公告层 |
**新浪**search.sina.com.cn 搜索 4 页探测全返空(疑风控/需 cookie);老个股新闻页 vip.stock.finance.sina 结构已变。**判:新浪免费新闻线不可依赖,东财单源即可**(与「优先新浪源」纪律的例外说明:新闻类新浪无可用接口,实测为据)。
---
## ④ 长期语料库存储规模估算(用户核心关切)
基准:全 A ~5400 只;新闻日总量按实测分布推导:超热50只×15 + 热200只×8 + 中1500只×3 + 冷3650只×1 ≈ **1.05 万条/交易日 ≈ 260 万条/年**(250 交易日)。公告按全 A 130 万条/年(②实测推算)。
| 层 | 档 | 单条 | 年增量 | **1 年** | **3 年** | **5 年** |
|---|---|---|---|---|---|---|
| 新闻 | 标题级 | ~0.2KB | 0.5GB | **0.5GB** | 1.5GB | 2.5GB |
| 新闻 | 标题+摘要 | ~0.5KB | 1.3GB | **1.3GB** | 4GB | 6.5GB |
| 新闻 | **全文级** | ~4.1KB | 10.6GB | **10.6GB** | 32GB | 53GB |
| 公告 | 元数据(标题+摘要+23字段) | ~1KB | 1.3GB | **1.3GB** | 4GB | 6.5GB |
| 公告 | PDF 全量 | ~400KB均值 | **~520GB** | **520GB** | 1.6TB | 2.6TB |
| 公告 | PDF 只存定期+业绩类 | ~1MB | ~45GB | **45GB** | 135GB | 225GB |
**给用户权衡的三句话**
1. **标题/摘要/元数据级全都不是事**——三层全建 5 年 <20GB,比 dbbardata 26G 还小,量级顾虑可以直接打消。
2. **大头只有公告 PDF 全量(520GB/年、5 年 2.6TB**——但这层几乎肯定不需要全存:元数据全量 + PDF 只存定期报告/业绩预告类(45GB/年),就是事件因子可回测的完整底座。
3. **真正的约束不是存储是抓取吞吐与年限**:新闻全文 1 万 HTTP/日;公告 PDF 全量 ≈3600 份/日 下载+520GB/年 流量;新闻历史**只能回补 3 年**(接口硬顶),公告可回补到 ~2000 年——想攒 5 年新闻语料必须**现在开始攒**,公告可以慢慢回补。
**建议的最小可行组合**(供 factor session 拼进决策包,非本 session 实施):新闻标题+摘要级(增量从现在攒,0.5-1GB/年)+ 公告元数据全量回补 2000 起(~15GB 累计)+ 定期类 PDF45GB/年)。总盘子 5 年 <300GBVPS 可承载。
---
**Sources**: [JQData 使用说明(财务数据)](https://www.joinquant.com/help/api/doc?name=JQDatadoc&id=10547) · [聚宽数据字典](https://www.joinquant.com/data/dict) · [jqdatasdk GitHub](https://github.com/JoinQuant/jqdatasdk) · [akshare stock_disclosure_cninfo 源码(本地)](venv310/lib/python3.10/site-packages/akshare/stock_feature/stock_disclosure_cninfo.py) · cninfo/np-listapi/新浪 均为本日直连实测(探测脚本 /tmp/probe_corpus_sources.py、/tmp/probe_round2.py,未跑生产)。
@@ -403,6 +403,127 @@ FETCHERS 注册表新增两键即自动可被未来 provider MCP server 暴露
- **VPS 部署终态**: 使用层 3 commit(4966d30/7f01c5f/564160d)推 VPS(run#1043,tag=564160d,
gap=0),VPS 端 8/8 功能验证过(双层接口/区间滤日/回补数据可读/白名单拒绝/实盘方法面)。
## 18. 增补 2026-09-06:基本面语料库(新闻+公告)采集设计——NAS 域(本节为最新,覆盖前文相关决策)
> 用户拍板(2026-09-06,经 factor session 转达):范围=六项全做(新闻标题+摘要级增量/新闻全文级/
> 新闻历史回补/公告元数据全量回补 2000 起/公告每日增量/定期+业绩类 PDF),**唯一不做=公告 PDF 全量
> (520GB/年)**。前置调研=`docs/fundamental_corpus_probes_20260906.md`(三摸底实测)。
> 本节为 spec,验收通过后才实施;spec 阶段零建表零采集。
### 18.1 硬约束(用户原话级)
1. **存储全部落 NAS、一律不上 VPS**——「vps承载有压力,之前基本面都放在了nas上,没有放vps,本次
也一样」。VPS 零参与:零 schtask、零存储、零采集进程;repo 里进脚本仅为随 NAS 部署管道分发
(promote --target nas → /app)VPS 侧永远不会被调度。
2. **采集发起位置=NAS 本机**(sanguo_vnpy_v2 容器内 docker exec)。关键差异:家宽出口 IP ≠ VPS
公网 IP(49.232.102.198),与 VPS 侧 ak-daily/ak-events 的东财限流**零冲突**——这正是采集放
NAS 的第二个理由(第一个是存储)。09-06 实测佐证:np-listapi/巨潮/东财文章页 ~35 发连续探测
自家宽 IP 全成功、零限流。
3. **时间带**:全部采集限于 **00:3017:30**,避开 18:0523:45 傍晚带(VPS 夜任务密集+家宽使用)。
唯一日窗=每日 06:00 起(见 18.3)。
4. 慢爬纪律:单进程单线程、per-domain 限速+抖动、直连不走代理(Session.trust_env=False,防
Mac 系统代理同款坑)。新浪线已判不可依赖(09-06 实测空返),本设计不使用。
### 18.2 数据模型(NAS 落位:/volume1/stock/corpus/,与 A股数据/ 平级)
```
/volume1/stock/corpus/
news_meta/dt=YYYY-MM-DD/part-0.parquet # 东财个股新闻·标题+摘要级(仅新条目,append-only)
news_fulltext/dt=YYYY-MM-DD/part-0.parquet# 东财新闻正文(按 art_code 全局去重,4.1KB/条)
ann_meta/dt=YYYY-MM-DD/part-0.parquet # 巨潮公告元数据(仅新条目;回补的也落发现日分区)
ann_pdf/YYYY/<announcementId>.pdf # 定期+业绩类 PDF(文件名=唯一id,天然幂等)
state/ # 断点水位+unit marker(JSON/parquet)
logs/corpus_YYYYMMDD_HHMMSS.log
```
Schema(列名冻结,消费方=factor session 因子加工层,后续 provider fetcher 可包):
- **news_meta**: `art_code`(pk), `stock_code`(6位), `show_time`, `title`, `summary`(可 null:
np-listapi 回补段无摘要——search-api 只有最近100条,历史摘要物理不存在), `media_name`(同上可
null), `url`, `first_seen_date`
- **news_fulltext**: `art_code`(pk,跨股票全局一条——同一篇稿提及多股只在 meta 层多行),
`url`, `show_time`, `content_text`(去标签正文), `fetch_date`
- **ann_meta**: `announcement_id`(pk), `sec_code`, `sec_name`, `org_id`, `title`, `short_title`,
`content`(摘要原文), `ann_time`(epoch ms→ts), `ann_type`, `ann_type_name`, `column_id`,
`important`, `adjunct_url`, `adjunct_size`, `batch_num`, `first_seen_date`
- **ann_pdf 索引**(state/ann_pdf_index.parquet): `announcement_id`, `sec_code`, `ann_type_name`,
`report_year`(从报告类别+公告年推), `local_path`, `bytes`, `fetch_date`
设计要点:**id 键控、无「$today 文件名」语义**——条目自带时间戳(show_time/ann_time),分区键是
发现日而非业务日,盘前跑/隔夜跑都无 0902/0904 式错标风险(与 A 档快照族的root差异)append-only
不重写(仅新条目入区,短窗 id 去重=读近 N 日分区),无 merge 改写类事故面。
### 18.3 采集设计:**1 个脚本 + 1 个调度入口**(脚本整合原则,用户追加指令②)
- **脚本**: `scripts/data_platform/corpus_download.py`(repo 内唯一新文件;单脚本红线同款——
corpus 栈一个入口,类型靠内部注册表,禁再开新脚本)。参数 `--lane daily|backfill`
`--until HH:MM`(墙钟自停)、`--limit N`(手动冒烟)。
- **调度**: DSM 任务计划 **sanguo-corpus-daily,每日 06:00 一条**:
`docker exec sanguo_vnpy_v2 python -X utf8 /app/scripts/data_platform/corpus_download.py
--lane daily && docker exec … --lane backfill --until 17:30`
(两 lane 串行同进程域=天然互斥;rc 聚合,任一 lane 失败 log 留痕)。回补 lane 每日从断点续跑,
17:30 前完成当前 unit 即 checkpoint 退出。
**daily lane(每日,总 ~4.5h,06:0010:30 前后)**:
1. 公告增量(巨潮,~5400 req @1/s≈1.5h):每股 seDate=T-1~T 两天窗+`announcement_id` 短窗去重
(同 margin_sse 两天窗自愈模式,漏一天次日自动补上);
2. 新闻增量(东财 search-api=akshare stock_news_em 同款端点,~5400 req @1/s≈1.5h):带摘要,
每股最近100条,新 art_code 入 news_meta;
3. 新闻全文(东财文章页,@2/s,~1万 req≈1.5h):仅下载昨日新发现的 art_code 正文;
4. 当日 PDF(定期+业绩类 category 过滤,数量级 ~100-400 份/日,峰值在 4 月年报季)。
**backfill lane(每日 10:3017:30 剩余时间,断点续跑,顺序=因子价值优先)**:
① ann_meta 全量回补(2000→今,unit=(stock,year),~19 万 req,预计 36 天跑完);
② news_meta 回补(np-listapi 标题级,unit=(stock,page),翻到空页或 page≥200 止,~11 万 req,
24 天)——历史段 summary=null 是物理上限(search-api 只有最近100条),spec 如实约定;
③ news_fulltext 回补(①②清单里的 url,@2/s,~1000万 req≈12 个月慢车道);
④ 定期+业绩类 PDF 回补(年份**新→旧**,2026→2000,~34 万份/~300GB,慢车道数周–数月)。
**容量闸门**: /volume1 实测空闲 645G(2026-09-06);PDF 回补每落 50GB 自查 `df`,空闲<200G 即
暂停 PDF 段并 log 告警升级用户重拍(其余段不受影响——非 PDF 段总盘子 <60G)。
**失败语义(吸收 09-01/09-05 教训)**: fetch 失败→unit 不标 done 不写半截(parquet tmp+rename);
真空(该股该年 0 公告)→标 done 合法;确定性解析错→记日志跳过该 unit **绝不烧重试、绝不连坐后续
unit**(northbound 断路器饿死教训);域名级连续传输错(403/429/超时×10)→该域本日冷却、它域继续、
rc=1 留痕,次日自然重试。
**探测优先(用户追加指令①)**: 深度不预设上限——巨潮按年翻到空、东财按页翻到空/PAGE 硬顶为止,
PDF 按可得性实下(404 标 missing 不重试);每源每股记录 first_date 入 state/depth_summary.json,
实施期边探边记,实际深度以落盘数据为准(三摸底测得:巨潮≈2000 起渐密/1993 有零星,东财≈最热股 3 年)。
### 18.4 预算汇总(实测口径)
| 层 | 增量/年 | 回补累计 | 请求量级 |
|---|---|---|---|
| news_meta(标题+摘要) | ~1.3GB | +3 年标题级 ~1.5GB | 日 ~5400;回补 ~11 万 |
| news_fulltext | ~10.6GB | 3 年 ~32GB | 日 ~1 万;回补 ~1000 万(慢) |
| ann_meta | ~1.3GB | 2000 起 ~15GB | 日 ~5400;回补 ~19 万 |
| ann_pdf(定期+业绩) | ~45GB | ~300GB(**带容量闸门**) | 日 ~100-400;回补 ~34 万 |
| **非 PDF 合计** | **~13GB/年** | **<60GB** | — |
### 18.5 验收标准(实施完成的定义)
1. **daily lane**: T+1 晨抽查 5 股(超热/热/中/冷/ST)——show_time/ann_time∈[T-1,T] 的条目
全在且 id 无重复;日志限速合规(平均间隔≥设定值,零 429/403 连击)。
2. **ann_meta 回补**: 600519 年报 2001 起逐年可查;announcement_id 全局无重;year×count 曲线
单调合理(早年稀疏→近年 ~130 万/年)。
3. **news 回补**: 600519 最早条目落 2023-09±1 月(实测硬顶对齐);depth_summary.json 全量产出。
4. **PDF**: 抽 20 份跨年份可打开(%PDF 魔数+size>0+meta 可反查路径);索引行数=文件数。
5. **边界**: /volume1/stock/corpus 之外零写入;VPS 零改动(git diff 触及面仅 scripts+tests+docs);
容量闸门演练一次(临时阈值)证明会停。
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 连通金丝雀(容器内 1 发/域+目录骨架)→ T2 corpus_download.py daily lane 四段+state 机制
+测试 → T3 DSM 任务注册+首周人工盯跑 → T4 backfill lane ①② → T5 ③④+容量闸门 → T6 验收
清单执行+活文档本节补「实施终态」小节。每步一个 commit,标签 **[nas]**(VPS 零触及)。
## 参考(调查来源)
- xtdata 官方:https://dict.thinktrader.net/nativeApi/xtdata.html