I have a DataFrame
for weights
and returns
and I want to adjust the weights
based on the returns one day before, except for the initial weights. The basic idea is that the weights are changing based on the returns.
I created an example with the weights
, returns
and the preferred rolling weights
:
weights:
01K W 02K W 03K W 04K W
Dates
2021-01-01 0.0 0.2 0.3 0.5
2021-01-02 0.0 0.2 0.3 0.5
2021-01-03 0.5 0.2 0.3 0.0
2021-01-04 0.5 0.2 0.3 0.0
2021-01-05 0.5 0.0 0.2 0.3
2021-01-06 0.5 0.0 0.2 0.3
returns:
01K W 02K W 03K W 04K W
Dates
2021-01-01 0.01 0.01 -0.03 0.05
2021-01-02 0.02 0.02 0.04 -0.02
2021-01-03 0.03 -0.03 0.01 -0.02
2021-01-04 -0.03 0.01 0.02 0.03
2021-01-05 0.02 0.02 0.01 0.01
2021-01-06 0.01 -0.01 0.03 0.02
With these weights
and returns
, I try to calculate the rolling weights
for 01K W
as follows:
- 2021-01-03: 0.5 (initial weight) (ignore return on previous day)
- 2021-01-04: 0.515 = 0.5 * (1 0.03) (0.03=return on 2021-01-03)
- 2021-01-05: 0.4996 = 0.5 * (1 0.03) * (1-0.03)(-0.03=return on 2021-01-04)
- 2021-01-06: 0.5095 = 0.5 * (1 0.03) * (1-0.03) * (1 0.02)(0.02=return on 2021-01-05)
rolling_weights:
01K W 02K W 03K W 04K W
Dates
2021-01-01 0.0000 0.20000 0.30000 0.500
2021-01-02 0.0000 0.20200 0.29100 0.525
2021-01-03 0.5000 0.20604 0.30264 0.000
2021-01-04 0.5150 0.19986 0.30567 0.000
2021-01-05 0.4996 0.00000 0.20785 0.300
2021-01-06 0.5095 0.00000 0.20993 0.303
For reproducibility:
import pandas as pd
returns = pd.DataFrame({
'Dates':['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05', '2021-01-06'],
'01K W':[0.01, 0.02, 0.03, -0.03, 0.02, 0.01],
'02K W':[0.01, 0.02, -0.03, 0.01, 0.02, -0.01],
'03K W':[-0.03, 0.04, 0.01, 0.02, 0.01, 0.03],
'04K W':[0.05, -0.02, -0.02, 0.03, 0.01, 0.02]})
returns = returns.set_index('Dates')
weights = pd.DataFrame({
'Dates':['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05', '2021-01-06'],
'01K W':[0, 0, 0.5, 0.5, 0.5, 0.5],
'02K W':[0.2, 0.2, 0.2, 0.2, 0, 0],
'03K W':[0.3, 0.3, 0.3, 0.3, 0.2, 0.2],
'04K W':[0.5, 0.5, 0, 0, 0.3, 0.3]})
weights = weights.set_index('Dates')
Thank you very much for your suggestions.
CodePudding user response:
Multiply weights
by partial (i.e. resets every time weights
are zero) cumprod of returns
that are zeroed at positions where weights
are zero, and then shifted 1 position down:
weights_new = pd.DataFrame([weights[col]*(returns.where(weights!=0,0).shift(1).fillna(0) 1)[col].groupby(((returns.where(weights!=0,0).shift(1).fillna(0) 1)[col] == 1).cumsum()).cumprod() for col in weights.columns]).T