使用 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 基于 2 列计算加权平均值