yfinance 429 限流与季报截断怎么破?Python 迁移 FMP /stable/ 字段映射指南
在美股个人量化与策略原型验证阶段,开源库 yfinance 常被用作入门工具。但当策略走向多因子横截面回测与每日定时生产任务时,其底层调用雅虎财经非官方接口(财报模块请求 fundamentals-timeseries、行情与摘要依赖网页 Cookie 与 crumb 令牌校验)的瓶颈便会集中暴露:高并发轮询易触发 YFRateLimitError: Too Many Requests (429);.quarterly_income_stmt 等属性默认仅返回最近 4~5 个季度,且缺失 SEC 10-Q/10-K 受理时间戳,直接拿财季结束日回测极易引入前视偏差(Look-Ahead Bias)。
本文基于 FMP数据源中文站 梳理的 /stable/ 接口体系,调取 2026 年 11 月 7 日实盘快照,对苹果(AAPL)、微软(MSFT)、英伟达(NVDA)、谷歌(GOOGL)、Meta(META)、亚马逊(AMZN)6 家科技巨头与台积电 ADR(TSM)的财报字段、复权行情及全市场 63,549 行 EOD Bulk 数据做逐项对账,提供一份可复核的 yfinance 迁移映射与口径排雷指南。
一、 为什么量化生产环境需要迁出 yfinance?三大工程瓶颈与实盘深度对账
从非官方抓取库迁移至结构化商业 API,核心解决的是请求吞吐、历史期数深度与披露时间轴三大工程问题:
- 多并发 429 限流 vs 批量端点降维(含跨端点成交量口径差异):
yfinance的.info与.financials需逐股请求并维护会话令牌。而在 FMP/stable/架构下,盘中或盘后快照可调 Stock Batch Quote(股票批量报价接口,/stable/batch-quote)单次传入多个代码;全市场收盘归档可调 Bulk(批量数据接口)下的 Eod Bulk(日线行情批量接口,/stable/eod-bulk?date=2026-11-06),单次 HTTP 请求拉回全市场 63,549 行 CSV 记录。按代码格式统计,其中不含.号后缀的代码共 23,564 行(属代码格式分类,除美股主板普通股外还包含无点号的 OTC 证券、权证、优先股及基金,其中 1~4 位纯大写字母代码为 15,747 行、其余无点号代码 7,817 行;实盘建库需结合 Company Profile Bulk(公司概况批量接口,/stable/profile-bulk)的exchange、isActivelyTrading、isEtf、isFund过滤证券范围),含.号跨市场后缀的代码共 39,985 行(前 7 大后缀合计 27,448 行:.L7,031 行、.HK4,507 行、.BO4,347 行、.TO3,962 行、.SS2,612 行、.NS2,589 行、.SZ2,400 行,其余多市场后缀 12,537 行,已存盘于证据文件eod_bulk_2026_11_06_stats)。
- 单股日线
/full与eod-bulk的成交量差异提醒:对比表 1 六家公司在 2026-11-06 当天的单股/stable/historical-price-eod/full与/stable/eod-bulk实盘记录可见,两者的open、high、low、close四价 100% 全等,但以eod-bulk成交量为基准,单股/full的volume比eod-bulk高出 0.61%~4.48%(例如 AAPL 在/full为 44,703,806 股、在eod-bulk为 42,788,083 股,比eod-bulk高出 1,915,723 股即 4.48%,反过来即eod-bulk比/full低 4.29%;MSFT 高出 3.02%、AMZN 高出 3.72%、NVDA 高出 1.20%、META 高出 0.88%、GOOGL 高出 0.61%)。这源于批量快照生成截点与延迟交易结算汇总的时点差异,生产落库应固定单一主数据源或明确覆盖规则,切勿把两类端点的volume无标记混写进同一张量价因子表。
- 季报 4~5 期截断 vs 长周期历史序列(注意三表期数不等与取交集约束):
yfinance对三大季度报表仅返回最近 4~5 期,难以计算跨周期滚动因子(如 8 季滚动 SUE、5 年中枢 ROE)。通过 FMP 的 Statements(财务报表接口)传入period=quarter&limit=200,在本次核验的 6 家样本上实际返回利润表 63~165 期季报(三大报表整体区间为 60~165 期季报,其中 META 资产负债表为 60 期)、19~42 期年报。
- 三表合并(Join)的日期交集约束:从表 1 可以看到,同一标的三大报表的历史返回期数并不相等——AAPL 季报返回利润表 165 期(起自 1985-09-30)、资产负债表 153 期(起自 1988-09-30)、现金流量表 148 期(起自 1989-12-31,对应 FASB SFAS 95 准则生效期);GOOGL 季报则出现现金流量表(95 期,起自 2003-03-31)比资产负债表(92 期,起自 2003-12-31)早 3 期的情形。因此跨表计算 ROE、ROIC 或自由现金流转换率时,严禁按数组下标位置直接拼表,必须先按
(date, period)取三表共有财季的交集(即set(inc_dates) & set(bs_dates) & set(cf_dates))。
- 缺失披露时间戳 vs
acceptedDate的使用边界:yfinance财报列索引仅有会计期末日(如 2026-09-26)。FMP 在每条财报记录中提供filingDate与精确到秒的acceptedDate(SEC EDGAR 受理时间戳),便于控制回测前视偏差。但工程上需明确三点边界:①acceptedDate是法定 10-Q/10-K 受理时间,可能晚于盘后 8-K 业绩新闻稿首次发布日(如 AAPL 在 2026-11-02 发布业绩 8-K,次日 2026-11-03 08:05:15 受理 10-K);②acceptedDate反映首次申报受理时点,不单独追踪后续重述修订史;③/stable/ratios-ttm返回的是当前最新滚动 TTM 快照(无历史时点参数),做长周期历史 Point-in-Time 回测时应基于满足acceptedDate <= 回测日的历史三表滚动自算 TTM 指标并留存数据版本。
我们实盘调用 FMP 的 Income Statement(利润表接口,/stable/income-statement)、Balance Sheet Statement(资产负债表接口,/stable/balance-sheet-statement)、Cash Flow Statement(现金流量表接口,/stable/cash-flow-statement)与 Financial Ratios TTM(TTM 财务比率接口,/stable/ratios-ttm),对 6 家美股科技龙头截至 2026-11-07 的历史报表期数深度与最新财季指标统计如下:
表 1:6 家美股科技龙头 FMP /stable/ 历史报表期数深度与最新季报实盘对账(快照日:2026-11-07)
| 股票代码 | 季报期数(利润 / 资产 / 现金流) | 季报利润表起止跨度 | 年报期数(起止跨度) | 最新财季与 SEC 受理时间 (date · acceptedDate) | 最新单季营收 / 净利润(亿美元) | 最新单季自由现金流(亿美元) | TTM 稀释市盈率 |
|---|---|---|---|---|---|---|---|
| AAPL | 165 / 153 / 148 期 | 1985-09-30 ~ 2026-09-26 | 42 期 (1985 ~ 2026) | FY2026 Q4 (2026-09-26) · 2026-11-03 08:05:15 | 1,144.77 / 307.11 | +258.59 | 38.17 |
| MSFT | 165 / 153 / 149 期 | 1985-09-30 ~ 2026-09-30 | 41 期 (1986 ~ 2026) | FY2027 Q1 (2026-09-30) · 2026-10-28 16:07:39 | 922.79 / 366.29 | +186.33 | 27.71 |
| NVDA | 110 / 110 / 110 期 | 1999-05-02 ~ 2026-07-26 | 28 期 (1999 ~ 2026) | FY2027 Q2 (2026-07-26) · 2026-08-26 16:36:00 | 962.21 / 596.88 | +214.00 | 23.60 |
| GOOGL | 99 / 92 / 95 期 | 2002-03-31 ~ 2026-09-30 | 27 期 (1999 ~ 2025) | FY2026 Q3 (2026-09-30) · 2026-10-28 20:29:06 | 1,275.77 / 264.68 | -90.65 | 14.82 |
| META | 63 / 60 / 63 期 | 2011-03-31 ~ 2026-09-30 | 19 期 (2007 ~ 2025) | FY2026 Q3 (2026-09-30) · 2026-10-21 20:00:08 | 646.01 / 98.60 | -11.56 | 20.81 |
| AMZN | 123 / 120 / 119 期 | 1996-03-31 ~ 2026-09-30 | 30 期 (1996 ~ 2025) | FY2026 Q3 (2026-09-30) · 2026-10-29 18:20:46 | 2,019.44 / 206.85 | -348.37 | 20.96 |
实测数据说明:表 1 中 GOOGL(-90.65 亿美元)、META(-11.56 亿美元)与 AMZN(-348.37 亿美元)在 2026-09-30 季度的单季
freeCashFlow转负,均因当季 AI 数据中心等资本开支(capitalExpenditure)规模超过当季经营活动现金流净额(operatingCashFlow),按freeCashFlow == operatingCashFlow + capitalExpenditure精确勾稽如下:GOOGL 为422.90 + (-513.55) = -90.65 亿美元;META 为327.86 + (-339.42) = -11.56 亿美元;AMZN 为424.22 + (-772.59) = -348.37 亿美元。
二、 yfinance 常用属性与方法到 FMP /stable/ 接口的功能映射总表
在重构既有 Python 代码时,第一步是将 yf.Ticker(sym) 及 yf.download() 按实际数据语义(快照 vs 历史序列、零复权 vs 拆股复权 vs 分红复权)路由到对应的 FMP /stable/ 端点。下表梳理了 11 类常用功能的映射关系、复权分流与字段数(统一按单条 JSON 记录含 symbol 的总键数统计):
表 2:yfinance 属性/方法与 FMP /stable/ 端点功能映射对照表
| 迁移模块 | yfinance 原属性 / 方法 | FMP /stable/ 对应接口与参数示例 | 复权口径、日期边界与返回结构差异 |
|---|---|---|---|
| 实时/盘后快照报价 | Ticker.fast_info · Ticker.info(行情快照部分) | Stock Quote(股票报价接口,/stable/quote?symbol=AAPL) · Stock Batch Quote(股票批量报价接口,/stable/batch-quote?symbols=AAPL,MSFT) | 返回当前时点快照 JSON 数组 [{...}],含 price、previousClose、changePercentage(跨日涨跌幅)、marketCap、priceAvg50、priceAvg200 |
| 多股批量历史日线 | yf.download(syms, start=..., end=...) | 多股并发调下方日线接口,或全市场按日调 Eod Bulk(日线行情批量接口,/stable/eod-bulk?date=YYYY-MM-DD) | yf.download 的 end 为左闭右开 [start, end)(不含 end 当日);FMP 的 from/to 为闭区间 [from, to](含 to 当日),且返回降序 JSON 数组、小写字段名 |
| 历史日线(零复权原价) | Ticker.history(auto_adjust=False)(取未复权 OHLC 原价) | Unadjusted Stock Price(未复权日线行情接口,/stable/historical-price-eod/non-split-adjusted?symbol=AAPL) | 返回拆股与分红均未调整的原始交易价(注意其 JSON 键名仍写作 adjOpen、adjHigh、adjLow、adjClose、volume;如 AAPL 在 2020-08-31 实施 1 拆 4 前一日 2020-08-28 收盘为 499.24 美元) |
| 历史日线(仅拆股复权) | Ticker.history() 仅做拆股平滑(不含现金分红复权) | Stock Price and Volume Data(日线完整行情接口,/stable/historical-price-eod/full?symbol=AAPL&from=...) | 返回已完成拆合股前复权(Split-Adjusted)的 open、high、low、close、volume、change、changePercent、vwap(如 AAPL 2020-08-28 拆股复权 close = 124.81 = 499.24 / 4,不等于 auto_adjust=False 的原价) |
| 历史日线(拆股+分红全复权) | Ticker.history(auto_adjust=True)(或旧版 Adj Close 列) | Dividend Adjusted Price Chart(分红复权日K线接口,/stable/historical-price-eod/dividend-adjusted?symbol=AAPL) | 专设独立端点返回同时完成拆合股与现金分红除权调整的 adjOpen、adjHigh、adjLow、adjClose 与 volume |
| 公司基本面档案 | Ticker.info(静态公司档案部分) | Company Profile Data(公司概况接口,/stable/profile?symbol=AAPL) | 在本次核验的 6 家样本中返回 36 个字段(含 symbol、cik、isin、cusip、sector、industry、ipoDate、isActivelyTrading、isAdr 等) |
| TTM 估值与财务比率 | Ticker.info(trailingPE / returnOnEquity 等) | Financial Ratios TTM(TTM 财务比率接口,/stable/ratios-ttm?symbol=AAPL) · Key Metrics TTM(TTM 关键指标接口,/stable/key-metrics-ttm?symbol=AAPL) | 拆分为 62 个字段的 TTM 财务比率与 43 个字段的 TTM 关键指标(均含 symbol),算式透明可对账(详见本站财务计算公式库) |
| 季度 / 年度利润表 | Ticker.quarterly_income_stmt · Ticker.income_stmt | Income Statement(利润表接口,/stable/income-statement?symbol=AAPL&period=quarter&limit=200) | 本次核验的 6 家样本返回 63~165 期季报、19~42 期年报,每条记录含 39 个字段(含 symbol、acceptedDate、ebitda、epsDiluted 等) |
| 季度 / 年度资产负债表 | Ticker.quarterly_balance_sheet · Ticker.balance_sheet | Balance Sheet Statement(资产负债表接口,/stable/balance-sheet-statement?symbol=AAPL&period=quarter&limit=200) | 每条记录含 61 个字段(含 symbol),自带预计算的总债务 totalDebt 与狭义净债务 netDebt |
| 季度 / 年度现金流量表 | Ticker.quarterly_cashflow · Ticker.cashflow | Cash Flow Statement(现金流量表接口,/stable/cash-flow-statement?symbol=AAPL&period=quarter&limit=200) | 每条记录含 47 个字段(含 symbol),自带 operatingCashFlow、capitalExpenditure 与 freeCashFlow |
| 历史分红与拆合股明细 | Ticker.dividends · Ticker.splits | Dividends Company(公司分红派息接口,/stable/dividends?symbol=AAPL) · Stock Split Details(公司拆合股明细接口,/stable/splits?symbol=AAPL) | 分红接口提供除息日 date、登记日 recordDate、派息日 paymentDate 与宣告日 declarationDate;拆股接口提供分子 numerator 与分母 denominator |
三、 三大报表与估值指标高频字段名对照字典(以 AAPL FY2026 Q4 实盘报文为例)
yfinance 返回的财报 DataFrame 采用带空格的 Title Case 行索引(如 "Total Revenue"、"Diluted EPS"),且曾随上游模板调整而改名(如旧版 "Total Liab" 变为 df.loc["Total Liabilities Net Minority Interest"])。FMP /stable/ 则采用统一的 lowerCamelCase(小驼峰)JSON 键名。
以下展示 AAPL 最新财季(FY2026 Q4,结账日 2026-09-26)在 FMP /stable/income-statement 下的真实返回片段(完整 39 字段报文存盘于配套证据文件):
// GET https://quote-fmp.com/stable/income-statement?symbol=AAPL&period=quarter&limit=1
// 节选:仅展示 AAPL 2026-09-26(FY2026 Q4)单条记录中的 17 个高频核心字段(原始返回共 39 个字段)
[
{
"date": "2026-09-26",
"symbol": "AAPL",
"reportedCurrency": "USD",
"cik": "0000320193",
"filingDate": "2026-11-03",
"acceptedDate": "2026-11-03 08:05:15",
"fiscalYear": "2026",
"period": "Q4",
"revenue": 114477000000,
"costOfRevenue": 59657000000,
"grossProfit": 54820000000,
"researchAndDevelopmentExpenses": 11730000000,
"sellingGeneralAndAdministrativeExpenses": 7459000000,
"operatingIncome": 35631000000,
"netIncome": 30711000000,
"epsDiluted": 2.1,
"weightedAverageShsOutDil": 14630318000
}
]
为方便开发者替换代码中的字典键名,下表按 13 组模块行梳理了 38 个 FMP 字段(其中第 3 列直接列出 26 个候选字段、第 5 列勾稽说明补充 12 个关联字段,对照 22 个 yfinance 常用行索引/字典键)及 AAPL 实盘返回值:
表 3:yfinance 财报与估值键名迁移至 FMP /stable/ 候选字段对照表(以 AAPL 2026-09-26 季报 / 2026-11-07 TTM 为例)
| 所属模块 | yfinance 原字段名(DataFrame 行索引 / .info 键) | FMP /stable/ 对应字段名与端点 | AAPL 实盘返回值 | 迁移与勾稽注意事项 |
|---|---|---|---|---|
| 时间与身份 | 列名 Timestamp('2026-09-26')(无申报时间与 CIK) | date · filingDate · acceptedDate · cik · fiscalYear · period | 2026-09-26 · 2026-11-03 · 2026-11-03 08:05:15 · 0000320193 · 2026 · Q4 | yfinance 缺失后 5 项;回测可用时点可结合 acceptedDate 与 8-K 公告核对(详见错位财年对齐实战) |
| 利润表 | "Total Revenue" / "Operating Revenue" | revenue (/stable/income-statement) | 114,477,000,000 (1,144.77 亿美元) | 全市场统一键名,单位为 reportedCurrency 原币(元) |
| 利润表 | "Cost Of Revenue" | costOfRevenue | 59,657,000,000 | 毛利恒等式:grossProfit (548.20 亿) == revenue - costOfRevenue |
| 利润表 | "Research And Development" | researchAndDevelopmentExpenses | 11,730,000,000 | 销管费用 sellingGeneralAndAdministrativeExpenses 为 74.59 亿 |
| 利润表 | "Operating Income" · "EBITDA" | operatingIncome · ebitda | 35,631,000,000 · 39,585,000,000 | 另提供 ebit (361.35 亿) 与折旧摊销 depreciationAndAmortization (34.50 亿) |
| 利润表 | "Net Income" · "Diluted EPS" | netIncome · epsDiluted | 30,711,000,000 · 2.1 | 稀释加权平均股本 weightedAverageShsOutDil 为 14,630,318,000 股 |
| 资产负债表 | "Cash And Cash Equivalents" | cashAndCashEquivalents (/stable/balance-sheet-statement) | 36,305,000,000 | 广义现金及短投 cashAndShortTermInvestments 为 567.22 亿 |
| 资产负债表 | "Total Assets" | totalAssets | 404,548,000,000 (4,045.48 亿美元) | 合并恒等式:totalAssets == totalLiabilities (2,924.55 亿) + totalEquity (1,120.93 亿) |
| 资产负债表 | "Total Debt" · "Net Debt" | totalDebt · netDebt | 80,111,000,000 · 43,806,000,000 | totalDebt == shortTermDebt (119.03 亿) + longTermDebt (682.08 亿);netDebt == totalDebt - cashAndCashEquivalents |
| 现金流量表 | "Operating Cash Flow" | operatingCashFlow (/stable/cash-flow-statement) | 28,101,000,000 | 与同表 netCashProvidedByOperatingActivities (281.01 亿) 数值全等 |
| 现金流量表 | "Capital Expenditure" · "Free Cash Flow" | capitalExpenditure · freeCashFlow | -2,242,000,000 · 25,859,000,000 | 本次核验的 6 家样本中 capitalExpenditure 均以负数列报,满足 freeCashFlow == operatingCashFlow + capitalExpenditure |
| 现金流量表 | "Stock Based Compensation" · "Repurchase Of Capital Stock" | stockBasedCompensation · commonStockRepurchased | 3,266,000,000 · -24,296,000,000 | 股权激励与股票回购核心字段,直接用于计算真实净股东回报率 |
| TTM 比率 | .info 键:"trailingPE" · "priceToBook" · "returnOnEquity" · "enterpriseToEbitda" | priceToEarningsDilutedRatioTTM · priceToBookRatioTTM · returnOnEquityTTM · evToEBITDATTM | 38.17 · 44.50 · 1.2761 (127.61%) · 29.19 | /stable/ratios-ttm 负责价格乘数与周转率,/stable/key-metrics-ttm 负责 EV 倍数与 ROE/ROIC |
四、 迁移时最容易算错数的四个口径暗坑(实盘排雷)
把 URL 和字段名替换完成后,若不了解 FMP 与 yfinance 在底层计算口径上的四处差异,直接套用旧公式会导致回测收益率与估值失真。
1. 日线 changePercent 是“当日日内涨跌幅”,不能当成“跨日收盘收益率”!
在 yfinance 中,开发者习惯对 df["Close"].pct_change() 求跨日收益率;当迁移到 FMP Stock Price and Volume Data(日线完整行情接口,/stable/historical-price-eod/full)时,看到返回报文里带有 change 和 changePercent 字段,很多人会直接读取 changePercent 当作日收益率。
这是迁移头号必死坑:在本次核验的 18 + 2 = 20 根跨六年已定盘日线样本(2026-11-04 至 2026-11-06 六家公司共 18 根日线 + AAPL 2020-08-28 与 2020-08-31 拆股前后 2 根日线,完整校验表存盘于证据文件 daily_18_bars_intraday_and_vwap_audit)中,/stable/historical-price-eod/full 的 change == round(close - open, 2)、changePercent 对应 (close - open) / open × 100%(该字段小数精度不固定,20 根样本中 8 根给足 4~8 位小数、12 根仅保留 2 位小数,按 2 位计最大偏离 0.00492pp 即 <0.005pp)20/20 无一例外全部成立——即它衡量的是剔除隔夜跳空缺口的当日日内实体涨跌幅(哪怕在 2020-08-28 拆股前一日收 124.81 / 开 126.01 返回 -1.20 / -0.95231%、2020-08-31 拆股当日收 129.04 / 开 127.58 返回 +1.46 / +1.14%,跨越六年与拆股边界依然严格服从该日内公式),而非相对前一日收盘价(previousClose)的跨日涨跌幅!
我们以 6 家科技巨头在 2026-11-06 当天的实盘日线与批量报价报文做对账验证:
表 4:2026-11-06 六大科技股 FMP 日线 changePercent(日内口径)与真实跨日收盘收益率实盘对比
| 股票代码 | 前一日收盘 prev_close (11-05) | 当日开盘 open (11-06) | 当日收盘 close (11-06) | FMP 日线 change (close - open) | FMP 日线 changePercent(日内涨跌) | 真实跨日收盘涨跌幅 (close / prev_close - 1) | 方向是否相反? |
|---|---|---|---|---|---|---|---|
| AAPL | 344.17 | 338.73 | 342.37 | +3.64 | +1.07% (接口返回 1.07,仅 2 位;算式 1.0746%) | -0.52% (-0.523%) | 方向相反(低开高走,真跌假涨) |
| MSFT | 535.93 | 525.69 | 530.61 | +4.92 | +0.94% (0.93591%) | -0.99% (-0.99267%) | 方向相反(低开高走,真跌假涨) |
| NVDA | 181.60 | 191.10 | 186.64 | -4.46 | -2.33% (接口返回 -2.33,仅 2 位;算式 -2.33386%) | +2.78% (+2.77533%) | 方向相反(高开低走,真涨假跌) |
| GOOGL | 282.57 | 284.90 | 284.78 | -0.12 | -0.04% (-0.04212%) | +0.78% (+0.78211%) | 方向相反(高开微落,真涨假跌) |
| META | 605.08 | 607.33 | 610.15 | +2.82 | +0.46% (0.46433%) | +0.84% (+0.83791%) | 同向(但漏计 +0.37% 隔夜跳空) |
| AMZN | 260.21 | 259.81 | 259.30 | -0.51 | -0.20% (-0.1963%) | -0.35% (-0.34972%) | 同向(但漏计 -0.15% 隔夜跳空) |
表 4 的实测结果极具警示意义:在 2026-11-06 这一天,AAPL、MSFT、NVDA、GOOGL 四家巨头的日线 changePercent 与真实跨日收盘涨跌幅符号完全相反! 例如 NVDA 在 11-05 收于 181.60 美元,11-06 大幅高开于 191.10 美元后日内回落收于 186.64 美元——全天真实跨日涨幅为 +2.78%(注:实时报价接口 /stable/quote 与 /stable/batch-quote 中的 changePercentage 字段计算的正是相对 previousClose 的 +2.77533%),但历史日线接口 /stable/historical-price-eod/full 中的 changePercent 记录的是日内从 191.10 跌至 186.64 的 -2.33%(接口返回 2 位小数 -2.33,按四价精确算式 -4.46 / 191.10 = -2.33386%)。因此,回测计算日频收益率时,切忌直接读取日线接口的 changePercent,必须按日期升序排列后用 close[t] / close[t-1] - 1(或复权收盘价 adjClose[t] / adjClose[t-1] - 1)自行计算。
2. 日线三档复权分流:零复权(/non-split-adjusted)、拆股复权(/full)与分红复权(/dividend-adjusted)
在 yfinance 中,通过布尔参数 auto_adjust=True/False 切换复权模式;而在 FMP /stable/ 架构下,三类复权口径被严格拆分为三个独立端点(详见《美股分红复权行情怎么拉?基于 FMP 分红复权日 K 线接口计算真实总回报率实战》):
- 零复权原始价(
/stable/historical-price-eod/non-split-adjusted):对应yfinance的auto_adjust=False原始 OHLC 价格。实测 AAPL 在 2020-08-31(1 拆 4 拆股生效日)与前一日 2020-08-28 的返回报文可见,2020-08-28 的未复权收盘价为 499.24 美元(volume = 46,907,500),2020-08-31 除权后直接变为 129.04 美元(volume = 225,702,700)。注意该端点的 JSON 键名仍写作adjOpen / adjHigh / adjLow / adjClose。 - 仅拆合股前复权(
/stable/historical-price-eod/full):返回的open、high、low、close默认已完成历史拆合股平滑(如 AAPL 在 2020-08-28 的close = 124.81 = 499.24 / 4、volume = 187,630,000 = 46,907,500 × 4),但不含现金分红复权;同时,在本次核验的 20 根跨六年已定盘日线样本中,该端点的vwap字段 20/20 恒等于四价简单算术均值(open + high + low + close) / 4(如表 4 中 AAPL 11-06 四价均值为(338.73 + 345.79 + 338.30 + 342.37) / 4 = 341.2975,2020-08-28 为(126.01 + 126.44 + 124.58 + 124.81) / 4 = 125.46,均与接口vwap完全相等)。 - 拆股 + 现金分红全复权(
/stable/historical-price-eod/dividend-adjusted):对应yfinance的auto_adjust=True(或Adj Close列),直接返回同时完成拆合股与现金分红除权调整的adjOpen、adjHigh、adjLow、adjClose、volume。计算长周期因子总回报率(Total Return)时,应调用该端点或使用/stable/eod-bulk中的adjClose列。
3. /stable/ 接口路径传参规范、DataFrame 索引转换与 JSON / CSV 双轨制
- 代码改走 Query 参数与日期升序转换:现行
/stable/架构统一采用查询参数?symbol=AAPL(批量报价/stable/batch-quote传?symbols=AAPL,MSFT),且所有历史日线与三大报表默认按date从新到旧(降序)返回。若原yfinance下游代码依赖升序DatetimeIndex与首字母大写列名(Open/High/Low/Close/Volume),可在拉取 JSON 后执行df = pd.DataFrame(rows).sort_values("date").set_index("date")并重命名列。 - 常规接口返回 JSON 数组 vs Bulk 接口返回 CSV 流:单股查询接口均返回顶层 JSON 数组
[{...}];但/stable/eod-bulk、/stable/income-statement-bulk等 Bulk(批量数据接口)返回的是 CSV 文本流(调r.json()会抛出JSONDecodeError),须用csv.DictReader(io.StringIO(r.text))或pd.read_csv(io.StringIO(r.text))解析(详见《FMP Bulk 批量接口建库实战》)。
4. 跨表勾稽与非美 ADR 估值的「币种 + 存托股换算比例」双重核验(以台积电 TSM 实测为例)
- 合并资产负债表与现金流恒等式:FMP 资产负债表满足合并口径恒等式
totalAssets == totalLiabilities + totalEquity(其中totalEquity == totalStockholdersEquity + minorityInterest,对含少数股东权益的公司切勿漏加minorityInterest;详见《Piotroski F-Score 9 分选股法实战》)。 - 跨国 ADR 必须同时核对
reportedCurrency与每份 ADR 代表的普通股股数(ADR Ratio):以台积电美股 ADR(TSM,公司章程规定 1 份美股 ADR 代表 5 股台湾普通股)为例,我们实盘拉取/stable/quote?symbol=TSM、/stable/income-statement?symbol=TSM与/stable/ratios-ttm?symbol=TSM(完整数据存盘于证据文件tsm_adr_audit)即可实现内部自证:
- 股价与财报币种错配:纽交所行情
/stable/quote?symbol=TSM的报价为美元(price = 375.44 USD、marketCap = 1,947,212,051,200 USD),而利润表的记账币种为新台币(reportedCurrency = "TWD",FY2025 营收 38,090.54 亿新台币、净利润 16,976.04 亿新台币); - 跨接口自证 FMP 利润表股本与
epsDiluted已按 1:5 折算为每份 ADR 口径,切勿重复乘 5:直接用报价接口的美元市值除以美元股价marketCap ÷ price = 1,947,212,051,200 / 375.44 = 5,186,480,000 份(约 51.86 亿份 ADR),与利润表中的稀释加权平均股本weightedAverageShsOutDil(FY2025 为 5,186,111,400、2026Q3 为 5,186,400,000)仅相差 0.007% / 0.0015%,证明利润表的股本字段本身就是折算后的 ADR 份数。同时,FY2025 表内自算netIncome ÷ weightedAverageShsOutDil = 1,697,604,000,000 / 5,186,111,400 = 327.34 新台币,而接口返回epsDiluted = 331.25 新台币(相差 -1.18%;2026Q3 自算为 147.05 vs 接口 147.15,相差 0.07%,TTMnetIncomePerShareTTM = 491.33新台币/ADR),说明年度epsDiluted直接取自公司申报的普通股稀释 EPS(66.25 新台币)乘以 5(66.25 × 5 = 331.25)。因此,用美股 TSM 美元股价除以 FMP 利润表epsDiluted计算市盈率时,只需调用 Forex(外汇数据接口)将新台币折算为美元,绝不能再将epsDiluted乘以 5;反之若直接引用台湾证交所原始普通股 EPS(66.25 新台币),才需同时乘以 5 并换算汇率。
五、 Python 迁移实战:40 行代码完成 FMP 核心数据拉取与跨接口口径对账
下面给出完整、零伪代码、可直接运行的 Python 迁移数据读取与对账脚本(40 行)。脚本通过环境变量 FMP_KEY 读取密钥,在 SNAP_DATE = "2026-11-07" 快照下按 (x.get("acceptedDate") or x["date"])[:10] <= SNAP_DATE 过滤截至快照日已受理的季报,自动完成 6 家科技巨头的历史季报深度盘点、最新财季三表日期与恒等式校验、TTM 市盈率读取,以及真实跨日收益率 vs 日内 changePercent 的对比:
import os, requests
# Linux/macOS: export FMP_KEY=your_api_key_here
# Windows PowerShell: $env:FMP_KEY="your_api_key_here"
API_KEY, BASE = os.environ["FMP_KEY"], "https://quote-fmp.com/stable"
SNAP_DATE, SYMBOLS = "2026-11-07", ["AAPL", "MSFT", "NVDA", "GOOGL", "META", "AMZN"]
def get_json(path, **params):
r = requests.get(f"{BASE}/{path}", params={**params, "apikey": API_KEY}, timeout=25)
r.raise_for_status()
return r.json()
for sym in SYMBOLS:
inc_q = [x for x in get_json("income-statement", symbol=sym, period="quarter", limit=200) if (x.get("acceptedDate") or x["date"])[:10] <= SNAP_DATE]
bs_q = [x for x in get_json("balance-sheet-statement", symbol=sym, period="quarter", limit=200) if (x.get("acceptedDate") or x["date"])[:10] <= SNAP_DATE]
cf_q = [x for x in get_json("cash-flow-statement", symbol=sym, period="quarter", limit=200) if (x.get("acceptedDate") or x["date"])[:10] <= SNAP_DATE]
rat = get_json("ratios-ttm", symbol=sym)[0]
px = sorted(get_json("historical-price-eod/full", symbol=sym, **{"from": "2026-10-20", "to": SNAP_DATE}), key=lambda x: x["date"])
if not inc_q or not bs_q or not cf_q or len(px) < 2:
continue
q0_i, q0_b, q0_c = inc_q[0], bs_q[0], cf_q[0]
if not (q0_i["date"] == q0_b["date"] == q0_c["date"]):
continue
bs_ok = (q0_b["totalAssets"] == q0_b["totalLiabilities"] + q0_b["totalEquity"])
fcf_ok = (q0_c["freeCashFlow"] == q0_c["operatingCashFlow"] + q0_c["capitalExpenditure"])
p1, p0 = px[-1], px[-2]
cc_ret = round((p1["close"] / p0["close"] - 1.0) * 100.0, 2)
print({
"symbol": sym,
"inc_q_n": len(inc_q),
"inc_q_from": inc_q[-1]["date"],
"latest_q": f"FY{q0_i['fiscalYear']}-{q0_i['period']}({q0_i['date']})",
"accepted": q0_i["acceptedDate"],
"rev_B": round(q0_i["revenue"] / 1e8, 2),
"fcf_B": round(q0_c["freeCashFlow"] / 1e8, 2),
"pe_ttm": round(rat["priceToEarningsDilutedRatioTTM"], 2),
"cc_ret_pct": cc_ret,
"fmp_chg_pct": round(p1["changePercent"], 2),
"bs_fcf_ok": (bs_ok and fcf_ok),
})
在本地终端配置好 FMP_KEY 后执行该脚本,根据上述代码返回结果整理的标准输出(stdout)与表 1、表 4 的实盘数值完全一致:
{'symbol': 'AAPL', 'inc_q_n': 165, 'inc_q_from': '1985-09-30', 'latest_q': 'FY2026-Q4(2026-09-26)', 'accepted': '2026-11-03 08:05:15', 'rev_B': 1144.77, 'fcf_B': 258.59, 'pe_ttm': 38.17, 'cc_ret_pct': -0.52, 'fmp_chg_pct': 1.07, 'bs_fcf_ok': True}
{'symbol': 'MSFT', 'inc_q_n': 165, 'inc_q_from': '1985-09-30', 'latest_q': 'FY2027-Q1(2026-09-30)', 'accepted': '2026-10-28 16:07:39', 'rev_B': 922.79, 'fcf_B': 186.33, 'pe_ttm': 27.71, 'cc_ret_pct': -0.99, 'fmp_chg_pct': 0.94, 'bs_fcf_ok': True}
{'symbol': 'NVDA', 'inc_q_n': 110, 'inc_q_from': '1999-05-02', 'latest_q': 'FY2027-Q2(2026-07-26)', 'accepted': '2026-08-26 16:36:00', 'rev_B': 962.21, 'fcf_B': 214.0, 'pe_ttm': 23.6, 'cc_ret_pct': 2.78, 'fmp_chg_pct': -2.33, 'bs_fcf_ok': True}
{'symbol': 'GOOGL', 'inc_q_n': 99, 'inc_q_from': '2002-03-31', 'latest_q': 'FY2026-Q3(2026-09-30)', 'accepted': '2026-10-28 20:29:06', 'rev_B': 1275.77, 'fcf_B': -90.65, 'pe_ttm': 14.82, 'cc_ret_pct': 0.78, 'fmp_chg_pct': -0.04, 'bs_fcf_ok': True}
{'symbol': 'META', 'inc_q_n': 63, 'inc_q_from': '2011-03-31', 'latest_q': 'FY2026-Q3(2026-09-30)', 'accepted': '2026-10-21 20:00:08', 'rev_B': 646.01, 'fcf_B': -11.56, 'pe_ttm': 20.81, 'cc_ret_pct': 0.84, 'fmp_chg_pct': 0.46, 'bs_fcf_ok': True}
{'symbol': 'AMZN', 'inc_q_n': 123, 'inc_q_from': '1996-03-31', 'latest_q': 'FY2026-Q3(2026-09-30)', 'accepted': '2026-10-29 18:20:46', 'rev_B': 2019.44, 'fcf_B': -348.37, 'pe_ttm': 20.96, 'cc_ret_pct': -0.35, 'fmp_chg_pct': -0.2, 'bs_fcf_ok': True}
六、 常见问题解答(FAQ)
1. 以前用 yf.download(["AAPL", "MSFT", ...]) 一次拉多只股票的日线,迁到 FMP 后如何选择单股接口与批量接口?
按标的数量与用途分两档处理:若仅获取几十只自选股的最新盘面快照,可调用 Stock Batch Quote(股票批量报价接口,/stable/batch-quote?symbols=AAPL,MSFT,NVDA)单次请求批量返回;若需每日盘后归档全市场数千只标的的日线 OHLCV 与 adjClose,可调用 Eod Bulk(日线行情批量接口,/stable/eod-bulk?date=YYYY-MM-DD)单次拉取全市场当日 63,549 行 CSV 收盘数据(注意单股 /full 接口的成交量比 eod-bulk 高出约 0.61%~4.48%,建库时应固定单一主数据源)。
2. yfinance 里拿不到的标普 500 历史成分股变动、退市股清单、13F 机构持仓与电话会纪要,FMP 对应哪几个端点?
这四个高阶投研端点均已在本次实盘核验中验证通过(样本响应存盘于配套证据文件 faq2_endpoints_live_proof):还原历史时点成分股池以消除幸存者偏差,可组合调用 Historical S&P 500(标普500成分变动接口,/stable/historical-sp500-constituent)与 Delisted Companies(退市公司清单接口,/stable/delisted-companies?page=0&limit=100,详见《消除美股回测幸存者偏差实战》);提取管理层业绩电话会全文与 13F 机构持仓申报,则分别调用 Earnings Transcript(业绩电话会纪要检索接口,/stable/earning-call-transcript?symbol=AAPL&year=2026&quarter=3)与 Institutional Ownership Filings(机构持股申报接口,/stable/institutional-ownership/latest?page=0&limit=100)。
如需在本地跑通上述 yfinance 迁移对账脚本与全量 /stable/ 接口,可前往 快速接入指南 免费申领 Ultimate 全接口试用密钥,或查阅 定价与会员套餐 了解详情。