Home > Blockchain >  Calculation of floating weights based on weight and return DataFrame
Calculation of floating weights based on weight and return DataFrame

Time:12-13

I have two DataFrames; returns and weights and I try to combine them to a floating_weights DataFrame. The idea behind is that I want to dynamically adjust the weights in period t with the return in period t-1. So the weights increase, if there are positive returns and vice versa.

Here I created a simple example:

weights:
    Dates       01K W   02K W   03K W   04K W
0   2021-01-01  0.0     0.2     0.3     0.5
1   2021-01-02  0.0     0.2     0.3     0.5
2   2021-01-03  0.5     0.2     0.3     0.0
3   2021-01-04  0.5     0.2     0.3     0.0
4   2021-01-05  0.5     0.0     0.2     0.3
5   2021-01-06  0.5     0.0     0.2     0.3


returns:
Dates           01K W   02K W   03K W   04K W
0   2021-01-01  0.01    0.01    -0.03   0.05
1   2021-01-02  0.00    0.02    0.04    -0.02
2   2021-01-03  0.03    -0.03   0.01    -0.02
3   2021-01-04  -0.03   0.01    0.02    0.00
4   2021-01-05  0.02    0.02    0.01    0.01
5   2021-01-06  0.01    -0.01   0.03    0.02

The floating_weights DataFrame is based on the normal weights adjusted with the returns from the previous period:

floating_weights (2021-01-01, 02K W): 0.2 (start with normal weight)

floating_weights (2021-01-02, 02K W): 0.202 = 0.2 * (1 0.01)

floating_weights (2021-01-03, 02K W): 0.206 = 0.2 * (1 0.01) * (1 0.02)

floating_weights (2021-01-04, 02K W): 0.19986 = 0.2 * (1 0.01) * (1 0.02) * (1-0.03)

The floating_weights would look like this.

    Dates       01K W   02K W   03K W   04K W
0   2021-01-01  0.0000  0.20000 0.30000 0.500
1   2021-01-02  0.0000  0.20200 0.29100 0.525
2   2021-01-03  0.5000  0.20604 0.30264 0.000
3   2021-01-04  0.5150  0.19986 0.30567 0.000
4   2021-01-05  0.4995  0.00000 0.20785 0.300
5   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, 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, 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 the help!

CodePudding user response:

We can use cumprod to calculate the cumulative returns, then shift and multiply the cumulative returns with the weights dataframe to get the desired result

r = returns.add(1).cumprod().shift()
floating_weights = weights.mul(r, fill_value=1)

If you want to reset the cumprod every time the weight is assigned to zero, in such case we have to consider each column separately

floating_weights = weights.copy()

for col in weights:
    g = weights[col].eq(0).cumsum()
    r = returns[col].add(1).groupby(g).cumprod()
    floating_weights[col] = weights[col].mul(r.shift(1), fill_value=1)

>>> floating_weights

               01K W     02K W     03K W  04K W
Dates                                          
2021-01-01  0.000000  0.200000  0.300000  0.500
2021-01-02  0.000000  0.202000  0.291000  0.525
2021-01-03  0.500000  0.206040  0.302640  0.000
2021-01-04  0.515000  0.199859  0.305666  0.000
2021-01-05  0.499550  0.000000  0.207853  0.300
2021-01-06  0.509541  0.000000  0.209932  0.303
  • Related