第 1 章 · 03 yfinance 免费数据三件套:行情/期权/财报(对应 QS046)


文档摘要

第 1 章 · 03 yfinance 免费数据三件套:行情/期权/财报(对应 QS046) 速查摘要: 是最易上手的免费金融数据源——一行 ,无需注册 API key、无需 OpenBB 这套庞然大物,就能拉到股票行情(OHLCV)、期权链(calls/puts)、财务报表三大类数据。本节对 AAPL/MSFT/GOOGL 三只科技股批量拉取这三类数据,再用一套数据清洗模板(选列 + astype 强制类型 + 加 Symbol 标签列 + dropna + concat)把它们整理成统一的标准 DataFrame,是"免费数据获取"最实用的主角脚本。 涉及脚本:原项目 QS046-download-free-market-data/01downloadfreemarketdata.

第 1 章 · 03 yfinance 免费数据三件套:行情/期权/财报(对应 QS046)

速查摘要:yfinance 是最易上手的免费金融数据源——一行 pip install yfinance,无需注册 API key、无需 OpenBB 这套庞然大物,就能拉到股票行情(OHLCV)、期权链(calls/puts)、财务报表三大类数据。本节对 AAPL/MSFT/GOOGL 三只科技股批量拉取这三类数据,再用一套数据清洗模板(选列 + astype 强制类型 + 加 Symbol 标签列 + dropna + concat)把它们整理成统一的标准 DataFrame,是"免费数据获取"最实用的主角脚本。

涉及脚本:原项目 QS046-download-free-market-data/01_download_free_market_data.py(约 80 行 Python)

⚠️ 注意:yfinance 不依赖 OpenBB,独立可跑,是本章对环境要求最低的脚本。但它本质上是"逆向"雅虎财经网页接口的非官方库,接口随时可能因雅虎改版而失效——稳定性不如付费 API,但免费、零门槛、覆盖全球市场。财报返回的 DataFrame 默认是"行=指标、列=日期",要 .transpose() 转置才能按公司逐行整理。

工具与原理

yfinance 的三个核心入口

yfinance 围绕 Ticker 对象组织,一个 ticker 对应一只股票:

  • Ticker.history(period="1y"):历史 OHLCV(开高低收成交量),period 可选 1mo/3mo/1y/5y/max 等。返回行=日期、列=Open/High/Low/Close/Volume 的 DataFrame。
  • Ticker.option_chain():期权链。返回一个含 .calls.puts 两个 DataFrame 的对象,字段包括合约代号 contractSymbol、行权价 strike、最新价 lastPrice、买一 bid、卖一 ask、成交量 volume、未平仓量 openInterest。期权数据反映市场对未来的预期(波动率、价格区间)。
  • Ticker.financials:年度财务报表(损益表)。返回的 DataFrame 默认是"行=财务指标(如 Total Revenue、Net Income)、列=报告日期",每只股票一张表。

三类数据的金融含义

  • 行情(OHLCV):最基础的数据,做技术分析、算指标、回测策略都靠它。
  • 期权链:期权价格隐含了市场对未来波动率的预期(可用 Black-Scholes 反推隐含波动率 IV);openInterest(未平仓量)高的行权价往往是市场认为的"关键价位"(支撑/阻力)。
  • 财务报表:基本面分析的原料。营收、净利润的增长率反映公司成长性,横向对比 AAPL/MSFT/GOOGL 能看出谁的基本面更强。

数据清洗模板(本节核心)

API 返回的原始 DataFrame 有几个通病:列太多(含 Dividends/Stock Splits 等用不上的列)、类型混乱(数值列可能存成 object)、多只股票数据无法区分来源。本节给出一套可复用的四步清洗模板:

  1. 选列:只保留需要的列(如 OHLCV 五列)。
  2. astype 强制类型:把每列统一转成 float,避免 object 类型导致后续运算报错。
  3. 加 Symbol 列:给每行打上股票代码标签,这样多只股票 concat 后还能区分。
  4. dropna:丢掉缺失值,保证后续分析干净。

这套模板适用于几乎所有"多标的 + 多类数据"的批量整理场景,值得背下来。

脚本精读

第一步:批量拉三类数据(12-20 行)

stock_symbols = ["AAPL", "MSFT", "GOOGL"] market_data = { symbol: yf.Ticker(symbol).history(period="1y") for symbol in stock_symbols } options_data = {symbol: yf.Ticker(symbol).option_chain() for symbol in stock_symbols} financials_data = {symbol: yf.Ticker(symbol).financials for symbol in stock_symbols}

要点:

  • 用字典推导 + 循环批量拉数据,{symbol: Ticker(symbol).history(...) for symbol in stock_symbols} 一次拿到三只股票的行情,key 是代码、value 是 DataFrame。
  • 注意每只股票重新构造 Ticker 对象(三行各构造一次)——虽然能复用同一个 Ticker 对象,但这样写更直白、可读性高。
  • option_chain() 不传参,默认返回最近到期月份的期权链;传 expiration="2024-12-20" 可指定到期日。

第二步:清洗行情数据(23-31 行)

standardized_market_data = [] for symbol, df in market_data.items(): if not df.empty: df = df[["Open", "High", "Low", "Close", "Volume"]] df = df.dropna() df = df.astype(float) df["Symbol"] = symbol standardized_market_data.append(df) market_df = pd.concat(standardized_market_data).reset_index()

四步模板的完整体现:

  1. df[["Open", "High", "Low", "Close", "Volume"]] 选列,丢掉 Dividends、Stock Splits 等无关列。
  2. df.dropna() 清缺失。
  3. df.astype(float) 强制把所有列转 float。这一步很关键——history() 返回的列虽然看起来是数值,但有时 Dividends/Splits 列会混入 int 或 object,统一成 float 后续算指标、画图才不会出错。
  4. df["Symbol"] = symbol 打标签,标记每行属于哪只股票。
  5. pd.concat(standardized_market_data).reset_index() 把多只股票的 DataFrame 纵向拼接成长表,reset_index() 把日期从索引变成普通列(因为不同股票的日期索引会冲突,变成长表更通用)。

这种"一行一只股票一天"的长表(Long Format)是 pandas 推荐的整洁数据(Tidy Data)格式,适合后续 groupby、pivot。

第三步:清洗期权数据(34-65 行)

standardized_options_data = [] for symbol, option_chain in options_data.items(): calls = option_chain.calls puts = option_chain.puts for opt_type, opt_df in [("call", calls), ("put", puts)]: if not opt_df.empty: opt_df = opt_df[ [ "contractSymbol", "strike", "lastPrice", "bid", "ask", "volume", "openInterest", ] ] opt_df = opt_df.dropna() opt_df = opt_df.astype( { "strike": float, "lastPrice": float, "bid": float, "ask": float, "volume": float, "openInterest": float, } ) opt_df["Type"] = opt_type opt_df["Symbol"] = symbol standardized_options_data.append(opt_df) options_df = pd.concat(standardized_options_data).reset_index(drop=True)

期权清洗比行情多两个细节:

  • calls 和 puts 分开处理,用 [("call", calls), ("put", puts)] 元组列表复用同一段清洗逻辑——避免重复代码的常用模式。
  • astype({...}) 用字典批量转多列:不同列类型转换规则不同,传字典可一次性指定每列目标类型,比逐列写简洁。
  • 打两个标签列:Type(call/put)+ Symbol(股票代码),concat 后能按这两个维度筛选。

reset_index(drop=True)drop=True 表示丢弃原索引直接重编号,不像行情那样需要把日期保留成列。

第四步:清洗财报(68-75 行)

standardized_financials_data = [] for symbol, df in financials_data.items(): if not df.empty: df = df.transpose() df["Symbol"] = symbol df = df.dropna(axis=1, how="all") standardized_financials_data.append(df) financials_df = pd.concat(standardized_financials_data).reset_index()

关键操作——df.transpose() 转置:financials 默认"行=指标、列=日期",但我们要"一行一只股票、列=各指标"才能跨公司 concat。.transpose() 行列互换,加 Symbol 列后 concat 成长表。

dropna(axis=1, how="all") 删掉全空的指标列——有些财务项在某些公司不存在(比如研发费用),整列 NaN 的删掉。

第五步:最终去缺(78-81 行)

if market_df.isnull().values.any(): market_df = market_df.dropna() if options_df.isnull().values.any(): options_df = options_df.dropna()

兜底清洗——isnull().values.any() 先检查整张表有没有任何缺失,有再 dropna。这是防御性写法,确保最终三张表都干净。

关键技巧

技巧一:transpose() 处理财务报表。这是 yfinance 财报数据的标准操作:API 默认"行=指标、列=日期"是为单只股票查看方便,但跨公司对比时要先 transpose 成"行=日期、列=指标",再加 Symbol 列 concat 成长表。规律:**API 返回的"天然形状"未必是分析要的形状,转置是家常便饭**。

技巧二:astype(dict) 批量转多列类型。当不同列要转不同类型(有的转 float、有的转 int、有的转 str),传字典 astype({"strike": float, "volume": float}) 一次性搞定,比逐列赋值优雅,也比 astype(float) 全转更安全(能跳过不该转的列)。

技巧三:加 Symbol 列让多标的 concat 不丢身份。批量整理多只股票数据时,concat 前先给每个子表加 Symbol = symbol 列,这样拼起来后还能用 df[df.Symbol == "AAPL"] 筛选。否则多只股票数据混在一起无法区分,是新手最常犯的错。

技巧四:for opt_type, opt_df in [("call", calls), ("put", puts)] 元组列表复用逻辑。把"标识 + 数据"打包成元组列表,一次循环处理多个变体(call/put、买/卖、多空),是消除重复代码的利器,比写两遍几乎相同的代码清晰得多。

技巧五:长表(Long Format)是整洁数据。多标的场景下,"一行一只股票一天/一个合约/一个报告期"的长表比宽表更通用——支持 groupby、pivot、merge,符合 Hadley Wickham 的 Tidy Data 原则。

💡 速查要点:yfinance 三件套(history/option_chain/financials)是免费拉数据的主力。清洗模板四步走——选列、astype、加 Symbol 标签、dropna——能把多只股票、多类数据整理成统一长表。财报务必 transpose() 转置后再跨公司 concat。

本节要点

  1. yfinance 零门槛:无需 API key、不依赖 OpenBB,pip install yfinance 即可,是免费数据源里最易上手的。
  2. 三件套:Ticker.history(period="1y") 行情、Ticker.option_chain() 期权链(calls+puts)、Ticker.financials 财报。
  3. 数据清洗四步模板:选列 → astype 强制类型 → 加 Symbol 标签 → dropna,适用于所有多标的批量整理。
  4. transpose() 转置财报:API 默认"行=指标、列=日期",转置后才能跨公司 concat 成长表。
  5. astype(dict) 批量转多列类型,比逐列写更优雅;长表(Long Format)是 Tidy Data 推荐格式。

作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U