调用pct_change()报错ValueError:获取美国总统任期标普500回报遇问题
问题分析与解决方案
报错原因
当你尝试下载的时间段内没有标普500数据(标普500指数1957年才正式推出,更早的总统任期根本没有该指数记录),yf.download()会返回空的Adj Close序列。此时调用pct_change()会触发ValueError: attempt to get argmax of an empty sequence——空序列无法计算涨跌幅。
解决步骤
- 前置检查数据是否为空:计算回报前先判断下载的
sp500_data是否有内容,直接跳过无记录的总统。 - 修正累积回报的填充逻辑:原代码中
fillna(axis=1)是错误的(Adj Close是Series,没有列轴),应该用fillna(1)填充第一个交易日的NaN值(初始累积回报为1,对应投入1元无涨跌的情况)。 - 标记无记录的总统:单独记录这些总统,方便后续区分。
修改后的代码
import datetime import yfinance as yf # 处理总统任期日期格式 presidents['Start'] = presidents['Start'].apply(lambda x: datetime.datetime.strptime(x, "%B %d, %Y").strftime("%Y-%m-%d")) presidents['End'] = presidents['End'][:-1].apply(lambda x: datetime.datetime.strptime(x, "%B %d, %Y").strftime("%Y-%m-%d")) presidents['End'].iloc[-1] = datetime.datetime.now().strftime("%Y-%m-%d") cumulative_returns = {} no_sp500_records = [] for index, row in presidents.iterrows(): party = row['Party'] president = row['Name'] start_date = row['Start'] end_date = row['End'] sp500_data = yf.download('^GSPC', start_date, end_date, progress=False)['Adj Close'] # 检查是否获取到有效数据 if sp500_data.empty: no_sp500_records.append(president) cumulative_returns[president] = { 'cumulative_returns': None, 'party': party, 'status': '无标普500记录' } continue # 计算日度回报与累积回报 returns = sp500_data.pct_change() c_ret = (1 + returns).cumprod().fillna(1) cumulative_returns[president] = { 'cumulative_returns': c_ret, 'party': party, 'status': '有记录' } # 输出无记录的总统列表 print("无标普500记录的总统:", no_sp500_records)
关键说明
- 空数据拦截:通过
sp500_data.empty快速识别无数据场景,避免后续计算触发报错。 - 累积回报修正:
fillna(1)确保第一个交易日的累积回报初始值正确,符合“初始投入1元”的逻辑。 - 状态区分:新增
status字段,清晰标记每个总统对应的指数数据状态,方便后续分析。
内容的提问来源于stack exchange,提问作者ADV_1977
相关产品推荐
相关产品推荐

