yfinance Financials 财务报表与业绩数据 API 完全指南:Ticker 三大报表、盈余日历与 SEC 备案详解
【免费下载链接】yfinanceDownload market data from Yahoo! Finance's API项目地址: https://gitcode.com/GitHub_Trending/yf/yfinance
本篇技术指南围绕 yfinance 仓库中 yfinance.financials.rst 所定义的Ticker财务数据接口展开,系统讲解利润表、资产负债表、现金流量表、盈余数据、盈余日历与 SEC 备案六大类 API 的方法/属性双形态用法、参数语义、底层数据流水线与缓存机制。读完本文,你将能够熟练通过yf.Ticker拉取标准化的年度/季度/TTM 财务报表,掌握pretty、as_dict、freq、limit等关键参数的精确行为,并理解这些接口背后的 Yahoo 财报时序数据通道及其边界限制。
一、接口全景:方法(Method)与属性(Property)的双形态设计
yfinance 的财务数据 API 全部挂在yfinance.Ticker对象上,文档将其归类为 Financials 模块。其核心设计是一套「方法为底层实现、属性为便捷封装」的双形态结构:
- 方法形态(如
get_income_stmt()):允许传入as_dict、pretty、freq等参数,灵活控制输出; - 属性形态(如
income_stmt):无参数访问,内部固定使用pretty=True,直接返回格式化好的pd.DataFrame或dict。
属性的实现定义在 yfinance/ticker.py 中,例如income_stmt属性就是get_income_stmt(pretty=True)的别名(yfinance/ticker.py)。方法本体集中在 yfinance/base.py 的TickerBase中。
完整接口清单如下(与 yfinance.financials.rst 的 autosummary 一一对应):
| 类别 | 方法 | 属性 |
|---|---|---|
| 利润表 | get_income_stmt() | income_stmt/quarterly_income_stmt/ttm_income_stmt |
| 资产负债表 | get_balance_sheet() | balance_sheet |
| 现金流量表 | get_cashflow() | cashflow/quarterly_cashflow/ttm_cashflow |
| 盈余摘要 | get_earnings() | earnings |
| 盈余日历 | get_earnings_dates() | earnings_dates |
| 事件日历 | get_calendar() | calendar |
| SEC 备案 | get_sec_filings() | sec_filings |
从源码结构看,属性形态还保留了一批历史兼容别名,如incomestmt、financials、balancesheet、cash_flow等,它们与主属性返回完全一致的数据(见 yfinance/ticker.py)。
二、三大财务报表:利润表、资产负债表与现金流量表
三大报表是 Financials 模块的核心,三者的方法签名高度一致,均接受as_dict、pretty、freq三个参数,返回以报告日期为列、以科目为行的pd.DataFrame。
2.1 通用参数语义
以利润表为例,yfinance/base.py 中get_income_stmt()的参数定义如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
as_dict | bool | False | 为True时将DataFrame转为 Pythondict返回 |
pretty | bool | False | 为True时将驼峰命名的行索引格式化为人读的标题(如TotalRevenue→Total Revenue) |
freq | str | "yearly" | 报告频率:"yearly"(年度)、"quarterly"(季度)、"trailing"(近 12 个月,TTM) |
pretty的格式化底层调用utils.camel2title(),利润表对EBIT、EBITDA、EPS、NI等缩写做了保留处理(yfinance/base.py),资产负债表则对PPE做了缩写保护(yfinance/base.py)。
典型用法:
import yfinance as yf t = yf.Ticker("AAPL") # 年度利润表(方法形态,原始驼峰行名) raw = t.get_income_stmt(pretty=False, freq="yearly") print(raw.head()) # 季度利润表(属性形态,自动 pretty) q = t.quarterly_income_stmt print(q) # TTM 利润表 ttm = t.ttm_income_stmt # 转为 dict,便于 JSON 序列化 d = t.get_income_stmt(as_dict=True)2.2freq参数的三档语义与约束差异
虽然三个freq取值在三个方法中外观一致,但底层校验并不完全相同。核心校验逻辑位于 yfinance/scrapers/fundamentals.py 的_fetch_time_series():
- 合法
freq仅为"yearly"、"quarterly"、"trailing"三者,否则抛出ValueError; "trailing"(TTM)仅对利润表和现金流量表开放,若对资产负债表传入freq="trailing"会直接抛错"frequency 'trailing' only available for cash-flow or income data"。因此ttm_income_stmt、ttm_cashflow存在,但不存在ttm_balance_sheet。
此外,TTM 数据在底层还有一个特殊行为:时序接口只返回最近一列数据。在 yfinance/scrapers/fundamentals.py 中可以看到if (timescale == "trailing"): df = df.iloc[:, [0]],即 TTM 结果永远只有「最近 12 个月」这一列。
2.3 各报表的典型输出内容
仓库测试 tests/test_ticker.py 对各报表的返回内容做了明确断言,可作为字段预期:
- 利润表:至少包含
Total Revenue(总营收)与Basic EPS(基本每股收益)两行,年度数据相邻两列间隔约 365 天(tests/test_ticker.py); - 资产负债表:至少包含
Total Assets(总资产)与Net PPE(净固定资产)两行(tests/test_ticker.py); - 所有报表的列按报告日期降序排列(最新报告期在最左列),行顺序与 Yahoo 官网展示顺序一致(yfinance/scrapers/fundamentals.py)。
可复制的验证代码:
import yfinance as yf t = yf.Ticker("MSFT") assert "Total Revenue" in t.income_stmt.index assert "Basic EPS" in t.income_stmt.index assert "Total Assets" in t.balance_sheet.index assert "Net PPE" in t.balance_sheet.index # 年度与季度数据的时间间隔(天) import pandas as pd annual_period = abs((t.income_stmt.columns[0] - t.income_stmt.columns[1]).days) assert abs(annual_period - 365) < 20三、盈余数据:earnings与earnings_dates
3.1get_earnings():盈余摘要(已标记废弃)
get_earnings(as_dict=False, freq="yearly")返回freq为"yearly"、"quarterly"或"trailing"的盈余表(yfinance/base.py)。需要特别提示:该接口在底层已不可用——yfinance/scrapers/fundamentals.py 中的earnings属性会直接发出DeprecationWarning并返回None,警告文案明确建议改用Ticker.income_stmt中的Net Income(净利润)行。因此在新代码中应避免使用earnings/get_earnings(),改用利润表数据。
3.2get_earnings_dates():盈余公告日期与预期/实际 EPS
get_earnings_dates(limit=12, offset=0)是盈余日历的核心接口,返回以盈余公告日期为索引、含EPS Estimate(预期 EPS)、Reported EPS(实际 EPS)、Surprise(%)(超预期幅度)三列的DataFrame(yfinance/base.py)。
参数行为:
| 参数 | 默认值 | 约束与语义 |
|---|---|---|
limit | 12 | 请求的盈余公告行数;上限 100,超过会抛出ValueError("Yahoo caps limit at 100")。默认 12 大致对应未来 4 个季度 + 历史 8 个季度 |
offset | 0 | 搜索偏移:0从未来 EPS 预期开始;1从最近一次实际 EPS 开始;x从第 x 次历史 EPS 开始 |
结果会按limit做内存缓存(self._earnings_dates[limit] = df),重复以相同limit调用不会重复请求网络(yfinance/base.py)。
其数据来源值得说明。实现上存在两条通道:
- HTML 爬取(当前默认):
_get_earnings_dates_using_scrape()请求https://finance.yahoo.com/calendar/earnings?symbol={ticker}&offset={offset}&size={size},用 BeautifulSoup 解析页面<table>,再经pd.read_html()转表,并将EDT/EST时区转换为America/New_York(yfinance/base.py)。size会根据limit自动取 25 / 50 / 100 三档。 - Screener API(已停用):
_get_earnings_dates_using_screener()使用v1/finance/visualization接口。源码注释明确记录:2025 年夏季 Yahoo 停止更新该端点的数据,因此实现已回退到 HTML 爬取(yfinance/base.py)。
仓库测试覆盖了earnings_dates的基本返回与limit=100场景(tests/test_ticker.py)。实际返回格式示例(来源为源码 docstring):
EPS Estimate Reported EPS Surprise(%) Date 2025-10-30 2.97 - - 2025-07-22 1.73 1.54 -10.88 2025-05-06 2.63 2.7 2.57四、calendar:事件、盈余预期与股息日期
get_calendar()返回一个dict,包含近期公司事件与盈余预估区间(yfinance/base.py)。底层实现位于 yfinance/scrapers/quote.py 的_fetch_calendar(),通过拉取 Yahoo 的calendarEvents模块构建字典,常见键如下:
| 键 | 类型 | 含义 |
|---|---|---|
Dividend Date | datetime.date | 股息发放日 |
Ex-Dividend Date | datetime.date | 除息日 |
Earnings Date | list[datetime.date] | 预计盈余公告日期列表 |
Earnings High/Earnings Low/Earnings Average | 数值 | 分析师盈余预期的高值 / 低值 / 均值 |
Revenue High/Revenue Low/Revenue Average | 数值 | 分析师营收预期的高值 / 低值 / 均值 |
测试 tests/test_ticker.py 断言该 dict 至少包含Earnings Date、Earnings Average、Earnings Low、Earnings High四个键,且验证了结果会被缓存(连续两次t.calendar返回同一对象)。
import yfinance as yf t = yf.Ticker("AAPL") cal = t.calendar # 等价于 t.get_calendar() print(cal["Earnings Date"]) print(cal["Earnings Average"], cal["Earnings Low"], cal["Earnings High"])五、sec_filings:SEC 备案文件检索
get_sec_filings()返回公司向美国 SEC 提交的备案文件列表(yfinance/base.py)。底层_fetch_sec_filings()(yfinance/scrapers/quote.py)拉取 Yahoo 的secFilings模块,并对原始结构做两处规整:
- 每条备案的
exhibits(附件)被转换为{类型: 链接}的字典,如{'EX-10.1': 'https://...'}; - 备案
date从'%Y-%m-%d'字符串解析为datetime.date对象。
返回的每条记录通常包含备案类型(如 10-K 年报、10-Q 季报、8-K 重大事件公告)、提交日期、附件链接等字段。适合用于构建「该公司最近申报了哪些文件」的监控清单:
import yfinance as yf t = yf.Ticker("NVDA") for filing in t.sec_filings: # 等价于 t.get_sec_filings() print(filing.get("date"), filing.get("type")) # exhibits 为 {类型: url} 字典 print(filing.get("exhibits"))六、底层数据通道:财报时序 API 与工程细节
理解上述接口的底层实现,有助于判断数据边界与异常场景。三大报表最终都汇聚到yfinance/scrapers/fundamentals.py的Financials类:
6.1 数据来源与时序端点
- 数据来自 Yahoo 的
fundamentals-timeseries时序端点(/ws/fundamentals-timeseries/v1/finance/timeseries/{symbol}),yfinance 明确注释选择该通道是因为它返回的数据与 Yahoo 官网展示一致,优于刮取QuoteSummaryStore(yfinance/scrapers/fundamentals.py); - 请求的科目键(如
TotalRevenue、NetIncome、TotalAssets)集中定义在 yfinance/const.py 的fundamentals_keys中,分为financials(利润表)、balance-sheet、cash-flow三组,其中利润表在 Yahoo 内部存储键为financials,需要做一次键名映射(yfinance/scrapers/fundamentals.py); - 时间范围限制:无论
period1如何设置,Yahoo 最多返回 4 个年度或 5 个季度的数据,start_dt固定为 2016-12-31(yfinance/scrapers/fundamentals.py); "yearly"在请求层被翻译为"annual"前缀(annualTotalRevenue等),"quarterly"与"trailing"保持原样(yfinance/scrapers/fundamentals.py)。
6.2 结果缓存
Financials类为每个freq维护独立的缓存字典(_income_time_series、_balance_sheet_time_series、_cash_flow_time_series),同一次会话内重复访问同一频率不会重复发起网络请求(yfinance/scrapers/fundamentals.py)。
6.3 分块请求回退机制(WSL2 / 受限代理适配)
这是一个值得关注的工程细节:拼接全部科目键的单条 URL 可能超过约 2KB,在 WSL2 的 NAT 或受限代理环境下会被静默丢弃。因此实现做了两层处理:
- 定义
_CHUNK_KEYS = 60,即每个分块最多 60 个科目键(yfinance/scrapers/fundamentals.py); - 默认先尝试单条长 URL(快速路径),失败后自动切换为分块请求,并通过
YfData.fundamentals_use_chunked标志粘性记住该失败状态,避免在遍历多个 ticker 时每个都浪费一次超时;若分块也失败则回滚标志并重新抛出(yfinance/scrapers/fundamentals.py)。
仓库测试专门覆盖了该回退场景,如 tests/test_ticker.py 的test_balance_sheet_chunked_fallback_on_timeout与test_cash_flow_chunked_fallback_on_timeout。
6.4 异常处理策略
_fetch_time_series()捕获到建表异常时,默认通过YfConfig.debug.hide_exceptions决定是否抛出;开启调试隐藏后仅记录错误日志并返回空DataFrame(yfinance/scrapers/fundamentals.py)。也就是说,某些 ticker 财报数据不可得时,接口可能静默返回空表,调用方应自行判空。
七、最佳实践与注意事项汇总
综合源码与测试,使用 Financials 系列接口时建议遵循以下要点:
- 优先使用属性形态:
income_stmt、balance_sheet、cashflow、calendar、earnings_dates、sec_filings无需记忆参数,且内部已做pretty=True格式化与结果缓存。 - TTM 仅限利润表与现金流量表:需要近 12 个月数据用
ttm_income_stmt/ttm_cashflow,且注意 TTM 表只有最新一列。 - 远离
earnings:该接口已废弃并固定返回None,净利润请从income_stmt的Net Income行读取。 get_earnings_dates的limit不要超过 100,否则直接抛ValueError;offset语义从 0 开始(未来预期起)。- 注意静默空表:财报时序通道对部分 ticker 可能返回空,
YfConfig.debug.hide_exceptions开启时异常被吞掉,建议对返回结果做df.empty判空。 - 理解数据边界:年度最多 4 年、季度最多 5 期,且起始时间不早于 2016 年底;需要更长历史请配合
Ticker.history()或download()等其他数据通道。 calendar与earnings_dates语义不同:calendar给出单只股票未来事件与分析师预期区间(dict),earnings_dates给出逐期盈余公告日期与预期/实际 EPS 对比(DataFrame),按需选用。
八、扩展阅读
- doc/source/reference/yfinance.financials.rst:本文所依据的 API Reference 原始页面;
- doc/source/reference/index.rst:yfinance 全部公开 API 索引,
Ticker与download等入口一览; - yfinance/base.py:三大报表与盈余方法的具体实现;
- yfinance/ticker.py:属性形态的封装与历史别名;
- yfinance/scrapers/fundamentals.py:财报时序数据抓取、分块回退与缓存;
- yfinance/scrapers/quote.py:
calendar与sec_filings的数据来源; - yfinance/const.py:财报科目键(
fundamentals_keys)完整清单; - tests/test_ticker.py:各接口的字段与行为断言,可作为使用预期参考。
【免费下载链接】yfinanceDownload market data from Yahoo! Finance's API项目地址: https://gitcode.com/GitHub_Trending/yf/yfinance
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考