关于 EDGAR 13F point-in-time
EDGAR 13F point-in-time 是用于查询指定日期已知机构持仓的 MCP 服务。它按申报可见日期和修订规则处理数据,适用于历史研究和回测。
主要功能
- 01将管理人名称解析为 CIK 候选
- 02列出指定日期前可见的申报
- 03查询截至指定日期的季度持仓
- 04比较两个时期的持仓
- 05筛选并限制返回的持仓
适用场景
- 01还原历史日期时已知的持仓
- 02避免投资回测纳入未来申报
- 03检查 13F 修订及其来源引用
- 04比较管理人不同季度的持仓
MCP 相关
该服务通过 stdio 与 MCP 客户端通信,提供管理人查询、申报列表、时点持仓和时期比较工具。每次查询都使用 as_of 日期,排除之后提交的申报。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx edgar13f-mcpSEC_USER_AGENTUser-Agent sent to sec.gov, e.g. 'Your Name [email protected]' (SEC fair access).EDGAR13F_AGENT_MODE'on' caps unnarrowed holdings/diff answers at 50 positions (auto_limited: true).EDGAR13F_CACHE_DIROn-disk cache directory (default: $XDG_CACHE_HOME/edgar13f or ~/.cache/edgar13f).本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
4收录的工具列表 · 更新于 1 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | |
| as_of | string | 否 | ISO-8601 知识截止日期:答案仅使用截至该日期已在 EDGAR 公开提交的信息。 |
| limit | integer | 否 |
详细介绍
edgar13f-mcp
一个 MCP 服务,用于回答有关 SEC Form 13F 持仓的问题,并还原某个日期当时可能已知的信息。它附带一套在服务编写之前就已冻结的评估。
功能与时点信息为何重要
持有价值 1 亿美元或以上 13F 证券的美国机构管理人每季度都要提交 Form 13F,最迟可在季度结束后 45 天提交。其中许多管理人之后会修订报告。重述修订会替换整份报告。新增持仓修订则会在报告中添加行。因此,“管理人 X 在 2024-12-31 持有哪些证券?”这个问题,在不同日期会有不同的正确答案:申报日期之前没有信息,之后是原始报告,再之后则是修订后的报告。
始终返回最新版本的工具,会把未来信息泄露到回测、研究笔记和 Agent 答案中。此服务的每次调用都要求提供 as_of 日期,并遵循两条规则(完整内容见 contracts/CONTRACTS.md):
- 可见性(§3): 只有 EDGAR 申报日期不晚于
as_of的申报文件,在as_of日期才可见。之后提交的内容不会影响答案:无论是行、引用、申报文件列表,还是哪份申报文件被视为“最新”。 - 修订(§4): 按顺序排列该期间内可见的申报文件。基础报告是最后一份原始报告或重述报告。之后的每份新增持仓修订都会合并到基础报告中。每行都会注明其来源申报文件。
安装与运行
使用 Python 3.11 和官方 MCP Python SDK 2.x。此服务仅通过 stdio 使用 MCP 通信。
一条命令即可运行(需要 uv)。此软件包已发布到 PyPI,名称为 edgar13f-mcp,由此仓库的发布工作流通过可信发布上传,并以 io.github.Serios16/edgar13f-mcp 的名称列入官方 MCP Registry:
export SEC_USER_AGENT="Your Name [email protected]" # required by SEC fair access
uvx --python 3.11 edgar13f-mcp # pin a release: [email protected]
用于 Claude Desktop 等 MCP 客户端:
{"mcpServers": {"edgar13f": {
"command": "uvx",
"args": ["--python", "3.11", "edgar13f-mcp"],
"env": {"SEC_USER_AGENT": "Your Name [email protected]"}}}}
任何提交或标签也可以直接从 GitHub 运行:
uvx --python 3.11 --from git+https://github.com/Serios16/[email protected] edgar13f-mcp。
较旧的命令名称 edgar13f-server 仍然可用。tests/tools/install_smoke.sh 会在构建好的 wheel 上测试这两个名称(清空 uv 缓存、完成 MCP 握手;输出见 reports/artifacts/install_smoke_stage6.txt)。也可以从克隆的仓库运行:
python3.11 -m venv .venv && . .venv/bin/activate
pip install -e .
export SEC_USER_AGENT="Your Name [email protected]" # required by SEC fair access
python -m edgar13f.server # or: edgar13f-server
环境变量:
SEC_USER_AGENT:发送至 sec.gov 的 User-Agent。此变量必填;未设置时,服务不会联系 sec.gov。EDGAR13F_CACHE_DIR:磁盘缓存目录。默认使用$XDG_CACHE_HOME/edgar13f(或~/.cache/edgar13f),之后使用每位用户独立的私有临时目录。服务不会写入其他位置。EDGAR13F_REDACT:必须精确设为off,才会返回默认情况下会隐藏的行(见“限制”)。任何其他值或不设置,都会保持隐藏状态。EDGAR13F_AGENT_MODE:必须精确设为on,才会将未缩小范围的持仓和差异答案限制为持仓最大的 50 个(见 Agent 使用)。未设置时,所有 v1 调用的回答都与 v1.1.0 逐字节一致。EDGAR13F_FIXTURE_DIR:使用记录的 fixture 而不是 EDGAR 提供数据(测试使用;与EDGAR13F_REDACT=off同时设置时会被拒绝)。
SEC 访问遵循公平访问政策。在共享同一缓存目录的进程之间,请求启动时间至少间隔 0.25 秒(每秒少于 5 次)。403/429/5xx 响应和 HTML 错误页面会触发指数退避。响应会缓存在磁盘上。
工具
| 工具 | 返回内容 |
|---|---|
find_manager(name[, as_of][, limit]) | 当前或曾用 EDGAR 名称包含 name 的 CIK 候选项,优先列出提交过 13F 文件的管理人。entity_name 是 EDGAR 的当前名称(非特定时点名称);指定 as_of 时,has_13f_filings 只统计日期不晚于该日期的 13F 文件。 |
list_13f_filings(cik, as_of[, period]) | 该管理人在 as_of 当日或之前提交的所有 13F-HR、13F-HR/A、13F-NT 和 13F-NT/A 文件(若指定 period,则仅列出该期文件),包含期次、修订编号和类型、报告类型、管理人名称以及 EDGAR 链接。 |
get_holdings_as_of(cik, period, as_of[, cusip][, issuer][, max_positions][, position_type]) | 截至 as_of 时已知的某一季度有效持仓,逐行按提交内容返回(不合并或重新缩放)。其中会引用基础文件和所有已应用的修订文件。 |
diff_holdings(cik, period_a, period_b, as_of[, cusip][, issuer][, max_positions]) | 两个季度之间的持仓变化,均按同一 as_of 确定,并以 (CUSIP, put/call, SH/PRN) 为键:新增、移除、增加、减少或不变。 |
find_manager、period、issuer 和 max_positions 来自
附录 A(增量扩展:不使用这些参数的调用会得到
与 v1.1.0 完全相同的答案)。
每个响应都是一个 JSON 对象,并包含免责声明 “13F 报告仅包含多头持仓;数据可能比期末滞后最多 45 天。” 当服务无法作答时,会返回一个带有 status: "declined" 的常规结果,并附上六种原因之一:unknown_cik、not_yet_filed、notice_only、invalid_period、invalid_argument、unsupported_request。
Agent 使用(附录 A)
这些扩展面向大模型 Agent;它们通常从名称开始查询,而且无法读取 40 MB 的答案。典型流程如下:
// 1. name -> CIK (managers that have filed Form 13F come first)
{"tool": "find_manager", "arguments": {"name": "berkshire hathaway", "as_of": "2025-08-27"}}
// 2. which filings make up one quarter, as of a date
{"tool": "list_13f_filings", "arguments": {"cik": "1067983", "as_of": "2025-08-27", "period": "2025-03-31"}}
// 3. one issuer only; the answer adds matched_cusips
{"tool": "get_holdings_as_of", "arguments": {"cik": "1067983", "period": "2025-03-31", "as_of": "2025-08-27",
"issuer": "apple"}}
// 4. the 10 largest positions; the answer adds total_positions, truncated and order
{"tool": "get_holdings_as_of", "arguments": {"cik": "1067983", "period": "2025-03-31", "as_of": "2025-08-27",
"max_positions": 10}}
// 5. the 20 largest changes by |value_delta|
{"tool": "diff_holdings", "arguments": {"cik": "1067983", "period_a": "2024-12-31", "period_b": "2025-03-31",
"as_of": "2025-08-27", "max_positions": 20}}
issuer(2-100 个字符)会筛选出发行人名称包含该字符串的行,不区分大小写,并忽略连续空白;它可与cusip组合使用,两者之间为 AND 关系。max_positions(1-200)会按汇总价值(持仓)或 |value_delta|(差异)对持仓进行排名,即按 (CUSIP, put/call, SH/PRN) 分组,并返回排名靠前的持仓及其所有行。持仓不会被拆分,因此,每个持仓包含多行的管理人仍可能返回许多行;若要查询单个证券,请使用issuer或cusip。- 新参数只会筛选或排序行。引用信息(
accession_number、source_accessions、filing_date)和特定时点行为保持不变,且会先进行脱敏,再应用任何筛选条件。 find_manager会匹配所有当前和曾用 EDGAR 名称,并返回 EDGAR 的当前名称,因此名称不适用于特定时点查询。空缓存时的首次调用会读取自 1993 年以来 EDGAR 的季度表单索引(约需一分钟,每个缓存目录仅执行一次);后续调用只需几毫秒。
启用 EDGAR13F_AGENT_MODE=on 后,如果 get_holdings_as_of 或 diff_holdings 调用未指定 cusip、issuer 或 max_positions,则会按 max_positions 为 50 进行响应,并在答案中添加 auto_limited: true。其他调用不受影响。MCP 客户端配置:
{"mcpServers": {"edgar13f": {
"command": "uvx",
"args": ["--python", "3.11", "edgar13f-mcp"],
"env": {"SEC_USER_AGENT": "Your Name [email protected]", "EDGAR13F_AGENT_MODE": "on"}}}}
限制
- 仅限多头持仓。 Form 13F 不包含空头持仓,因此会拒绝
position_type不为"long"的请求。 - 滞后。 报告最迟可在季度结束后 45 天提交,修正文件也可能在数月后才送达。答案的时效性仅取决于截至
as_of已提交的内容。 - 屏蔽。 默认情况下,解析信息表时会移除黄金 ETF/信托、美国能源行业 ETF、S&P 500 指数基金/ETF 及其 UCITS 仿制品的行,因为作者会在不涉及这些工具的独立研究中进行分析。之后这些行绝不会被返回、缓存或记录日志。匹配会结合发行方名称和证券名称模式以及 CUSIP 列表,并有意倾向于多删而非少删。一些普通证券也会被丢弃。有两个具体情形会导致评分扣分:所有名称中包含 S&P 的 “SPDR S&P ...” 基金(不只是 S&P 500 基金),以及发行方名称类似信托或基金、且类别名称带有 “.500” 票息的债券(例如 “5.500% NOTES”)。类别名称中含有 “UNIT” 的能源公司证券也是如此。裁定 D2 禁止缩小列表以弥补这些扣分。查询已移除的 CUSIP 会返回
ok,但不含任何行。屏蔽适用于持仓行;find_manager返回未经筛选的实体名称(裁定 N1)。若要关闭屏蔽,请将EDGAR13F_REDACT=off(必须恰好为off);以这种方式读取的行会缓存在单独目录中,且恢复屏蔽后绝不会被提供。请参阅CLAUDE.md规则 2 及REGISTER.md中的裁定 D2。 - 服务不支持 2013 年以前的文本格式 13F 文件,也不提供价格、图表或业绩数据。
评估方式
- 隐藏且冻结的评分器。 黄金数据集、泄漏数据集和评分器在任何服务端代码编写前,已在单独的私有仓库中冻结。构建者无法读取或写入该仓库。
contracts/PREREG_COMMITMENT.md中记录了该仓库清单及此处复制的合同文件的 SHA-256。最终阶段结束后,所有内容都会公开,以便核验哈希值。 - 黄金数据集: 40 个精选项目和 700 个生成项目,按案例类型分层(例如,重述前一天和重述当天),另有 3,114 个泄漏案例。
- 除门槛测试外, 私有仓库还保存了以下内容,且每项都在运行前预注册:一个样本外数据集、一项由大模型 Agent 参与的评估、该评估的一次诊断性重跑,以及围绕 2026 年第三季度申报截止日进行的实时捕获(结果见下文)。
- 此仓库中的控制项。 它们会在每次推送时于 CI 中离线运行;测试会拒绝套接字连接:
- 泄漏测试套件包含一个 mutant 控制(禁用可见性检查;必须能发现违规情况,且涵盖 Addendum A 中的每个参数以及
find_manager(as_of))和一个 no-op 控制; - 在合成行上验证阻止列表,并植入一个故障;
- 根据独立预言机,对 §4 中的修正规则进行穷举检查;每个植入的规则变异都会导致检查失败(
tests/unit/test_restatement.py); - 大小、映射和声明检查,每项都植入一个故障。
- 泄漏测试套件包含一个 mutant 控制(禁用可见性检查;必须能发现违规情况,且涵盖 Addendum A 中的每个参数以及
- 操作系统级隔离。 CI 使用独立的非特权操作系统用户运行服务端,并从只读的检出副本启动。若该用户在预期缓存目录之外创建任何文件或目录,作业就会失败;同时必须能捕获一个植入的意外写入(
tests/tools/unprivileged_probe.sh)。 - 外部交叉核验(仅在测试时运行)。
tests/tools/datasets_crosscheck.py会将随机抽取的 (cik, period, as_of) 三元组的答案与 SEC Form 13F Data Sets 进行比较。服务端绝不会读取这些数据集。
Gate 结果(由评估器报告;仅汇总数据)
按设计不公开单项结果。预先注册的决策 Gate 2 已在提交 b208c47 上通过,该提交标记为 v1.0.0。Gate 3、4 和 5 分别在提交 ca60c5c、f7ee806 和 cc61944 上通过,标记为 v1.1.0、v1.2.0 和 v1.2.1。五个 Gate 的汇总数据相同。v1.2.2 是在 PyPI 上发布的第一个版本,仅更改了打包内容:新增 edgar13f-mcp 命令,而 src/ 下只有版本字符串与 v1.2.1 不同。
| 指标 | Gate 1 | Gate 2(v1.0.0) | Gate 3(v1.1.0) | Gate 4(v1.2.0) | Gate 5(v1.2.1) |
|---|---|---|---|---|---|
| 主要 Gate | 全部 PASS | 全部 PASS | 全部 PASS | 全部 PASS | 全部 PASS |
| 生成项 | 698 / 700 | 698 / 700 | 698 / 700 | 698 / 700 | 698 / 700 |
| 生成遗漏 | 1 个 restatement_before,1 个 restatement_after | 相同 | 相同;两者均为 D2 过度匹配 | 相同 | 相同 |
| 引用有效性 | 669 / 671 | 669 / 671 | 669 / 671 | 669 / 671 | 669 / 671 |
| 泄漏 | 3,114 个案例中有 0 次违规 | 3,114 个案例中有 0 次 | 3,114 个案例中有 0 次 | 3,114 个案例中有 0 次 | 3,114 个案例中有 0 次 |
| 精选项 | 34 / 34 | 34 / 34 | 34 / 34 | 34 / 34 | 34 / 34 |
| 拒绝 | 6 / 6 | 6 / 6 | 6 / 6 | 6 / 6 | 6 / 6 |
两项生成遗漏均源于裁定 D2:屏蔽列表移除了评分器预期的行(两个已知过度匹配模式见“限制”)。D2 禁止通过缩小列表来挽回这两项。
样本外测试。 对于日期为 2025-09 至 2026-08 的申报文件,这些文件处于冻结评估涵盖的时间窗口之外(as_of 最晚至 2025-08-27),所有主要 Gate 均 PASS:生成项 699 / 700、3,102 个案例中有 0 次泄漏违规、引用 639 / 640、拒绝 6 / 6。唯一的遗漏是一次 D2 过度匹配,该情况在评分前已预测到。
对 AI Agent 是否有帮助?(由评估者报告;仅汇总数据)
预注册于运行前(2026-10-14):使用相同的模型(Claude Sonnet 5.5,effort medium)、 相同的 80 个纯英文问题、相同的指令、12 轮预算,以及每个工具结果 50,000 个字符的上限;每个问题运行 2 次。模型看到的每个工具结果都经过相同的脱敏处理。每个问题都注明管理机构和发行方(而非 CIK 或 CUSIP)、季度,以及“截至某日期已向 SEC 提交”。
| 工具箱 | 正确数 | 泄漏数 | 每次运行的工具调用数 | 每个正确答案的成本 |
|---|---|---|---|---|
| 不使用工具 | 5 / 150(仅拒答;达到预算上限后停止) | 0 | 0 | $0.17 |
| edgar13f v1.2.0,Agent 模式 | 160 / 160 | 0 | 2.2 | $0.017 |
| EdgarTools MCP 5.60.0 | 105 / 160 | 0 | 9.0 | $0.145 |
与 EdgarTools 相比的配对差异为:+34 个百分点(95% CI +24 至 +44),因此根据预注册规则,edgar13f 表现更好。EdgarTools 在差异查询(7 / 20)、修订文件(7 / 20)和时点查询(23 / 40)上的表现最弱;edgar13f 对所有类型的问题都回答正确。
EdgarTools 为何出错。 对其 31 个未答对的问题进行预注册诊断性复测(2026-10-15),重现了这些问题(62 次运行中有 49 次),再次没有错误数字或泄漏:
- 33 次耗尽了 12 轮,其中 31 次发生在模型已经找到正确文件之后;
- 16 次选择了拒答:13 次针对实际有答案的问题,3 次给出了错误的拒答理由;其中 4 次还选错了文件或期间;
- 没有一次是因为字符数上限,也没有一次是数字错误。
增加轮数预算可能会缩小部分差距,但成本会更高;目前尚未对此进行测量。预先声明的预期还包括 edgar13f 的泄漏更少,但双方都没有泄漏。因此,泄漏防护已在工具层面展示(见上文的防护机制),但对于 Agent 是否有效,既没有证据支持,也没有证据反驳。
注意事项:
- 只测试了一个模型和一个提示词。
- 这些问题是关于特定时点的 13F 查询,正是此服务的用途,并非一般性的 SEC 问题。发行方名称与多个证券匹配的问题已排除。
- 评分方要求引用基础文件。若规则也接受包含所问行的新持仓修订文件,则 edgar13f 的引用有 126 / 126 条有效(记录值为 122 / 126)。
实时测试(已预注册,待完成)
在 2026 年第三季度文件提交截止日期前后(2026 年 11 月 16 日),评估者会在 11 月 13 日、17 日、19 日和 26 日,对随机抽取的 300 家管理机构采集 v1.1.0 的答案;每次询问前一天的情况。SEC 发布涵盖这些文件的数据集后,再对答案评分。预注册测试时,当前版本为 v1.1.0。这些调用不会使用 v1.2.0 的任何新参数,而且 v1.2.0 的默认值与 v1.1.0 逐字节相同(对比了 3,689 次夹具调用和 1,328 次实时调用),因此结果同样适用于 v1.2.0。采集和评分代码在首次采集前已冻结;其哈希值记录于
reports/LIVE_TEST_COMMITMENT.md。
延迟
冷启动(缓存为空)时,对该季度脱敏后行数最多的五份 13F-HR,调用 get_holdings_as_of(cik, 2025-03-31, as_of=2025-08-27),在进程内测量(实测;tests/tools/cold_latency.py,产物位于 reports/artifacts/cold_latency_stage3_*.json)。每个单元格显示两次运行(v1.0.0)或三次运行(v1.1)中的最差结果。对于 1776033,次日提交的修订报告取代了原有的 34,332 行报告,因此结果为 1,599 行。
| CIK | 行数 | v1.0.0 | v1.1 | SEC 请求数 |
|---|---|---|---|---|
| 2012383 | 50,158 | 8.3 s | 4.1 s | 9 -> 6 |
| 319933 | 49,594 | 8.1 s | 4.3 s | 9 -> 5 |
| 1761755 | 44,548 | 16.2 s | 4.2 s | 31 -> 5 |
| 895421 | 44,192 | 44.5 s | 7.6 s | 118 -> 13 |
| 1776033 | 1,599 | 8.1 s | 2.9 s | 23 -> 6 |
v1.1 只读取可能影响所请求季度的封面页和历史页。缓存预热后的调用耗时低于 0.6 s。list_13f_filings 仍会读取每份报告的封面页,因此对这些管理人首次调用需要 2-36 s。通过 MCP stdio,服务处理 50k 行的结果(约 40 MB)会额外耗时约 1 s,但 MCP Python SDK 的 stdio 客户端(2.2.0)本身需要 6-15 s 才能读取这么大的消息(耗时与消息大小呈二次关系;上游报告草案位于 reports/upstream/)。
Agent 使用扩展,对同样五位管理人运行两次(实测;tests/tools/agent_latency.py,产物为 reports/artifacts/agent_latency_run1.json 和 _run2.json):
| 调用 | 首次调用,缓存为空 | 后续调用 |
|---|---|---|
find_manager(name) | 63-79 s(EDGAR 的名称文件和 136 个季度表单索引前缀,每个缓存目录读取一次) | 0.02-0.05 s;新进程中为 1.7-3.2 s |
list_13f_filings(cik, as_of, period) | 0.7-3.7 s(完整列表:2-36 s) | 低于 0.05 s |
max_positions=50 可将 17-19 MB 的持仓结果(44-50k 行)缩减至 0.4-1.0 MB,适用于四位大型管理人中的三位;SDK 客户端读取耗时也因此从 6-14 s 降至 0.2-0.3 s。第四位管理人的每个持仓会分别报告数百行,因此其 50 个持仓仍有 17,741 行(6.7 MB)。差异结果则从 0.4-2.1 MB 降至约 13 KB。
包含实测产物的阶段报告位于 reports/。
测试
pip install -e ".[test]"
python -m pytest -q tests # offline; sockets are refused
python tests/checks/size_budget.py . && python tests/checks/map_check.py . && python tests/checks/claims_check.py .
协议检查:inspector CI 任务会使用固定版本的 MCP Inspector CLI(tests/inspector/inspector_check.sh),针对记录的测试样例检查服务,覆盖两个协议时期(2025-11-25,含 initialize 握手;2026-07-28,不含握手),将结果与 reports/artifacts/inspector_stage5.json 对比,并且必须能检测到仅列出三个工具的桩实现并使测试失败。生命周期检查(stdin 关闭、格式错误的行、调用期间收到 SIGTERM/SIGKILL)位于 tests/invariants/test_lifecycle.py。注册表元数据:server.json;发布步骤见 PUBLISHING.md。
MAP.md 列出各模块,并说明每项契约规则的实施和测试位置。REGISTER.md 记录裁定、假设和提案。
许可
MIT;详见 LICENSE。运行时依赖仅使用宽松的 OSI 许可(MIT/Apache/BSD/PSF/ISC)。服务不使用 edgartools(评估时仅将其用作对比基准),也不包含任何 AGPL 项目的代码。该服务与 SEC 无关,且其返回内容不构成投资建议。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。