这个问题问的是价格,但不是我所知的回报(至少不是在 Python 中)。我想将给定的每日回报转换为其他频率,例如 2 天或 5 天回报。
这就是我所拥有的:
data = {'date': ['1/1/2022','1/1/2022', '1/2/2022','1/2/2022'], 'ticker': ['A', 'B','A', 'B'], '1dReturn': [0.11, 0.21,0.31, 0.41]}
df = pd.DataFrame(data)
这是我想得到的任何给定的 n 天回报,下面是 2 天:
data = {'date': ['1/1/2022','1/1/2022', '1/2/2022','1/2/2022'], 'ticker': ['A', 'B','A', 'B'], '1dReturn': [0.11, 0.21,0.31, 0.41], '2dReturn': [np.NaN, np.NaN,(1+0.11)*(1+0.31)-1, (1+0.21)*(1+0.41)-1]}
df = pd.DataFrame(data)
编辑:转念一想我觉得你可能想要一个
rolling
产品,看第二部分
cumprod
,然后减1:
df['2dReturn'] = (df.groupby('ticker')['1dReturn']
.transform(lambda g: g.add(1).cumprod().sub(1).tail(1-2))
)
输出:
date ticker 1dReturn 2dReturn
0 2022-01-01 A 0.11 NaN
1 2022-01-01 B 0.21 NaN
2 2022-01-02 A 0.31 0.4541
3 2022-01-02 B 0.41 0.7061
如果您不关心 NaN,请使用:
df['2dReturn'] = df['1dReturn'].add(1).groupby(df['ticker']).cumprod().sub(1)
这里我们只考虑
n
前几天使用rolling
和numpy.prod
.
n = 2
df[f'{n}dReturn'] = (df.groupby('ticker')['1dReturn']
.transform(lambda g: g.add(1).rolling(n)
.apply(np.prod, raw=True)
.sub(1)
)
)
输出(更大的例子):
date ticker 1dReturn 2dReturn 3dReturn 4dReturn 5dReturn
0 1/1/2022 A 0.11 NaN NaN NaN NaN
1 1/1/2022 B 0.21 NaN NaN NaN NaN
2 1/2/2022 A 0.31 0.4541 NaN NaN NaN
3 1/2/2022 B 0.41 0.7061 NaN NaN NaN
4 1/3/2022 A 0.12 0.4672 0.628592 NaN NaN
5 1/3/2022 B 0.22 0.7202 1.081442 NaN NaN
6 1/4/2022 A 0.32 0.4784 0.936704 1.149741 NaN
7 1/4/2022 B 0.42 0.7324 1.442684 1.955648 NaN
8 1/5/2022 A 0.13 0.4916 0.670592 1.188476 1.429208
9 1/5/2022 B 0.23 0.7466 1.130852 2.004501 2.635447
10 1/6/2022 A 0.33 0.5029 0.983828 1.221887 1.910672
11 1/6/2022 B 0.43 0.7589 1.497638 2.047118 3.296437
通常,在处理回报的转换时,您可能会发现使用自然对数回报更容易操作,“本身”是回报的公平近似值。
需要注意的是,回报应该很小,绝对值不大于 5%,否则近似值会远离基线。
如果你能将回报转化为
df['log_returns'] = np.log1p(df['returns'])
然后,您可以简单地对日志回报求和,而不是麻烦地加 1,计算它们,最后减去 1,@mozway 解决方案将变为:
df['2dReturn'] = df['log_returns'].groupby(df['ticker']).sum().sub(1)
干杯。