使用 Pandas DataFrame 计算每日收益

Posted

技术标签:

【中文标题】使用 Pandas DataFrame 计算每日收益【英文标题】:Calculate Daily Returns with Pandas DataFrame 【发布时间】:2013-11-28 19:48:30 【问题描述】:

这是我的 Pandas 数据框:

prices = pandas.DataFrame([1035.23, 1032.47, 1011.78, 1010.59, 1016.03, 1007.95, 
              1022.75, 1021.52, 1026.11, 1027.04, 1030.58, 1030.42,
              1036.24, 1015.00, 1015.20])

这是我的daily_return 函数:

def daily_return(prices):
    return prices[:-1] / prices[1:] - 1

这是来自此函数的输出:

0    NaN
1      0
2      0
3      0
4      0
5      0
6      0
7      0
8      0
9      0
10     0
11     0
12     0
13     0
14   NaN

为什么我有这个输出?

【问题讨论】:

【参考方案1】:

我喜欢以上所有方法。但是,我们也可以这样做:

daily_returns = (prices/prices.shift(1)) -1
daily_returns.iloc[0,:] = 0

*prices 是 pandas 数据框,daily_returns 将是 Series 对象。

【讨论】:

【参考方案2】:

只是对@YaOzl 的回答的一点补充,以防有人会读到这个。 如果您的退货数据是包含多只股票的面板电子表格:

>>> prices = pandas.DataFrame(
"StkCode":["StockA","StockA","StockA","StockA","StockA","StockB","StockB","StockB","StockB","StockB","StockC","StockC","StockC","StockC","StockC",], 
"Price":[1035.23, 1032.47, 1011.78, 1010.59, 1016.03, 1007.95, 1022.75, 1021.52, 1026.11, 1027.04, 1030.58, 1030.42, 1036.24, 1015.00, 1015.20]
)

这给了你:

      Price StkCode
0   1035.23  StockA
1   1032.47  StockA
2   1011.78  StockA
3   1010.59  StockA
4   1016.03  StockA
5   1007.95  StockB
6   1022.75  StockB
7   1021.52  StockB
8   1026.11  StockB
9   1027.04  StockB
10  1030.58  StockC
11  1030.42  StockC
12  1036.24  StockC
13  1015.00  StockC
14  1015.20  StockC

那么您可以简单地将 .pct_change(k).groupby(StkCode) 结合使用。 而且它比使用迭代器快千倍...(我在我的数据集上进行了尝试,成功地将处理时间从 10 小时缩短到 20 秒!!

>>> prices["Return"] = prices.groupby("StkCode")["Price"].pct_change(1)

给你:

      Price StkCode    Return
0   1035.23  StockA       NaN
1   1032.47  StockA -0.002666
2   1011.78  StockA -0.020039
3   1010.59  StockA -0.001176
4   1016.03  StockA  0.005383
5   1007.95  StockB       NaN
6   1022.75  StockB  0.014683
7   1021.52  StockB -0.001203
8   1026.11  StockB  0.004493
9   1027.04  StockB  0.000906
10  1030.58  StockC       NaN
11  1030.42  StockC -0.000155
12  1036.24  StockC  0.005648
13  1015.00  StockC -0.020497
14  1015.20  StockC  0.000197

【讨论】:

【参考方案3】:

为什么不用pandas默认提供的非常方便的pct_change方法:

import pandas as pd

prices = pandas.DataFrame([1035.23, 1032.47, 1011.78, 1010.59, 1016.03, 1007.95, 
          1022.75, 1021.52, 1026.11, 1027.04, 1030.58, 1030.42,
          1036.24, 1015.00, 1015.20])

daily_return = prices.pct_change(1) # 1 for ONE DAY lookback
monthly_return = prices.pct_change(21) # 21 for ONE MONTH lookback
annual_return = prices.pct_change(252) # 252 for ONE YEAR lookback

原创 prices:

print(prices)
          0                                                                    
0   1035.23                                                                    
1   1032.47                                                                    
2   1011.78                                                                    
3   1010.59                                                                    
4   1016.03                                                                    
5   1007.95                                                                    
6   1022.75                                                                    
7   1021.52                                                                    
8   1026.11                                                                    
9   1027.04                                                                    
10  1030.58                                                                    
11  1030.42                                                                    
12  1036.24                                                                    
13  1015.00                                                                    
14  1015.20                                                                    

每日返回作为prices.pct_change(1)

print(prices.pct_change(1))
           0                                                                   
0        NaN                                                                   
1  -0.002666                                                                   
2  -0.020039                                                                   
3  -0.001176                                                                   
4   0.005383                                                                   
5  -0.007953                                                                   
6   0.014683                                                                   
7  -0.001203                                                                   
8   0.004493                                                                   
9   0.000906                                                                   
10  0.003447                                                                   
11 -0.000155                                                                   
12  0.005648                                                                   
13 -0.020497                                                                   
14  0.000197 

【讨论】:

当你的数据是 asc. (2016-01-03、2016-01-02等)使用:df['Adj Close'].pct_change(-1) 知道为什么 pct_change 的答案与刚刚做的略有不同:newValue - oldValue / newValue 例如 (1032.47 - 1035.23) / 1032.47 给出 -0.0026732 而不是 pct_change 给出的 -0.002666 答案? 你必须除以层值,而不是最终值...正确答案是:(1032.47 - 1035.23) / 1035.23 = -0.002666 我知道这是一个旧答案,但文档没有说明您在 pct_change 中使用的值,1 表示每日,21 表示每月,252 表示每年。您能否解释一下这是如何工作的,或者这些值是指该问题的特定时期? @IshanSharma 这都是关于“context”的。当我们谈论股市时,1、21、252 是正确的时期,因为股市并非每天都在交易【参考方案4】:

因为操作会对索引进行对齐,所以您可以将其中一个 DataFrame 转换为数组:

prices[:-1].values / prices[1:] - 1

prices[:-1] / prices[1:].values - 1

取决于你想要的结果的索引。

或者使用shift()方法:

prices.shift(1) / prices - 1

和:

prices / prices.shift(1) - 1

【讨论】:

shift 比下降到values 要好得多。 小心;取决于您的价格数据如何按日期(asc、desc)排序,班次示例将是错误的。 prices / prices.shift(1) - 1 用于升序。 (Date,SPY,XOM 2012-07-02,136.51,84.79 2012-07-03,137.41,85.72) 等等 @mimoralea 所以降序是df['Adj Close'] / df['Adj Close'].shift(-1) - 1 对吧?!?

以上是关于使用 Pandas DataFrame 计算每日收益的主要内容,如果未能解决你的问题,请参考以下文章

Pandas DataFrame 中每月平均每日记录数

在 Pandas 中为 DataFrame 中的每一行返回多行

Python Pandas 迭代和索引

使用 pandas/dataframe 基于 2 列计算加权平均值

使用距离矩阵计算 Pandas Dataframe 中行之间的距离

使用 pandas python 计算每日气候学