计算滚动水下收益触发TypeError:无法将Series转换为float
解决Rolling Underwater收益计算的TypeError问题
嘿,我刚碰到过类似的问题,一眼就看出问题出在哪了:rolling.apply() 默认要求你的函数返回单个标量值,但你的lambda返回了一个完整的Series,pandas没法把Series转换成它期望的float类型,所以就抛出了TypeError。
问题根源
当你用rolling(5).apply(lambda x: x / x.cummax() - 1.0)时,每个窗口的x是一个长度为5的Series,x.cummax()会生成同样长度的累积最大值Series,两者运算后还是一个Series——但rolling.apply()默认只接受标量返回值,这就产生了类型冲突。
解决方案:用result_type='expand'返回序列结果
如果你确实需要每个滚动窗口内的逐元素水下收益(也就是窗口内每个位置相对于到该点的历史最大值的回撤),可以修改代码,加上raw=True和result_type='expand'参数:
import numpy as np import pandas as pd # 生成两种资产的随机收益 dfr = pd.DataFrame(data=np.random.random_sample((10, 2)), columns=['a', 'b']) print(dfr) # 定义计算窗口内水下收益的函数 def rolling_underwater(window): # 用numpy的累积最大值函数,比pandas处理更高效 cummax = np.maximum.accumulate(window) return window / cummax - 1.0 # 应用滚动计算,raw=True传递numpy数组,result_type='expand'展开序列结果 dfu = dfr.rolling(5, axis=0).apply(rolling_underwater, raw=True, result_type='expand') print(dfu)
这里的关键参数作用:
raw=True:把窗口数据以numpy数组的形式传给函数,比处理Series更快,也方便用numpy的累积计算函数。result_type='expand':告诉pandas你的函数会返回和窗口长度一致的数组,需要把这些值展开成对应行的输出——最终的dfu和原数据形状一致,前4行因为窗口未填满会显示NaN。
额外:如果要计算窗口内的最大回撤
要是你的需求是每个滚动窗口里的最大水下收益(即最大回撤),那可以直接让函数返回标量,不用result_type='expand':
df_max_drawdown = dfr.rolling(5, axis=0).apply(lambda x: (x / np.maximum.accumulate(x) - 1).min(), raw=True)
这个函数会返回每个窗口内的最小水下收益值(也就是最严重的回撤),完美符合rolling.apply()的标量返回要求。
内容的提问来源于stack exchange,提问作者SkyWalker
相关产品推荐
相关产品推荐

