Python 累积收益函数

Python 累积收益函数,python,pandas,dataframe,finance,Python,Pandas,Dataframe,Finance,我有一个数据帧,如下所示: Index Return 2008-11-21 0.153419 2008-11-24 0.037421 2008-11-25 0.077500 计算最后一行所有列的累积回报的最佳方法是什么 预期结果如下: Index Return 2008-11-21 0.153419 2008-11-24 0.037421 2008-11-25 0.077500 Cumulative 0.289316 其中累积回报率计算

我有一个数据帧,如下所示:

  Index      Return
2008-11-21   0.153419
2008-11-24   0.037421
2008-11-25   0.077500
计算最后一行所有列的累积回报的最佳方法是什么

预期结果如下:

  Index      Return
2008-11-21   0.153419
2008-11-24   0.037421
2008-11-25   0.077500
Cumulative   0.289316
其中累积回报率计算如下:

cumulative = (1 + return1) * (1 + return2) * (1 + return3) - 1 

在pandas中执行此操作的最佳方法是什么?

一个选项是只使用
减少
,尽管其他人可能会想出更快的矢量化方法:

In [10]: pd.read_clipboard()
Out[10]:
        Index    Return
0  2008-11-21  0.153419
1  2008-11-24  0.037421
2  2008-11-25  0.077500

In [11]: reduce(lambda x, y: (1+x)*(1+y)-1, _10['Return'])
Out[11]: 0.28931612705992227

请注意,在Python 3中,
reduce
functools
库的一部分,尽管它是Python 2的内置函数。

对于
pandas
,您可以使用
prod()
方法:

df.append(df.iloc[:,1:].apply(lambda col: (col + 1).prod() - 1), ignore_index=True)

#        Index    Return
#0  2008-11-21  0.153419
#1  2008-11-24  0.037421
#2  2008-11-25  0.077500
#3         NaN  0.289316
或者正如@Randy C所评论的,这可以进一步简化为:

df.append((df.iloc[:,1:] + 1).prod() - 1, ignore_index=True)
这是我的:

from numpy import prod
df.append(df.apply(lambda col: prod([(1+c) for c in col]) - 1), ignore_index=True)
另一个解决方案:

df.ix["Cumulative"] = (df['Return']+1).prod() - 1
这将在
df['Return']
列中添加1,将所有行相乘,然后从结果中减去1。这将产生一个简单的浮点值。然后将结果放在“累积”索引中。由于该索引尚不存在,因此:

如果要跨多个列应用此选项:

df.ix['Cummulative'] = df.apply(lambda x: (x+1).prod()-1)
这将输出以下内容(我制作了第二列“Return2”,它是“Return”的副本):


有一个
cumprod()
方法用于此。这将适用于每一列

df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
这将比大型数据集上的其他解决方案快2倍左右:

In[106]: %timeit df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
10 loops, best of 3: 18.4 ms per loop
In[107]: %timeit df.ix['Cummulative'] = df.apply(lambda x: (x+1).prod()-1)
10 loops, best of 3: 32.9 ms per loop
In[110]: %timeit df.append(df.iloc[:,1:].apply(lambda col: (col + 1).prod() - 1), ignore_index=True)
10 loops, best of 3: 37.1 ms per loop
In[113]: %timeit df.append(df.apply(lambda col: prod([(1+c) for c in col]) - 1), ignore_index=True)
1 loop, best of 3: 262 ms per loop

如果你能找到一个内置的方法,我建议不要使用apply,因为apply在数据帧上循环,这会使它变慢。Bult-in方法效率很高,通常情况下,使用apply不会比Bult-in方法更快。

不错的方法。只需进行计算,就可以简化为
(df['Return']+1)。prod()-1
@RandyC是的,这是解决这个问题的一种更简洁的方法。Thx@Psidom,我做了df=上述操作,效果很好,只是我的日期索引消失了,第一列下的cum Return返回一个NaN,尽管不包括任何NAN,但累积值不等于零。知道为什么吗?Thx@Jalepeno112,但如何在所有栏目中应用?更新了我的答案。没有回答你问题的那一部分。这与@Psidom的答案非常相似,但我认为这一个更具可读性。没问题。你应该看看@StevenG的答案。当然,首先
将numpy作为np导入
,然后:
df.append(df.apply)(lambda col:prod([(1+c)表示col中的c,如果不是np.isnan(c)]-1),忽略_index=True)
。如果你尝试一下,然后让我知道如果它不工作!那真是太快了!!但我有一个专栏包括NaN。跳过这些而不返回NaN的任何解决方法?
df.ix[“累计”]=((df.fillna(0)+1.cumprod()-1).iloc[-1]
将用0返回代替NaN。
df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
In[106]: %timeit df.ix["Cumulative"] = ((df+1).cumprod()-1).iloc[-1]
10 loops, best of 3: 18.4 ms per loop
In[107]: %timeit df.ix['Cummulative'] = df.apply(lambda x: (x+1).prod()-1)
10 loops, best of 3: 32.9 ms per loop
In[110]: %timeit df.append(df.iloc[:,1:].apply(lambda col: (col + 1).prod() - 1), ignore_index=True)
10 loops, best of 3: 37.1 ms per loop
In[113]: %timeit df.append(df.apply(lambda col: prod([(1+c) for c in col]) - 1), ignore_index=True)
1 loop, best of 3: 262 ms per loop