yfinance脚本yf.download列应用故障修复及期权链历史数据咨询
问题背景
我基于yfinance库编写了脚本,流程为:下载SPY股票行情数据,获取季度期权链,计算并添加上下行权价、上下期权合约代码列。但执行倒数第二行Stocks['Call_lower_price'] = Stocks['Call_lower_ticker'].apply(yf.download(['Call_lower_ticker'], start=Stocks.index)['Close'].iloc[0])时出现错误,报错信息如下:
[*********************100%%**********************] 1 of 1 completed [*********************100%%**********************] 1 of 1 completed **1 Failed download: ['CALL_LOWER_TICKER']: ValueError('The truth value of a DatetimeIndex is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().') ---------------------------------------------------------------------------** IndexError Traceback (most recent call last) File <timed exec>:19 File C:\ProgramData\anaconda3\Lib\site-packages\pandas\core\indexing.py:1191, in _LocationIndexer.__getitem__(self, key) 1189 maybe_callable = com.apply_if_callable(key, self.obj) 1190 maybe_callable = self._check_deprecated_callable_usage(key, maybe_callable) -> 1191 return self._getitem_axis(maybe_callable, axis=axis) File C:\ProgramData\anaconda3\Lib\site-packages\pandas\core\indexing.py:1752, in _iLocIndexer._getitem_axis(self, key, axis) 1749 raise TypeError("Cannot index by location index with a non-integer key") 1751 # validate the location -> 1752 self._validate_integer(key, axis) 1754 return self.obj._ixs(key, axis=axis) File C:\ProgramData\anaconda3\Lib\site-packages\pandas\core\indexing.py:1685, in _iLocIndexer._validate_integer(self, key, axis) 1683 len_axis = len(self.obj._get_axis(axis)) 1684 if key >= len_axis or key < -len_axis: -> 1685 raise IndexError("single positional indexer is out-of-bounds") IndexError: single positional indexer is out-of-bounds
技术问题
- 如何修改代码使该行yf.download函数正常工作?
- 是否可以下载yf.option.chain的历史数据?
完整代码
%%time import yfinance as yf import pandas as pd import warnings import datetime warnings.filterwarnings("ignore", message="The 'unit' keyword in TimedeltaIndex construction is deprecated and will be removed in a future version. Use pd.to_timedelta instead.", category=FutureWarning, module="yfinance.utils") Stocks=yf.download('SPY', period="1y", interval="1d", group_by='ticker') stock = yf.Ticker('SPY') Expirations = stock.options options_chain = stock.option_chain('2024-09-20') Calls_desk=options_chain.calls Stocks['110_for_Call'] = Stocks['Close']*1.1 Stocks['Call_lower_strike'] = Stocks['110_for_Call'].apply(lambda x: Calls_desk.iloc[Calls_desk[Calls_desk['strike'] < x]['strike'].idxmax()]['strike']) Stocks['Call_upper_strike'] = Stocks['110_for_Call'].apply(lambda x: Calls_desk.iloc[Calls_desk[Calls_desk['strike'] > x]['strike'].idxmin()]['strike']) Stocks['Call_lower_ticker'] = Stocks['110_for_Call'].apply(lambda x: Calls_desk.iloc[Calls_desk[Calls_desk['strike'] < x]['strike'].idxmax()]['contractSymbol']) Stocks['Call_upper_ticker'] = Stocks['110_for_Call'].apply(lambda x: Calls_desk.iloc[Calls_desk[Calls_desk['strike'] > x]['strike'].idxmin()]['contractSymbol']) Stocks['Call_lower_price'] = Stocks['Call_lower_ticker'].apply(yf.download(['Call_lower_ticker'], start=Stocks.index)['Close'].iloc[0]) Stocks
解答
问题1:修复yf.download调用错误
原代码错误有两个核心原因:
apply未用lambda接收每行的合约代码,导致传入固定字符串'Call_lower_ticker'而非实际合约代码start=Stocks.index传入整个DataFrame索引,引发DatetimeIndex歧义错误
方案1:逐行处理(简单直接)
用lambda接收每行的合约代码和对应日期,同时处理下载失败的情况:
def get_option_price(contract_ticker, row_date): try: data = yf.download(contract_ticker, start=row_date, period="1d") return data['Close'].iloc[0] if not data.empty else None except Exception as e: print(f"下载{contract_ticker}失败: {e}") return None Stocks['Call_lower_price'] = Stocks.apply( lambda row: get_option_price(row['Call_lower_ticker'], row.name), axis=1 )
方案2:批量下载(效率更高)
先收集所有唯一合约代码批量下载,再映射回DataFrame,避免重复请求:
# 收集唯一合约代码 unique_tickers = Stocks['Call_lower_ticker'].unique() # 批量下载所有合约的历史数据 all_option_data = yf.download(unique_tickers, start=Stocks.index.min(), end=Stocks.index.max())['Close'] # 映射每行对应的期权价格 Stocks['Call_lower_price'] = Stocks.apply( lambda row: all_option_data.loc[row.name, row['Call_lower_ticker']] if row['Call_lower_ticker'] in all_option_data.columns else None, axis=1 )
问题2:yfinance是否支持下载历史期权链数据
yfinance不支持直接获取历史期权链数据,它只能获取当前有效的未到期合约期权链。如果需要历史期权链数据,有两种替代方案:
- 使用专业金融数据API(如Interactive Brokers、Polygon.io等),这类服务商提供历史期权数据接口
- 自行定期抓取并存储当前期权链数据,构建私人历史数据库(适合长期需求场景)
内容的提问来源于stack exchange,提问作者Vasiliy Deryuga
相关产品推荐
相关产品推荐

