Williams AD指标函数调用报错:Timestamp与int无法比较的解决方法
Williams AD指标函数报错解决办法
问题重现
使用实现William's Accumulation/Distribution指标的函数,传入yfinance获取的SPY股票数据(索引为Timestamp类型的DataFrame)时,调用williams_ad(df)触发以下错误:
TypeError: '>' not supported between instances of 'Timestamp' and 'int'
错误原因
函数中通过if index > 0判断是否为第一行之后的数据,但DataFrame的索引是Timestamp类型,无法直接与整数0进行比较,导致类型不匹配。
解决方案
方案1:使用位置索引替代标签索引
修改循环逻辑,通过enumerate获取迭代的位置序号,避免直接使用Timestamp索引进行判断,同时修复已弃用的set_value方法:
def williams_ad(data, high_col='High', low_col='Low', close_col='Close'): # 复制数据避免修改原DataFrame data_copy = data.copy() data_copy['williams_ad'] = 0.0 for pos, (index, row) in enumerate(data_copy.iterrows()): if pos > 0: prev_index = data_copy.index[pos-1] prev_value = data_copy.at[prev_index, 'williams_ad'] prev_close = data_copy.at[prev_index, close_col] if row[close_col] > prev_close: ad = row[close_col] - min(prev_close, row[low_col]) elif row[close_col] < prev_close: ad = row[close_col] - max(prev_close, row[high_col]) else: ad = 0.0 data_copy.at[index, 'williams_ad'] = ad + prev_value return data_copy
方案2:临时重置为整数索引
先将DataFrame索引重置为整数,计算完成后恢复原索引:
def williams_ad(data, high_col='High', low_col='Low', close_col='Close'): data_copy = data.copy().reset_index() data_copy['williams_ad'] = 0.0 for index, row in data_copy.iterrows(): if index > 0: prev_value = data_copy.at[index-1, 'williams_ad'] prev_close = data_copy.at[index-1, close_col] if row[close_col] > prev_close: ad = row[close_col] - min(prev_close, row[low_col]) elif row[close_col] < prev_close: ad = row[close_col] - max(prev_close, row[high_col]) else: ad = 0.0 data_copy.at[index, 'williams_ad'] = ad + prev_value # 恢复原索引 return data_copy.set_index(data.index.name)
方案3:Pandas向量化操作(高效推荐)
用向量化运算替代循环,大幅提升处理大数据的效率:
import numpy as np import pandas as pd def williams_ad(data, high_col='High', low_col='Low', close_col='Close'): data_copy = data.copy() prev_close = data_copy[close_col].shift(1) # 计算AD增量 cond_up = data_copy[close_col] > prev_close cond_down = data_copy[close_col] < prev_close ad = pd.Series(0.0, index=data_copy.index) ad[cond_up] = data_copy.loc[cond_up, close_col] - np.minimum(prev_close[cond_up], data_copy.loc[cond_up, low_col]) ad[cond_down] = data_copy.loc[cond_down, close_col] - np.maximum(prev_close[cond_down], data_copy.loc[cond_down, high_col]) # 累加得到最终Williams AD值 data_copy['williams_ad'] = ad.cumsum() return data_copy
验证
调用修改后的函数即可正常运行:
import pandas as pd import yfinance as yF df = yF.download(tickers="SPY", period="5y", interval="1d", prepost=False, repair=True) result_df = williams_ad(df) print(result_df['williams_ad'].tail())
内容的提问来源于stack exchange,提问作者prashanth manohar
相关产品推荐
相关产品推荐

