美股 10-K 财报文本与 SEC 公告怎么批量下载?免爬 EDGAR 的 FMP 原始文件检索与 CIK/CUSIP/ISIN 编码映射方案(SEC Filings API)

做美股基本面投研、大模型美股财报文本 RAG 问答或事件驱动量化回测时,团队迟早要直接调取美国证监会(SEC)的 10-K 年报、10-Q 季报、20-F 外国发行人年报与 8-K 重大事件公告原文,并将内部证券主表中的股票代码(Ticker)与 SEC 的 CIK 编号、彭博/13F 持仓的 CUSIP 以及跨国清算的 ISIN 编码对齐。如果直接去写爬虫抓 SEC EDGAR 官方目录,不仅要应对严格的请求频控、索引页跳转与复杂的 iXBRL 嵌套标签,还会频繁在“一企多股、一码多市场”的编码映射上踩坑。

本文基于 FMP数据源中文站 对 FMP 旗下 SecFilings(SEC 文件接口)、Search(证券搜索接口)、Directory(基础目录接口)、Company(公司资料接口) 与 Statements(财务报表接口) 五大模块的实盘采样(实盘数据快照截至 2026-11-10 14:59 UTC),梳理出一套免爬 EDGAR 的 SEC 原始文件检索与四码互查工程方案,并重点揭示三项实测排雷结论:

  1. 四码互查不能做简单的“1 对 1”字典映射:实测伯克希尔(CIK 为 0001067983)与 Alphabet(CIK 为 0001652044)在单一 CIK 下分别挂载多只不同股份类别代码,而单查英伟达 CUSIP(67066G104)会同时返回美股主板、法兰克福/德交所跨市场挂牌及 5 家伦敦/欧洲市场无关公司串码共 8 条记录;此外苹果(037833100)、微软(594918104)、伯克希尔 B(084670702)的 9 位 CUSIP 为纯数字,若路由层直接按“全数字即 CIK”分流会触发静默查空。
  2. 按股票代码拉取 SEC 申报流时,6 家样本中有 5 家高管内部交易 Form 4 占比高达 60%~92%(BRK-A 为 27%):实测 /stable/sec-filings-search/symbol 单页(100 条)中,微软、Alphabet、台积电的 Form 4 记录分别占到 76 条、74 条与 92 条,导致 Alphabet 的 2025 财年 10-K 与台积电的 20-F 年报被挤到第 3 页(需翻页扫描 300 条);同时 Alphabet 在 2026 年内于美东时间 20:29~21:56 提交的 10-K 与 10-Q 样本,因突破 SEC 当日 17:30 截点,其 filingDate 均比接收时间 acceptedDate 顺延至下一个工作日。
  3. 10-K 原生全表 JSON 可免解析直取 70~112 张披露附注表,但需防范 period 索引差异与二进制流响应头伪装:实测苹果 FY2026 的 /stable/financial-reports-json 直接返回 82 个顶层键(含 79 张主表与附注细分表),但英伟达 FY2026 的 10-K 年报在 /stable/financial-reports-dates 中并未挂载于 period=FY,而是归入 period=Q4;同时 /stable/financial-reports-xlsx 虽返回标准 ZIP/XLSX 二进制流,其 HTTP 响应头 Content-Type 却标记为 application/json,客户端须直接按二进制流落盘。

直接去 SEC EDGAR 抓取美股 10-K 年报、10-Q 季报与 8-K 公告,为什么容易卡在限流与编码映射上?

许多量化与 AI 投研团队在起步阶段会尝试直接连接 SEC 官方的 data.sec.gov 或 sec.gov/Archives/edgar/data/ 抓取美股财报文本,但在生产环境跑批时通常会撞上四道工程墙:

下表对比了自建 SEC EDGAR 抓取管线与调用 FMP SEC Filings 及配套接口的工程实现差异:

对比维度自建 SEC EDGAR 抓取方案FMP SEC Filings 与编码映射方案核心端点与字段支撑
证券编码寻址仅支持 CIK 编号;缺 CUSIP / ISIN 互查原生支持 Ticker、CIK、CUSIP、ISIN、名称互查/stable/profile、/stable/search-cik、/stable/search-cusip、/stable/search-isin
原文与附件直链需结合提交元数据或 -index.htm 拼装路径同时返回索引页 link 与目标文件直链 finalLink(10-K 直达正文,财报 8-K 常直达 EX-99.1)/stable/sec-filings-search/symbol、/stable/sec-filings-search/cik
按表单类型检索需下载全市场每日 Master Index 离线清洗支持按 formType 跨市场拉取或直调最新 8-K 流/stable/sec-filings-search/form-type、/stable/sec-filings-8k
财报事件过滤需下载 8-K 正文正则匹配 Item 2.02原生提供布尔字段 hasFinancials 标记含财报公告/stable/sec-filings-8k、/stable/sec-filings-financials
10-K 全表结构化需自研 iXBRL 解析器拆解数十张附注表一键拉取 10-K 全表 JSON 或下载原生 XLSX/stable/financial-reports-dates、/stable/financial-reports-json、/stable/financial-reports-xlsx
SIC 行业与监管归属需从提交头部文本提取 4 位 SIC 编码直接返回 4 位 sicCode、行业名称及 SEC 审查办公室/stable/sec-profile、/stable/standard-industrial-classification-list

跨数据库关联美股证券时,如何用 API 一键打通 Ticker、CIK、CUSIP 与 ISIN 四套编码互查?

在构建多源融合的金融数据库时,开发者经常遇到“如何查询 CUSIP”、“ISIN 有没有 API 可以查询”以及“如何把 13F 持仓表里的 CUSIP 或 SEC 的 CIK 编号批量映射回美股行情代码(Ticker)”等工程问题:行情系统通常用 Ticker(股票代码),SEC 财报与 13D/13G 公告用 10 位 CIK 编号(Central Index Key),13F 机构持仓与北美清算系统用 9 位 CUSIP,而全球多市场组合管理则用 12 位 ISIN(美股通常为 US + 9 位 CUSIP + 1 位校验码)。

在 FMP 的 Company(公司资料接口)、Search(证券搜索接口) 与 Directory(基础目录接口) 下,共有 8 个核心端点协同完成四码映射:

我们对苹果(AAPL)、英伟达(NVDA)、微软(MSFT)、伯克希尔 A/B 股(BRK-A / BRK-B)、Alphabet A/C 股(GOOGL / GOOG)与台积电 ADR(TSM)共 8 只代表性标的进行了四码映射与反查实测,结果汇总如下(数据快照截至 2026-11-10 14:59 UTC,对应字段为 symbol、cik、cusip、isin、exchange 与 isAdr):

股票代码发行人名称10 位 CIK 编号9 位 CUSIP 编码12 位 ISIN 编码主板与 ADR 属性反查接口实测命中数与排雷特征
AAPLApple Inc.0000320193037833100US0378331005NASDAQ / 非 ADRsearch-cik 命中 2 条(含多伦多 AAPL.TO);search-cusip 命中 4 条;search-isin 命中 5 条
NVDANVIDIA Corporation000104581067066G104US67066G1040NASDAQ / 非 ADRsearch-cusip 命中 8 条(除美股 NVDA 与德交所 NVD.F/NVD.DE 外,混入 0QOJ.L 等 5 家欧洲无关公司串码)
MSFTMicrosoft Corporation0000789019594918104US5949181045NASDAQ / 非 ADR9 位 CUSIP(594918104)为纯数字,切勿当作未补零 CIK 传给 profile-cik
BRK-ABerkshire Hathaway Inc.0001067983084670108US0846701086NYSE / 非 ADR与 BRK-B 共享同一 CIK(0001067983),但拥有独立的 CUSIP 与 ISIN
BRK-BBerkshire Hathaway Inc.0001067983084670702US0846707026NYSE / 非 ADR调 profile-cik?cik=0001067983 仅返回单条默认记录 BRK-B,需用 search-cik 拿全双股
GOOGLAlphabet Inc.000165204402079K305US02079K3059NASDAQ / 非 ADRsearch-cik?cik=0001652044 命中 4 条(GOOG、GOOGL、GOOGM、GOOGN)
GOOGAlphabet Inc.000165204402079K107US02079K1079NASDAQ / 非 ADR与 GOOGL 共享 CIK(0001652044),靠 CUSIP 末三位 107 与 305 精准区分 C 股与 A 股
TSMTaiwan Semiconductor Mfg.0001046179874039100US8740391003NYSE / ADR(true)虽为中国台湾企业,美股 ADR 仍分配 US 开头 ISIN 与 10 位 SEC CIK,年报走 20-F

在将上述接口接入生产证券主表(Security Master)时,必须重点处理以下四项实测边界:

  1. CIK 补零兼容性(Unpadded vs 10-Digit Zero-Padded):SEC 规范的 CIK 为 10 位定长前导零字符串(如苹果为 0000320193),而不少外部 CSV 表在经过 Excel 保存后会丢失前导零变成整数 320193。实测表明,FMP 的 /stable/search-cik、/stable/profile-cik、/stable/sec-filings-company-search/cik 与 /stable/sec-filings-search/cik 四个端点同时兼容不补零(cik=320193)与 10 位补零(cik=0000320193)传参,且返回报文中的 cik 字段统一标准化为 10 位前导零格式。
  2. “一企多股”陷阱:单调 profile-cik 会漏掉同发行人下的其他股份类别:CIK 标识的是法律申报主体(Entity),而 CUSIP 与 ISIN 标识的是具体证券(Issue)。如上表所示,伯克希尔 A 股(BRK-A)与 B 股(BRK-B)共用 CIK 0001067983;如果直接调用 /stable/profile-cik?cik=0001067983,接口仅返回单元素数组(默认取 BRK-B),导致 BRK-A 被静默丢弃。正确做法是先调 /stable/search-cik?cik=0001067983 获取该主体下的全部挂牌代码(返回 BRK-A 与 BRK-B 共 2 条;Alphabet 的 0001652044 则返回 GOOG、GOOGL、GOOGM、GOOGN 共 4 条),再按目标 symbol 调 /stable/profile 补齐各自的 cusip 与 isin。
  3. “一码多市场”与跨库串码清洗:调 search-cusip 与 search-isin 后必须过滤海外挂牌与错误映射:同一只美股的 CUSIP 或 ISIN 常被法兰克福(.F)、德意志交易所(.DE)、墨西哥(.MX)、维也纳(.VI)等海外市场直接沿用。例如实测 /stable/search-cusip?cusip=037833100 返回 AAPL.MX、AAPL、APC.F、APC.DE 共 4 条记录,且美股主场 AAPL 排在数组第 2 位;更典型的是查询英伟达 /stable/search-cusip?cusip=67066G104 时,返回的 8 条记录中除美股 NVDA 及德交所 NVD.F、NVD.DE 共 3 条确属英伟达外,还混入了 0QOJ.L(Peach Property Group AG)、0A0L.IL(Sectra AB)、0QDX.IL(AB Sagax)、0QN1.L(Santhera Pharmaceuticals)、0QQN.L(Bucher Industries)共 5 家伦敦/欧洲市场无关公司的错误映射记录。因此,拿到 search-cusip 或 search-isin 的返回数组后,绝不能盲取 res[0],必须优先筛选不含 . 后缀的美股原生代码,并回查 /stable/profile 校验 exchange 与目标标识是否吻合。
  4. 9 位纯数字 CUSIP 与未补零 CIK 的路由冲突:英伟达(67066G104)与 Alphabet(02079K305)的 CUSIP 含英文字母,很容易识别;但苹果(037833100)、微软(594918104)、伯克希尔 A/B(084670108 / 084670702)和台积电(874039100)的 9 位 CUSIP 全部由纯数字组成。如果自动转换函数简单写成 if token.isdigit(): call_profile_cik(token),传入伯克希尔 B 的 CUSIP(084670702)就会被误判为 CIK 0084670702 并返回空数组 []。工程上遇到长度为 9 且含数字的编码时,应优先走 /stable/search-cusip 试探,未命中时再回退至 CIK 分支。

免爬 EDGAR 索引库:如何按股票代码、CIK 或表格类型(Form Type)批量获取 SEC 原始申报链接与接收时间戳?

完成编码对齐后,即可通过 SecFilings(SEC 文件接口) 下的 5 个检索端点直接获取 SEC 原始申报元数据与文档直链:

我们以 from=2025-01-01&to=2026-11-10 窗口对 6 家代表性公司进行了实盘拉取(数据快照截至 2026-11-10 14:59 UTC;注:BRK-A 与 BRK-B 共享同一 CIK 0001067983,二者底层 SEC 申报流完全一致),下表展示了各标的在首页(page=0&limit=100)的表单分布结构,以及定位到的最新年报(10-K / 20-F)与最新当期报告(8-K / 6-K)实测时间戳(对应字段为 formType、filingDate、acceptedDate 与 finalLink):

股票代码首页 100 条中 Form 4 占比查到最新年报所需扫描页数最新年报类型与归档日期最新年报精确接收时间最新 8-K/6-K 接收时间SEC 年报主文档直链(finalLink 尾部文件名)
AAPL60 / 100(60.0%)1 页(100 条)10-K / 2026-11-032026-11-03 08:05:152026-11-09 16:30:40.../000032019326000026/aapl-20260926.htm
NVDA64 / 100(64.0%,含 1 条 4/A)1 页(100 条)10-K / 2026-02-252026-02-25 16:42:192026-09-03 08:03:56.../000104581026000021/nvda-20260125.htm
MSFT76 / 100(76.0%)1 页(100 条)10-K / 2026-07-292026-07-29 16:08:012026-11-05 06:01:52.../000119312526323660/msft-20260630.htm
BRK-A27 / 100(27.0%)1 页(100 条)10-K / 2026-03-022026-03-02 06:02:282026-11-09 06:10:14.../000119312526083899/brka-20251231.htm
GOOGL74 / 100(74.0%,300 条中占 167 条)3 页(300 条)10-K / 2026-02-052026-02-04 21:56:032026-11-05 16:10:44.../000165204426000018/goog-20251231.htm
TSM92 / 100(92.0%,300 条中占 261 条)3 页(300 条)20-F / 2026-04-162026-04-16 06:05:492026-11-10 08:41:38.../000162828026025362/tsm-20251231.htm

从上表与底层报文对账中,可以提炼出四条直接决定下载管线稳定性的核心机制:

  1. 区分 link 索引页与 finalLink 目标文件(10-K 直达主表正文,财报日 8-K 常直达 EX-99.1 业绩公报):每条申报记录均包含两个 URL 字段——link 指向 SEC 申报目录索引页(如苹果 FY2026 年报的 0000320193-26-000026-index.htm),而 finalLink 则直接指向接口选出的核心目标文件,省去每次先请求 -index.htm 索引页的二次跳转。但实测需要注意两类表单的落点差异:对于 10-K、10-Q 与 20-F,finalLink 均指向完整的财报主文档正文(如 aapl-20260926.htm);而对于财报日提交的 8-K(如苹果 2026-11-02 的 a8-kex991q4202609262026.htm、微软 2026-10-28 的 msft-ex99_1.htm、Alphabet 2026-10-28 的 googexhibit991q32026.htm),FMP 的 finalLink 会直接指向最具信息密度的 Exhibit 99.1 业绩新闻稿附件(若需 8-K 封面主表壳,可通过同条记录的 link 索引页获取)。
  2. Form 4 内部人交易挤占单页容量,单股查年报必须实现 page 自动翻页:由于 /stable/sec-filings-search/symbol 接口不支持传入 formType 参数在服务端过滤,返回结果包含了该公司的全部 SEC 表单(Form 4、Form 3、Form 144、8-K、10-Q、10-K、DEF 14A、424B2 等)。对于高管期权行权与减持频繁的科技股(如 GOOGL 首页 100 条中有 74 条 Form 4 与 9 条 Form 144;TSM 首页 100 条中有 92 条 Form 4),仅查 page=0 只能覆盖最近 1~5 个月,导致年初披露的 10-K 或 20-F 年报在首页完全不可见(GOOGL 与 TSM 均需翻到 page=2 即第 3 页才扫出年报)。若业务目标是跨公司拉取某段时间内的全部 10-K,直接调用 /stable/sec-filings-search/form-type?formType=10-K 效率更高;但需注意,若同一 CIK 下挂载了普通股、权证(Warrant)、配股权(Right)与单元(Unit)(如实测 2026-11-10 披露 10-K 的 SPAC 公司 AlphaTime Acquisition Corp,CIK 为 0001889106),该接口会为 ATMC、ATMCR、ATMCU、ATMCW 返回 4 条指向同一个 finalLink 的记录,入库前务必按 (cik, finalLink) 联合主键去重。
  3. SEC 17:30 ET 截点顺延机制:filingDate 与 acceptedDate 跨日错位及回测时间对齐边界:根据 SEC EDGAR 规则,常规 10-K、10-Q 与 8-K 若在美东时间工作日 17:30 之后提交(不同于截点为 22:00 的高管交易 Form 3/4/5),系统会将法定归档日 filingDate 顺延记作下一个工作日(例如苹果于 2026-04-20 17:29:51 提交的 8-K 卡在 17:30 前 9 秒,filingDate 仍保持 2026-04-20 当天;同类顺延亦见于 FWP 等表单,如苹果 2026-11-05 21:54:06 提交的 FWP 归档日顺延为 2026-11-06)。实测 Alphabet(GOOGL)在 2026 年内的以下三份定期报告样本均因晚于 17:30 提交而触发了跨日顺延:

在量化回测中需注意:filingDate 顺延属于法定归档日口径,而盘后核心财务数字往往已先通过业绩新闻稿(或附带 EX-99.1 的 8-K)释放;因此数据管线应同时记录 SEC 接收时间 acceptedDate、归档日 filingDate 与本地管线首次观测时间,严格按当时市场实际可得的信息时点对齐交易信号。

  1. 外国私人发行人(FPI / ADR)表单体系与 hasFinancials 精准降噪:像台积电(TSM)等在美挂牌的外国私人发行人(/stable/profile 中 isAdr: true),通常豁免提交美股常规的 10-K、10-Q 与 8-K,其年度报告主要采用 Form 20-F(如台积电于 2026-04-16 06:05:49 提交的 tsm-20251231.htm;部分加拿大发行人采用 Form 40-F,亦有少数外国发行人自愿采用 10-K),月度营收通报、法说会简报与季度财务摘要则装入 Form 6-K(台积电在 400 条记录中共有 64 份 6-K)。此外,在监控全市场实时公告时,调用 /stable/sec-filings-8k 与 /stable/sec-filings-financials 会额外返回布尔字段 hasFinancials——例如 2026-11-10 当日最新 8-K 流中,Alpha Pro Tech(APT,09:41:00)的 hasFinancials 为 true(附带财报数据),而 Allison Transmission(ALSN,09:00:39)等不含财务报表的 8-K 公告其 hasFinancials 为 false,可直接用该字段过滤掉非财报类公告。

不想自己解析 HTML 表格?如何直接拉取结构化的 10-K 年报全表数据(Form 10-K JSON / XLSX)与 SIC 行业分类?

如果投研场景不仅需要 10-K 原文链接,还希望直接把 10-K 年报里的所有财务主表与附注细分表(如按产品线拆分的营收、租赁负债到期日结构、递延税项调节表、期权激励汇总表)提取为结构化数据,无需自己写 BeautifulSoup 或 XBRL 解析器,可以直接调用 Statements(财务报表接口) 下的三件套:

  1. Financial Reports Dates(财报披露日期接口,/stable/financial-reports-dates?symbol=AAPL):查询目标公司已收录的全部结构化财报年份(fiscalYear)与周期(period)。
  2. Financial Reports Form 10-K JSON(10-K年报数据(JSON)接口,/stable/financial-reports-json?symbol=AAPL&year=2026&period=FY):将整份 10-K 年报中的所有 XBRL 披露表格一次性按章节键名以 JSON 字典返回。
  3. Financial Reports Form 10-K XLSX(10-K年报下载(XLSX)接口,/stable/financial-reports-xlsx?symbol=AAPL&year=2026&period=FY):将整份 10-K 的全部工作表打包导出为原生 Excel(.xlsx)二进制文件。

同时,配合 SecFilings(SEC 文件接口) 下的 SEC Company Full Profile(SEC 公司完整档案接口,/stable/sec-profile)、Industry Classification List(行业分类清单接口,/stable/standard-industrial-classification-list)、Industry Classification Search(行业分类检索接口,/stable/industry-classification-search)与 All Industry Classification(全行业分类数据接口,/stable/all-industry-classification),还能直接获取 SEC 官方的 4 位标准产业分类(SIC Code)与所属审查办公室。

我们对苹果(AAPL)、微软(MSFT)与英伟达(NVDA)的最新年度 10-K 结构化报表及 SIC 档案进行了实测对账,核心指标汇总如下:

股票代码SIC 编码与官方行业名称financial-reports-dates 收录期数最新年报调用参数(year / period)10-K JSON 顶层键总数(含披露表数)核心主表与附注细分表实测抽样对账(单位:百万美元)
AAPL3571 / Electronic Computers67 期(含 14 个 FY)year=2026 / period=FY82 个键(79 张表,XLSX 为 1.62 MB)主表 CONSOLIDATED STATEMENTS OF OPER:总营收 478,834(产品 355,533 + 服务 123,301),净利润 132,175,稀释 EPS 8.98;附注表 Revenue - Disaggregated Net Sal:iPhone 254,098 + Mac 37,929 + iPad 27,929 + 可穿戴与配件 35,577 + 服务 123,301 = 478,834(另有期初递延收入本期确认说明项 8,717,属总营收子集不参与加总)
MSFT7372 / Services-Prepackaged Software76 期(含 16 个 FY)year=2026 / period=FY115 个键(112 张表)含 INCOME STATEMENTS、BALANCE SHEETS、CASH FLOWS STATEMENTS、Pay vs Performance Disclosure、Cybersecurity Risk Management 等 112 张披露节点
NVDA3674 / Semiconductors & Related Devices64 期(仅 2025 及以前标 FY)year=2026 / period=Q4(传 FY 报错)92 个键(89 张表,FY2025 为 94 个键)封面表 Cover Page 明确标注 Document Type 为 10-K、Document Period End Date 为 Jan. 25, 2026、Document Fiscal Period Focus 为 FY;含 Groq、Stock-Based Compensation 等专题附注表

在实际调用这组高阶结构化接口时,有三个极具价值的工程细节需要注意:

  1. 绝不能盲目硬编码 period=FY,必须先用 financial-reports-dates 探路:实测苹果(FY2026 截至 2026-09-26)与微软(FY2026 截至 2026-06-30)在 /stable/financial-reports-dates 中同时存在 period="FY" 与 period="Q4" 两条记录,传 year=2026&period=FY 可正常拉回全量 10-K JSON;但对于英伟达(FY2026 截至 2026-01-25),如果你直接请求 /stable/financial-reports-json?symbol=NVDA&year=2026&period=FY,接口会返回无数据错误提示!回查 /stable/financial-reports-dates?symbol=NVDA 可见,英伟达 2025 财年及以前的年报归在 period="FY" 下,唯独最新的 2026 财年 10-K 年报被归档在 fiscalYear=2026 与 period="Q4" 名下(打开该 Q4 JSON 的封面表 Cover Page 可证实其 Document Type 确为 10-K 且 Document Fiscal Period Focus 为 FY)。因此,自动化脚本应先拉取 financial-reports-dates,优先匹配目标财年的 FY,若该财年无 FY 则自动回退读取 Q4。
  2. financial-reports-xlsx 的二进制流落盘防呆:实测调用 /stable/financial-reports-xlsx?symbol=AAPL&year=2026&period=FY(返回 1,618,958 字节)与 year=2025&period=FY(返回 1,399,564 字节)时,虽然 HTTP 状态码为 200 且前 8 字节魔数(Magic Number)为标准的 ZIP/XLSX 文件头 504b030414000000(即 PK\x03\x04),但服务端返回的 HTTP 响应头 Content-Type 却被标记为 application/json。在 Python 中切勿对其调用 resp.json() 或 .decode("utf-8")(会直接抛出 UnicodeDecodeError),而应直接将原始 bytes 以 "wb" 模式写入 .xlsx 文件。
  3. 444 个 SEC 标准 SIC 行业与 9 大审查办公室(Review Office)映射:实测 /stable/standard-industrial-classification-list 共返回 444 个 SEC 官方标准产业分类编码(SIC Code),并明确标注了每个行业在 SEC 公司金融部(Division of Corporation Finance)下属 9 个专业审查办公室的归属分布:其中制造业办公室(Office of Manufacturing)辖 153 个 SIC 行业,贸易与服务办公室(Office of Trade & Services)辖 106 个,生命科学办公室(Office of Life Sciences)辖 47 个,科技办公室(Office of Technology)与能源交通办公室(Office of Energy & Transportation)各辖 42 个,金融办公室(Office of Finance)辖 26 个,地产建筑办公室(Office of Real Estate & Construction)辖 24 个,国际公司金融办公室(Office of International Corp Fin)辖 3 个,结构化金融办公室(Office of Structured Finance)辖 1 个。在研究 SEC 问询函(Comment Letters)风格或按监管口径做同业可比筛选时(例如调用 /stable/industry-classification-search?sicCode=3571 一键筛出苹果 AAPL 与戴尔 DELL 等全部电子计算机硬件申报主体),SIC 体系比商业 GICS 分类更贴合 SEC 原始监管边界。

如何用 Python 构建“四码自动转换 + 8-K/10-K 最新申报实时监控”自动化管线?

下面我们将前文验证过的四项核心逻辑——① 兼容 Ticker / CIK / 纯数字 9 位 CUSIP / 12 位 ISIN 的智能四码路由与跨市场除噪(含查空防崩保护)、② 按实际申报流自动识别年报(10-K / 20-F / 40-F)与当期报告(8-K / 6-K)并翻页穿透 Form 4 噪音(最多扫 4 页 400 条)、③ 定位最新年报与当期公告的 acceptedDate 与 finalLink,以及 ④ 自动探测 financial-reports-dates 中的 FY / Q4 结构化 10-K 入口——封装为一段零外部依赖、可直接复制运行的固定窗口检索示例脚本(注:本函数面向“给定标识→单一证券”场景;若输入为挂有多只股份类别的发行人 CIK 且用于构建证券主表,请先按第 2 节方法调用 search-cik 枚举全部股类;若仅查发行人公告则可直接调 sec-filings-search/cik)。

运行前请先在终端设置环境变量 export FMP_API_KEY="你的密钥"(Windows PowerShell 使用 $env:FMP_API_KEY="你的密钥"):

import json, os, urllib.request
BASE_URL, API_KEY = "https://quote-fmp.com/stable", os.environ["FMP_API_KEY"]

def fmp_get(path, params):
    q = "&".join(f"{k}={v}" for k, v in {**params, "apikey": API_KEY}.items())
    req = urllib.request.Request(f"{BASE_URL}/{path}?{q}", headers={"User-Agent": "Mozilla/5.0"})
    with urllib.request.urlopen(req, timeout=20) as resp:
        return json.loads(resp.read().decode("utf-8"))

def resolve_security_id(raw_id):
    token = raw_id.strip().upper()
    if len(token) == 12 and token[:2].isalpha():
        hits = fmp_get("search-isin", {"isin": token})
        us_sym = next((h["symbol"] for h in hits if "." not in h["symbol"]), hits[0]["symbol"]) if hits else None
        prof = fmp_get("profile", {"symbol": us_sym}) if us_sym else []
    elif len(token) == 9 and any(c.isdigit() for c in token):
        hits = fmp_get("search-cusip", {"cusip": token})
        us_sym = next((h["symbol"] for h in hits if "." not in h["symbol"]), hits[0]["symbol"]) if hits else None
        prof = fmp_get("profile", {"symbol": us_sym}) if us_sym else fmp_get("profile-cik", {"cik": token.zfill(10)})
    else:
        prof = fmp_get("profile-cik", {"cik": token.zfill(10)}) if token.isdigit() else fmp_get("profile", {"symbol": token})
    if not isinstance(prof, list) or not prof: return {"input_id": raw_id, "error": "NOT_FOUND"}
    p, sec_p = prof[0], fmp_get("sec-profile", {"symbol": prof[0]["symbol"]})
    sp = sec_p[0] if isinstance(sec_p, list) and sec_p else {}
    return {"input_id": raw_id, "symbol": p["symbol"], "cik": p["cik"], "cusip": p["cusip"], "isin": p["isin"],
            "exchange": p["exchange"], "isAdr": p["isAdr"], "sicCode": sp.get("sicCode"), "sicDescription": sp.get("sicDescription")}

def audit_company_filings(raw_id, from_date="2025-01-01", to_date="2026-11-10"):
    meta = resolve_security_id(raw_id)
    if "error" in meta: return meta
    sym, ann_set, cur_set = meta["symbol"], {"10-K", "20-F", "40-F"}, {"8-K", "6-K"}
    ann, cur, pages, scanned, f4_cnt = None, None, 0, 0, 0
    for page in range(4):
        rows = fmp_get("sec-filings-search/symbol", {"symbol": sym, "from": from_date, "to": to_date, "page": page, "limit": 100})
        if not rows: break
        pages, scanned, f4_cnt = pages + 1, scanned + len(rows), f4_cnt + sum(1 for r in rows if r.get("formType") in ("4", "4/A"))
        ann = ann or next((r for r in rows if r.get("formType") in ann_set), None)
        cur = cur or next((r for r in rows if r.get("formType") in cur_set), None)
        if ann and cur: break
    dates = fmp_get("financial-reports-dates", {"symbol": sym}) or []
    fy_set = {d["fiscalYear"] for d in dates if d.get("period") == "FY"}
    rep = next((d for d in dates if d.get("period") == "FY" or (d.get("period") == "Q4" and d.get("fiscalYear") not in fy_set)), None)
    return {**meta, "scanned_pages": pages, "total_scanned": scanned, "form4_Count": f4_cnt,
            "latest_annual_form": ann["formType"] if ann else None, "annual_filingDate": ann["filingDate"][:10] if ann else None,
            "annual_acceptedDate": ann["acceptedDate"] if ann else None, "annual_finalLink": ann["finalLink"] if ann else None,
            "latest_current_form": cur["formType"] if cur else None, "current_filingDate": cur["filingDate"][:10] if cur else None,
            "current_acceptedDate": cur["acceptedDate"] if cur else None, "structured_10k_entry": f"{rep['fiscalYear']}-{rep['period']}" if rep else None}
for uid in ["AAPL", "1045810", "MSFT", "084670702", "US02079K3059", "US8740391003"]:
    print(json.dumps(audit_company_filings(uid), ensure_ascii=False))

向上述管线同时传入股票代码(AAPL、MSFT)、未补零 CIK(1045810,对应 NVDA)、9 位纯数字 CUSIP(084670702,对应 BRK-B)以及 12 位 ISIN(US02079K3059 对应 GOOGL、US8740391003 对应台积电 TSM),实盘运行输出的 6 条 JSON 结果如下(日常巡检时可将 to_date 设为运行当日;若出现 latest_annual_form: null 且 scanned_pages == 4,代表前 400 条申报已被 Form 4 等高频表单占满、扫描尚未触达年报披露日,可继续增大分页上限或改调 sec-filings-search/form-type):

{"input_id": "AAPL", "symbol": "AAPL", "cik": "0000320193", "cusip": "037833100", "isin": "US0378331005", "exchange": "NASDAQ", "isAdr": false, "sicCode": "3571", "sicDescription": "Electronic Computers", "scanned_pages": 1, "total_scanned": 100, "form4_Count": 60, "latest_annual_form": "10-K", "annual_filingDate": "2026-11-03", "annual_acceptedDate": "2026-11-03 08:05:15", "annual_finalLink": "https://www.sec.gov/Archives/edgar/data/320193/000032019326000026/aapl-20260926.htm", "latest_current_form": "8-K", "current_filingDate": "2026-11-09", "current_acceptedDate": "2026-11-09 16:30:40", "structured_10k_entry": "2026-FY"}
{"input_id": "1045810", "symbol": "NVDA", "cik": "0001045810", "cusip": "67066G104", "isin": "US67066G1040", "exchange": "NASDAQ", "isAdr": false, "sicCode": "3674", "sicDescription": "Semiconductors & Related Devices", "scanned_pages": 1, "total_scanned": 100, "form4_Count": 64, "latest_annual_form": "10-K", "annual_filingDate": "2026-02-25", "annual_acceptedDate": "2026-02-25 16:42:19", "annual_finalLink": "https://www.sec.gov/Archives/edgar/data/1045810/000104581026000021/nvda-20260125.htm", "latest_current_form": "8-K", "current_filingDate": "2026-09-03", "current_acceptedDate": "2026-09-03 08:03:56", "structured_10k_entry": "2026-Q4"}
{"input_id": "MSFT", "symbol": "MSFT", "cik": "0000789019", "cusip": "594918104", "isin": "US5949181045", "exchange": "NASDAQ", "isAdr": false, "sicCode": "7372", "sicDescription": "Services-Prepackaged Software", "scanned_pages": 1, "total_scanned": 100, "form4_Count": 76, "latest_annual_form": "10-K", "annual_filingDate": "2026-07-29", "annual_acceptedDate": "2026-07-29 16:08:01", "annual_finalLink": "https://www.sec.gov/Archives/edgar/data/789019/000119312526323660/msft-20260630.htm", "latest_current_form": "8-K", "current_filingDate": "2026-11-05", "current_acceptedDate": "2026-11-05 06:01:52", "structured_10k_entry": "2026-FY"}
{"input_id": "084670702", "symbol": "BRK-B", "cik": "0001067983", "cusip": "084670702", "isin": "US0846707026", "exchange": "NYSE", "isAdr": false, "sicCode": "6331", "sicDescription": "Fire, Marine & Casualty Insurance", "scanned_pages": 1, "total_scanned": 100, "form4_Count": 27, "latest_annual_form": "10-K", "annual_filingDate": "2026-03-02", "annual_acceptedDate": "2026-03-02 06:02:28", "annual_finalLink": "https://www.sec.gov/Archives/edgar/data/1067983/000119312526083899/brka-20251231.htm", "latest_current_form": "8-K", "current_filingDate": "2026-11-09", "current_acceptedDate": "2026-11-09 06:10:14", "structured_10k_entry": "2025-FY"}
{"input_id": "US02079K3059", "symbol": "GOOGL", "cik": "0001652044", "cusip": "02079K305", "isin": "US02079K3059", "exchange": "NASDAQ", "isAdr": false, "sicCode": "7370", "sicDescription": "Services-Computer Programming, Data Processing, Etc.", "scanned_pages": 3, "total_scanned": 300, "form4_Count": 167, "latest_annual_form": "10-K", "annual_filingDate": "2026-02-05", "annual_acceptedDate": "2026-02-04 21:56:03", "annual_finalLink": "https://www.sec.gov/Archives/edgar/data/1652044/000165204426000018/goog-20251231.htm", "latest_current_form": "8-K", "current_filingDate": "2026-11-05", "current_acceptedDate": "2026-11-05 16:10:44", "structured_10k_entry": "2025-FY"}
{"input_id": "US8740391003", "symbol": "TSM", "cik": "0001046179", "cusip": "874039100", "isin": "US8740391003", "exchange": "NYSE", "isAdr": true, "sicCode": "3674", "sicDescription": "Semiconductors & Related Devices", "scanned_pages": 3, "total_scanned": 300, "form4_Count": 261, "latest_annual_form": "20-F", "annual_filingDate": "2026-04-16", "annual_acceptedDate": "2026-04-16 06:05:49", "annual_finalLink": "https://www.sec.gov/Archives/edgar/data/1046179/000162828026025362/tsm-20251231.htm", "latest_current_form": "6-K", "current_filingDate": "2026-11-10", "current_acceptedDate": "2026-11-10 08:41:38", "structured_10k_entry": "2025-FY"}

如果希望在本地或云服务器立即复现上述四码对齐与 SEC 10-K/8-K 监控流水线,可前往 快速接入指南 免费申领 Ultimate 全接口试用密钥,或查阅 定价与会员套餐 了解国内直连与微信支付方案。


常见问题(FAQ):使用 SEC 申报文件与证券编码映射接口时最容易踩哪些坑?

Q1:为什么用 /stable/sec-filings-company-search/name 按公司名模糊搜索(如 company=Berkshire)会返回上百条 symbol 为 "None" 的记录?

因为 SEC Filings By Name(按名称查 SEC 申报接口,/stable/sec-filings-company-search/name)检索的是 SEC EDGAR 全量注册申报实体库,不仅包含二级市场上市公司,还包含大量需要在 SEC 备案 Form D 或 13F 的私募股权基金、有限合伙(LP)与资产管理机构。例如实测传入 company=Berkshire 共返回 104 个 SEC 申报主体,排在前面的 BERKSHIRE MULTIFAMILY VALUE FUND II LP(CIK 为 0001418405)与 BERKSHIRE PARTNERS(CIK 为 0001461632)均为非上市私募主体,其返回对象中的 symbol 字段为字符串字面量 "None"(注意不是 JSON 的 null)。如果只需要检索二级市场挂牌股票,建议优先使用 Company Name Search(公司名称检索接口,/stable/search-name),或在遍历结果时显式过滤 row.get("symbol") not in (None, "", "None")。

Q2:10-K 全表 JSON 接口(/stable/financial-reports-json)与标准化三大报表(/stable/income-statement 等)以及原始口径三大报表(As Reported)有什么区别?

三者服务于完全不同的投研颗粒度:

登录后可领取FMP Ultimate档15天试用 Key,覆盖全量接口。免费试用 15 天 →