使用Yahoo_fin/YahooFinancials获取美股历史数据遇错求助
让我们一步步解决你的问题,帮你按时完成项目:
问题解决方案
一、搞定YahooFinancials的KeyError/TypeError
你的报错核心原因是Yahoo的API接口已经更新,但旧版本的yahoofinancials包没跟上适配。而且就算你过滤了后缀,仍可能存在无效/已退市的股票代码,进一步触发异常。直接换用维护更活跃的yfinance包就好,它对Yahoo当前的接口兼容性更好。
二、消除yfinance的PerformanceWarning
循环逐个给DataFrame加列会导致数据碎片化,触发性能警告。最佳解决方式是:
- 要么用yfinance的批量下载功能,一次性拉取所有股票数据(效率最高)
- 要么先收集每只股票的Adj Close数据,最后用
pd.concat一次性合并成DataFrame
修正后的完整代码
import pandas as pd import numpy as np import yahoo_fin.stock_info as si import yfinance as yf import datetime as dt # 获取NASDAQ股票列表并过滤带无效后缀的代码 nasdaq = pd.DataFrame(si.tickers_nasdaq()) sym_set = set(nasdaq[0].values.tolist()) # 需要过滤的后缀集合 exclude_suffixes = {'W', 'R', 'P', 'Q'} # 过滤逻辑:排除长度>4且后缀在排除列表的代码 valid_tickers = [symbol for symbol in sym_set if not (len(symbol) > 4 and symbol[-1] in exclude_suffixes)] # 设置日期范围(最近30天) begin_date = dt.datetime.today() - dt.timedelta(30) end_date = dt.datetime.today() # 推荐方案:yfinance批量下载(效率最高,直接避免碎片化) prices = yf.download(valid_tickers, start=begin_date, end=end_date)['Adj Close'] # 备选方案:收集单股票数据后合并(可处理单股票下载失败的情况) # price_list = [] # for ticker in valid_tickers: # try: # # 获取单股票的Adj Close并重命名列 # adj_close = yf.download(ticker, start=begin_date, end=end_date)['Adj Close'].rename(ticker) # price_list.append(adj_close) # except Exception as e: # print(f"跳过无效代码 {ticker}:{str(e)}") # # 一次性合并所有列 # prices = pd.concat(price_list, axis=1) # 可选:删除完全没有数据的列(对应无法获取数据的股票) prices = prices.dropna(axis=1, how='all') # 查看结果 print(prices.head())
关键优化细节
- 简化过滤逻辑:用列表推导式替代原有的set循环,代码更简洁高效
- 批量下载替代循环:yfinance支持直接传入股票列表批量请求,内部做了优化,彻底避免数据碎片化问题
- 异常处理(备选):如果用备选方案,可以跳过下载失败的无效股票,保证整个流程不中断
- 空值清理:最后删除全空列,避免后续分析受无效数据影响
原代码问题解析
YahooFinancials报错:旧包依赖的Yahoo API端点已废弃,返回的数据结构完全变了,所以触发KeyError: 'timestamp';后续降级到网页抓取时,又因为页面结构更新出现TypeErroryfinance性能警告:循环中prices[stock] = ...本质是频繁调用DataFrame的insert操作,每次都会重构数据结构,导致内存碎片化,性能骤降。用批量下载或pd.concat就能彻底解决这个问题
内容的提问来源于stack exchange,提问作者Jabaker35
相关产品推荐
相关产品推荐

