4

I am trying to create a rolling EWMA with the following decay= 1-ln(2)/3 on the last 13 values of a df such has :

factor
Out[36]: 
    EWMA
0  0.043
1  0.056
2  0.072
3  0.094
4  0.122
5  0.159
6  0.207
7  0.269
8  0.350
9  0.455
10 0.591
11 0.769
12 1.000

I have a df of monthly returns like this :

change.tail(5)
Out[41]: 

date                                                                                                                                    
2016-04-30      0.033         0.031     0.010     0.007     0.014    -0.006    -0.001      0.035    -0.004     0.020     0.011     0.003
2016-05-31      0.024         0.007     0.017     0.022    -0.012     0.034     0.019      0.001     0.006     0.032    -0.002     0.015
2016-06-30     -0.027        -0.004    -0.060    -0.057    -0.001    -0.096    -0.027     -0.096    -0.034    -0.024     0.044     0.001
2016-07-31      0.063         0.036     0.048     0.068     0.053     0.064     0.032      0.052     0.048     0.013     0.034     0.036
2016-08-31     -0.004         0.012    -0.005     0.009     0.028     0.005    -0.002     -0.003    -0.001     0.005     0.013     0.003

I am just trying to apply this rolling EWMA to each columns. I know that pandas has a EWMA method but I can't figure out how to pass the right 1-ln(2)/3 factor.

help would be appreciated! thanks!

Steven G
  • 16,244
  • 8
  • 53
  • 77

2 Answers2

6

@piRSquared 's answer is a good approximation, but values outside the last 13 also have weightings (albeit tiny), so it's not totally correct.

pandas could do rolling window calculations. However, amongst all the rolling function it supports, ewm is not one of them, which means we have to implement our own.

Assuming series is our time series to average:

from functools import partial
import numpy as np

window = 13
alpha = 1-np.log(2)/3    # This is ewma's decay factor.
weights = list(reversed([(1-alpha)**n for n in range(window)]))
ewma = partial(np.average, weights=weights)
rolling_average = series.rolling(window).apply(ewma)
reading_ant
  • 344
  • 3
  • 12
  • 1
    it looks like ln and weight are not defined here, just fyi. I think it should be np.log and weights respectively – user6400946 Feb 15 '21 at 11:29
3

use ewm with mean()

df.ewm(halflife=1 - np.log(2) / 3).mean()

enter image description here

piRSquared
  • 285,575
  • 57
  • 475
  • 624