yfinance 使用指南:用 Python 优雅地下载 Yahoo! Finance 市场数据
【免费下载链接】yfinanceDownload market data from Yahoo! Finance's API项目地址: https://gitcode.com/GitHub_Trending/yf/yfinance
导读
yfinance 是一个面向 Yahoo! Finance 公开 API 的 Python 市场数据下载库,它提供了一套 Pythonic(符合 Python 习惯)的接口,让你可以用几行代码获取股票历史行情、基本面数据、期权链、实时行情流、行业板块信息乃至市场筛选结果。本文以仓库 README.md 为骨架,结合仓库内的官方示例(doc/source/reference/examples/)与源码实现,完整讲解 yfinance 的安装方式、八大核心组件(Ticker、Tickers、download、Market、WebSocket、Search、Sector/Industry、Screener)的用法,以及Calendars、Auth、代理等进阶能力,帮助你快速搭建自己的行情数据管道。
一、yfinance 是什么
yfinance提供了一种 Pythonic 的方式来从 Yahoo! Finance 获取金融与市场数据。它的核心设计理念是:以面向对象的方式封装 Yahoo 的公开 API,让"取数"这件事足够简单直接——你不需要手写 HTTP 请求、处理 cookie 与 crumb 校验,只需要创建对象、访问属性即可。
从源码的顶层导出(yfinance/init.py)可以看到,yfinance 对外开放的能力相当完整:
| 顶层导出 | 类型 | 用途 |
|---|---|---|
Ticker | 类 | 单个标的全量数据(历史、财务、期权等) |
Tickers | 类 | 批量管理多个标的 |
download | 函数 | 一键下载多个标的的历史行情 |
Market/MarketRegion | 类/枚举 | 市场状态与摘要信息 |
WebSocket/AsyncWebSocket | 类 | 实时行情流(同步/异步) |
Search | 类 | 报价与新闻搜索 |
Lookup | 类 | 标的查找 |
Sector/Industry | 类 | 行业板块信息 |
EquityQuery/FundQuery/ETFQuery/screen | 类/函数 | 构建查询并筛选市场 |
Calendars | 类 | 财报、IPO、拆股等事件日历 |
Auth | 类 | 登录态管理与订阅层级查询 |
config/set_config | 配置 | 全局配置(代理、重试等) |
这些正是 README 中 "Main components"(主要组件)一节的完整落地。
二、安装
从 PyPI 安装 yfinance 非常简单:
$ pip install yfinance安装后,在 Python 中即可直接导入:
import yfinance as yf需要说明两点:
- 依赖说明:yfinance 默认依赖
curl_cffi作为 HTTP 传输层。如果希望不使用curl_cffi而回退到requests,可以参考仓库文档 doc/source/advanced/install.rst 中的高级安装说明进行配置。 - 底层会话约束:从源码 yfinance/data.py 可以看到,yfinance 通过
YfData单例管理全局请求会话。缓存型会话(如requests_cache)以及非 curl_cffi/requests 的会话类型会被直接拒绝(抛出YFDataException),原因是缓存会破坏数据一致性——yfinance 自己就内置了 crumb、cookie 与响应缓存机制。
三、核心组件一:Ticker——单个标的数据中心
Ticker是 yfinance 最常用的入口,封装了单个股票、ETF、基金或指数的几乎所有公开数据。官方示例(doc/source/reference/examples/ticker.py)展示了它的典型用法:
import yfinance as yf dat = yf.Ticker("MSFT") # 获取历史行情数据 dat.history(period='1mo') # 期权链(取第一个到期日) dat.option_chain(dat.options[0]).calls # 财务报表 dat.balance_sheet dat.quarterly_income_stmt # 日历信息(财报日期、除息日等) dat.calendar # 综合信息(市值、PE、行业等) dat.info # 分析师目标价 dat.analyst_price_targets # WebSocket 实时行情 dat.live()从源码结构看(yfinance/ticker.py),Ticker继承自TickerBase(yfinance/base.py),其中:
history():拉取历史 OHLCV 数据,支持period(如1mo)或start/end日期区间两种模式,返回 pandas DataFrame;option_chain(date=None, tz=None):通过 Yahoo 的/v7/finance/options/{ticker}接口获取期权数据,返回包含calls、puts、underlying三个字段的 namedtuple。若指定的到期日不在dat.options列表中,会抛出ValueError并列出可用到期日(yfinance/ticker.py);- 属性访问:
info、calendar、analyst_price_targets、major_holders、institutional_holders、isin等均为延迟加载属性,首次访问时才会真正发起网络请求。
3.1 常见属性速查
除示例中的属性外,Ticker还暴露了大量常用数据接口(见 yfinance/ticker.py 与 yfinance/base.py):
| 属性/方法 | 说明 |
|---|---|
history() | 历史行情(OHLCV),可选actions=True附带分红拆股 |
actions/dividends/splits/capital_gains | 公司行为数据 |
financials/income_stmt/balance_sheet/cashflow | 三大财务报表(及季度版quarterly_*) |
info | 综合行情快照(市值、PE、52 周高低等) |
analyst_price_targets/recommendations | 分析师评级与目标价 |
calendar | 财报与除息日历 |
funds_data | 基金/ETF 专属数据(见后文) |
live() | 订阅该标的的 WebSocket 实时行情 |
get_isin() | 查询 ISIN 代码 |
四、核心组件二:Tickers——批量管理多个标的
当需要同时跟踪多个标的时,使用Tickers可以一次性创建多个Ticker对象,并按代码访问(官方示例 doc/source/reference/examples/tickers.py):
import yfinance as yf tickers = yf.Tickers('msft aapl goog') # 通过 .tickers 字典按代码访问(自动转为大写) tickers.tickers['MSFT'].info tickers.tickers['AAPL'].history(period="1mo") tickers.tickers['GOOG'].actions # WebSocket 实时行情 tickers.live()从源码看(yfinance/tickers.py),Tickers内部还封装了download()方法,本质上委托给multi.download(),参数与下文download函数完全一致——也就是说,Tickers既是对象容器,也是批量取数的便捷入口。
五、核心组件三:download——一键批量下载历史行情
yf.download()是 yfinance 最经典、最常用的函数级 API,一行代码即可下载多标的历史数据:
import yfinance as yf data = yf.download("SPY AAPL", period="1mo")返回结果是一个多级索引(MultiIndex)的 pandas DataFrame,默认按列(group_by='column')组织,即顶层为价格字段(Open/High/Low/Close/Volume),下一层为标的代码。
5.1 完整参数详解
download()的完整签名定义在 yfinance/multi.py,所有参数说明如下:
| 参数 | 类型/默认值 | 说明 |
|---|---|---|
tickers | str, list | 要下载的标的列表。字符串可用空格或逗号分隔,如"SPY AAPL"或"SPY, AAPL";也可传 list。支持 ISIN(如"US0378331005",内部会自动转换为 ticker) |
period | str,默认'1mo' | 有效区间:1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max。默认在未指定start/end时为'1mo'。period与start/end二选一 |
interval | str,默认"1d" | 有效周期:1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo。分钟级日内数据最多回溯 60 天。注意:30m数据实际是从 Yahoo 拉取15m后重采样得到的,以规避 Yahoo API 的 bug |
start/end | str(YYYY-MM-DD)或 datetime | 起始日期包含(如start="2020-01-01"的首个数据点就在当天);结束日期不包含(如end="2023-01-01"的最后数据点是2022-12-31)。start默认 99 年前,end默认当前 |
group_by | str,默认'column' | 按'ticker'或'column'分组组织 MultiIndex |
prepost | bool,默认False | 是否包含盘前盘后数据 |
auto_adjust | bool,默认True | 是否自动复权所有 OHLC 数据 |
back_adjust | bool,默认False | 是否使用后复权 |
repair | bool,默认False | 是否检测"货币单位 100 倍错乱"(currency unit 100x mixups)并尝试修复——这是 yfinance 的特色数据修复功能,仓库为其准备了大量测试用例(见 tests/test_price_repair.py 与 tests/data/ 下的*-fixed.csv对照数据) |
keepna | bool,默认False | 是否保留 Yahoo 返回的 NaN 行 |
actions | bool,默认False | 是否同时下载分红与拆股数据 |
threads | bool / int,默认True | 批量下载使用的线程数。True时自动取min(标的数据, CPU 核数 * 2)(见 yfinance/multi.py) |
ignore_tz | bool | 合并不同时区数据时是否忽略时区部分。默认取决于interval:日内数据(分钟/小时级)为False,日线及以上为True;同时控制返回索引的时区属性 |
rounding | bool,默认False | 是否将数值四舍五入到 2 位小数 |
timeout | None 或 float,默认10 | 请求超时秒数(支持小数,如0.01) |
session | Session | 自定义请求会话对象 |
multi_level_index | bool,默认True | 是否总是返回 MultiIndex DataFrame |
5.2 底层执行流程
从源码看(yfinance/multi.py),download()的执行分为几步:
- 将字符串 tickers 统一转为大写并去重,ISIN 自动转换为 ticker;
- 若开启
threads,通过_multitasking并行发起下载,并显示进度条; - 所有标的数据下载完成后,统一对齐时间索引并合并为 MultiIndex DataFrame。
调试提示:当开启 DEBUG 日志时,yfinance 会自动关闭多线程和进度条(yfinance/multi.py),避免日志交错,这在排查问题时非常有用。
六、核心组件四:Market——市场状态与摘要
Market用于获取某个市场的整体状态(开盘/收盘)与摘要信息。官方示例(doc/source/reference/examples/market.py):
import yfinance as yf EUROPE = yf.Market("EUROPE") status = EUROPE.status # 市场当前状态 summary = EUROPE.summary # 市场摘要从源码看,市场区域由MarketRegion枚举定义(yfinance/init.py、yfinance/domain/market.py),Market接受区域名称(如"EUROPE")进行构造。该组件适合做"交易日判断"和"市场概况"类的应用——例如在交易策略启动前先检查目标市场是否处于交易时段。
七、核心组件五:WebSocket 与 AsyncWebSocket——实时行情流
yfinance 提供同步与异步两套 WebSocket 客户端,用于订阅实时行情(定价数据流)。官方示例提供了完整的两种写法(doc/source/reference/examples/live_sync.py、doc/source/reference/examples/live_async.py)。
7.1 同步版 WebSocket
import yfinance as yf # 定义消息回调 def message_handler(message): print("Received message:", message) # ======================= # 方式一:上下文管理器(推荐) # ======================= with yf.WebSocket() as ws: ws.subscribe(["AAPL", "BTC-USD"]) ws.listen(message_handler) # ======================= # 方式二:手动管理 # ======================= ws = yf.WebSocket() ws.subscribe(["AAPL", "BTC-USD"]) ws.listen(message_handler)7.2 异步版 AsyncWebSocket
import asyncio import yfinance as yf # 定义消息回调 def message_handler(message): print("Received message:", message) async def main(): # ======================= # 方式一:异步上下文管理器 # ======================= async with yf.AsyncWebSocket() as ws: await ws.subscribe(["AAPL", "BTC-USD"]) await ws.listen() # ======================= # 方式二:手动管理 # ======================= ws = yf.AsyncWebSocket() await ws.subscribe(["AAPL", "BTC-USD"]) await ws.listen() asyncio.run(main())从源码看(yfinance/live.py、yfinance/live.py),两个类均基于wss://streamer.finance.yahoo.com/?version=2端点,AsyncWebSocket继承自BaseWebSocket,二者 API 对齐(subscribe订阅代码列表、listen持续监听并回调消息)。注意示例中同时订阅了股票(AAPL)与加密货币(BTC-USD)代码,说明该流不局限于股票。
另外,Ticker.live()和Tickers.live()也封装了实时流入口(见 yfinance/base.py 与 yfinance/tickers.py),可以按对象粒度直接启动订阅。
八、核心组件六:Search——报价与新闻搜索
Search用于搜索 Yahoo Finance 中的报价(quotes)、新闻(news)与研究内容(research)。官方示例(doc/source/reference/examples/search.py):
import yfinance as yf # 获取报价列表 quotes = yf.Search("AAPL", max_results=10).quotes # 获取新闻列表 news = yf.Search("Google", news_count=10).news # 获取相关研究内容 research = yf.Search("apple", include_research=True).researchSearch的构造参数支持max_results(报价结果数量上限)、news_count(新闻数量)与include_research(是否包含研究内容),三个属性quotes、news、research分别对应三类结果(实现见 yfinance/search.py)。该组件适合做关键词驱动的投研信息聚合,例如按行业热点收集新闻。
九、核心组件七:Sector 与 Industry——行业板块信息
Sector与Industry分别封装 Yahoo 的行业板块数据。官方示例(doc/source/reference/examples/sector_industry.py):
import yfinance as yf tech = yf.Sector('technology') software = yf.Industry('software-infrastructure') # 公共信息(Sector 与 Industry 通用) tech.key tech.name tech.symbol tech.ticker # 与该板块关联的 Ticker 对象 tech.overview tech.top_companies tech.research_reports # Sector 独有信息 tech.top_etfs tech.top_mutual_funds tech.industries # Industry 独有信息 software.sector_key software.sector_name software.top_performing_companies software.top_growth_companies9.1 与 Ticker 双向联动
板块与个股之间可以互相转换(官方示例 doc/source/reference/examples/sector_industry_ticker.py):
import yfinance as yf # Ticker -> Sector 和 Industry msft = yf.Ticker('MSFT') tech = yf.Sector(msft.info.get('sectorKey')) software = yf.Industry(msft.info.get('industryKey')) # Sector/Industry -> Ticker(获取代表性标的) tech_ticker = tech.ticker tech_ticker.info software_ticker = software.ticker software_ticker.history()这个双向转换能力非常实用:你可以从任意个股出发拿到它所属的板块与行业,再借助top_companies、top_etfs、top_mutual_funds等属性扩展出"同板块候选池",从而构建行业轮动或同业对比的分析流程。相关实现位于 yfinance/domain/sector.py 与 yfinance/domain/industry.py。
十、核心组件八:EquityQuery 与 Screener——市场筛选
EquityQuery(以及FundQuery、ETFQuery)用于构建结构化筛选条件,screen()函数则执行筛选。从源码看(yfinance/screener/query.py):
- 值运算:
EQ(等于)、IS-IN(属于)、BTWN(介于)、GT(大于)、LT(小于)、GTE(大于等于)、LTE(小于等于); - 逻辑组合:
AND、OR。
例如,可以基于地区(region)、行业(sector)、交易所(exchange)等条件构造股票筛选器,然后通过 yfinance/screener/screener.py 中的screen(query, offset, size, sortField, sortAsc, ...)执行,返回符合条件的标的列表。该模块还预置了一批常用筛选查询(PREDEFINED_SCREENER_QUERIES,见 yfinance/init.py),可直接用于快速筛选"最活跃"、"涨幅榜"等场景(Calendars示例中就曾用到screen(query="MOST_ACTIVES"))。
十一、进阶能力:Calendars、FundsData、Auth 与代理
除了 README 列出的八大组件,yfinance 还提供了几项值得掌握的进阶能力。
11.1 Calendars——事件日历
Calendars提供财报、IPO、拆股、经济事件四类日历数据,并支持按市值、活跃度过滤(官方示例 doc/source/reference/examples/calendars.py):
import yfinance as yf from datetime import datetime, timedelta # 默认初始化(今天 + 7 天) calendar = yf.Calendars() # 只取今天之后 1 天的事件 tomorrow = datetime.now() + timedelta(days=1) calendar = yf.Calendars(end=tomorrow) # 默认查询:访问属性即触发数据获取 calendar.earnings_calendar calendar.ipo_info_calendar calendar.splits_calendar calendar.economic_events_calendar # 手动查询(带自定义参数) calendar.get_earnings_calendar( market_cap=100_000_000, # 过滤掉小市值公司 filter_most_active=True, # 只显示活跃交易标的(内部使用 screen(query="MOST_ACTIVES")) ) # 实战示例:找出临近发布但尚未披露财报的公司 today = datetime.now() is_friday = today.weekday() == 4 day_after_tomorrow = today + timedelta(days=4 if is_friday else 2) calendar = yf.Calendars(today, day_after_tomorrow) df = calendar.get_earnings_calendar(limit=100) unreported_df = df[df["Reported EPS"].isnull()]11.2 FundsData——基金/ETF 专属数据
对于 ETF 或共同基金标的,Ticker.funds_data提供持仓与运作信息(官方示例 doc/source/reference/examples/funds_data.py):
import yfinance as yf spy = yf.Ticker('SPY') data = spy.funds_data data.description # 基金描述 data.fund_overview # 基金概览 data.fund_operations # 运作信息 data.asset_classes # 资产类别 data.top_holdings # 前十大持仓 data.equity_holdings # 股票持仓明细 data.bond_holdings # 债券持仓明细 data.bond_ratings # 债券评级 data.sector_weightings # 行业权重该能力让 yfinance 从"股票工具"扩展到了"基金研究工具",相关实现位于 yfinance/scrapers/funds.py。
11.3 Auth——登录态与会话管理
Auth允许你将浏览器中获得的登录 Cookie 注入会话,从而以登录用户身份请求数据(官方示例 doc/source/reference/examples/auth.py):
import yfinance as yf import os auth = yf.Auth() # 设置从浏览器获取的登录 Cookie。该调用会存储、实时校验并返回登录结果。 if auth.set_login_cookies(os.getenv("COOKIE_T"), os.getenv("COOKIE_Y")): print("Logged in") else: print("Invalid or expired cookies") # 此后所有发往 Yahoo Finance 的请求都携带该登录态。 # 随时重新校验实时登录状态(每次调用都会重新查询,不做缓存)。 auth.check_login() # -> True / False # 查询账户的订阅层级。 auth.subscription_tier() # -> 'gold' / 'silver' / 'bronze' / 'free' / None # 访问用户信息。 auth.user # -> {'guid': ...} or None从源码看(yfinance/data.py),set_login_cookies会以线程安全的方式把T、Y两个 Cookie 写入全局会话,并清除旧 crumb(crumb 可能与匿名态不匹配),强制在下一请求重新生成与当前 Cookie 匹配的 crumb,从而让登录态干净生效。同时,会话的 cookie 策略切换(basic/csrf)在登录态下不会清空用户 Cookie 锅,避免"静默登出"(yfinance/data.py)。
11.4 代理(Proxy)支持
所有请求级接口都支持proxy参数(官方示例 doc/source/reference/examples/proxy.py):
import yfinance as yf msft = yf.Ticker("MSFT") msft.history(..., proxy="PROXY_SERVER") msft.get_actions(proxy="PROXY_SERVER") msft.get_dividends(proxy="PROXY_SERVER") msft.get_splits(proxy="PROXY_SERVER") msft.get_capital_gains(proxy="PROXY_SERVER") msft.get_balance_sheet(proxy="PROXY_SERVER") msft.get_cashflow(proxy="PROXY_SERVER") msft.option_chain(..., proxy="PROXY_SERVER")此外,也可以通过全局配置设置代理:yf.config.network.proxy = proxy(旧的yf.set_config(proxy=...)方式已被标记为弃用,见 yfinance/init.py)。底层实现会将字符串代理统一规范化为{"http": ..., "https": ...}字典后挂到会话上(yfinance/data.py)。
十二、底层架构:YfData 单例与缓存机制
理解 yfinance 的底层架构有助于你更好地使用它。从源码看(yfinance/data.py):
YfData是单例(通过SingletonMeta元类实现):整个进程共享一个请求会话、一份 cookie 和一份 crumb,这既保证了多线程并发下的数据一致性,也大幅提升了请求效率(cookie/crumb 只需获取一次)。- 自带响应缓存:
YfData通过lru_cache装饰器缓存数据(yfinance/data.py),把字典/列表参数冻结后作为缓存键,默认缓存容量为 64。 - cookie 策略自动切换:默认使用
basic策略,失败时回退到csrf(yfinance/data.py)。 - 瞬时错误重试:对
TimeoutError、ConnectionError等瞬时网络错误(yfinance/data.py),请求层会自动重试。
这正是上一节提到"缓存型会话会被拒绝"的原因:yfinance 已经内置了完整的缓存与重试链路,外部再叠加requests_cache反而会引入脏数据。
十三、调试与测试
排查问题时可以开启调试日志:
import yfinance as yf yf.enable_debug_mode()该函数由 yfinance/utils.py 提供,开启后能观察每次请求的 URL、cookie 策略切换与重试过程(yfinance/data.py 中的日志即由此输出)。
仓库自带完整测试套件(tests/),其中与下载、价格修复相关的重点测试文件包括:
- tests/test_prices.py——历史行情下载与复权逻辑;
- tests/test_price_repair.py——
repair=True的价格修复逻辑,配套 tests/data/ 目录下大量*-bad-*.csv/*-fixed.csv成对数据,覆盖了"分红错乱"(bad-div)、"拆股错乱"(bad-stock-split)、"100 倍单位错乱"(100x-error)等真实场景; - tests/test_ticker.py、tests/test_multi.py、tests/test_live.py——分别覆盖
Ticker、批量下载与 WebSocket 功能。
如果你想运行测试验证环境,可按 doc/source/development/running.rst 与 doc/source/development/testing.rst 中的说明操作。
十四、法律与合规提示
最后必须强调 README 中明确说明的事项:
- 商标声明:Yahoo!、Y!Finance 与 Yahoo! finance 是 Yahoo, Inc. 的注册商标。
- 非官方工具:yfinance 与 Yahoo, Inc. 没有任何从属、背书或审查关系。它是一个使用 Yahoo 公开 API 的开源工具,仅用于研究与教育目的。
- 使用条款:在使用下载的数据前,你应当自行查阅 Yahoo! 的服务条款,确认你对所下载数据的使用权利。Yahoo! Finance API 仅限个人用途。
- 开源协议:yfinance 基于Apache Software License分发,详见 LICENSE.txt。
如果你希望参与社区共建、提交 Bug 报告或贡献代码,可以参考 CONTRIBUTING.md 中的指引。
【免费下载链接】yfinanceDownload market data from Yahoo! Finance's API项目地址: https://gitcode.com/GitHub_Trending/yf/yfinance
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考