# [SOLVED] Ewma Returns for a Time Series of returns in R

## Issue

What is the best method for calculating the EWMA returns for every column of my time series? Above all columns we have the returns from Today – 260d (-1Year) until Today -1d.

**The returns are calculated by the division of the close prices between days.

I was using the following function:

``````ewma.func <- function(rets, lambda) {
sig.p <- 0
sig.s <- vapply(rets, function(r) sig.p <<- sig.p*lambda + (r^2)*(1 - lambda), 0)
return(sqrt(sig.s))
}
``````

but It can only generate the Ewma for 1 column per time, so I also have to do the following:

``````ewma_col = NULL

for (w in 1:ncol(df)){
ewma_col[[w]] = ewma.func(df[,w], lambda = 0.94)
}

df2 <- do.call(rbind, ewma_col) %>% t()
colnames(df2) = colnames(df)
``````

Since I have 5 columns from this particular object and have more other 100 objects like these inside a list I’m working with, it becomes very hard and unefficient to have to calculate the Ewma for every column for every object. So I was thinking if there is a simpler way of doing that.

My sampled df:

``````structure(list(`25079578000106` = c(0.311405806132825, 0.0261260831393884,
0.126801611077099, -0.201990496952931, -0.169037712385034, -0.372023939507926,
0.426906935535953, -0.402262040825008, -0.273008284875687, 0.142923301064002,
0.0522466965776403, 0.491128923749784, 0.547432459279662, -0.00905547394722817,
0.243408062669914, -0.565142654522788, -0.0284871479379945, 0.141976900522423,
-0.115634388475883, 0.0858369759953348, 0.252102295598888, -0.130994651044603,
0.213179273123387, 0, 0.254748840234242, -0.162688137697842,
0.0670642675686395, 0.409574624973175, 0.11580733826122, 0.152815408000606,
-0.194192341950838, 0.079688931509736, 0.0390181277907686, 0.0366672406016733,
-0.0841513321574894, 0.170703395997407, -0.1032803445014, 0.301935098286776,
0.12983982123842, 0.179888841921638, -0.04270641511539, 0.194911670405418,
-0.126730582360324, 0.348033349109755, 0.0962079717282904, 0.0734806822947576,
0.151055897003971, -0.0701511527950061, -0.161361593563925, 0.246798639636836
), `21144577000147` = c(0.402627056610072, 0.0670045021252008,
0.136672287590045, -0.257998532470083, -0.126993350295379, -0.57979580369647,
0.493768537307915, -0.491292521383002, -0.403311319223576, 0.130267872918921,
-0.0309827290038811, 0.617972996951721, 0.486863606965926, 0.0791557540651411,
0.221599948054063, -0.743017289278214, -0.122417766579019, 0.199045961198863,
-0.204796549951425, 0.0958513541263528, 0.221446985779039, -0.103656955252518,
0.242373424043762, 0, 0.320491723141458, -0.187373789685807,
0.073898113987525, 0.443193321189028, 0.131922088075953, 0.167945069370035,
-0.218753095850843, 0.0856883381857187, 0.0915706430532737, 0.0253365722528542,
-0.10242040234516, 0.210685512865894, -0.111825193016557, 0.343926238201675,
0.145042635631398, 0.169826889032265, -0.085688805575046, 0.256890913078678,
-0.173078901207191, 0.502885210153181, 0.0139494439281407, 0.111911786007113,
0.124141056221561, -0.1009381527183, -0.164678661440121, 0.270671359612606
), `19107923000175` = c(1.17081038442848, -1.53767897591024,
-0.511278352678346, 0.801980435971927, -1.1354756311448, 1.33550018854294,
-0.877121115991031, 0.893385693962045, -3.05784205729651, 0.790948188478069,
-0.874211667633062, -2.0517918994301, 0.108547761010414, 1.31951493240194,
0.59011726098106, 0.751824284998293, -2.542040795106, -1.30722252988562,
0.166101507966232, -0.333577277251607, -0.48391700402135, -0.287302340893802,
0.276978237343428, 0, -2.20114477424431, 2.28636453339277, 3.21842714220111,
0.591201915267447, 1.88892838687025, -2.4835963874466, 0.93808037963754,
-2.02373054462441, 1.10818007306079, 0.963590860919794, 0.221162120942608,
0.927865234370984, 1.30669520840456, -1.5475129142942, 1.44346553624928,
-1.33299447861646, 2.56613694509724, -0.854390492077073, 0.431278918404132,
-0.419447091917391, 0.437028634769376, -0.279096110807586, 0.702864309823781,
1.8092529326168, -1.76575759915067, 1.79323091451806), `25079578000106` = c(-1.46258859240334,
-1.08758898677479, -0.0989607635347056, 0.877778709582344, -1.81190225830505,
3.65239411476068, -0.591252178764989, 1.21883593492385, 2.9361510378294,
-1.21526156190157, 5.60858230674057, -0.483417673513031, 3.11737542488117,
-0.928573480450723, -0.855911339203885, 1.42741011768521, 2.48564664470905,
3.64030099535739, -0.0133031404402573, 1.84565666459093, 3.33521612974437,
-0.706821796120494, -1.41998375802359, 0, -1.00702592444577,
-0.764259576953918, 0.504494091364904, 2.34908743768756, 1.12513038984616,
0.883990707916382, -0.23625019375686, 0.794114018390246, -1.84599011799946,
1.00693676176888, -2.68018999058768, 2.1352680909331, -0.361733150930377,
1.57261038511933, 0.0516994778081425, 1.29365618286101, 1.84691599060898,
-0.271832695671037, 1.894436301518, 0.0966644805885153, 1.10278020638361,
-1.48991306559765, 0.533713807271852, 0.703722278376517, -0.931114916329534,
2.53580948592571), `19436835000117` = c(1.49069022500044, -1.29966042904925,
-0.395616604691895, 0.727380076932604, -0.30439719239439, 0.550924036724609,
-0.846017086223583, 0.841084288731508, -2.71310085681762, 0.432345969238668,
-1.42297721340583, -1.75329706107732, -0.234704765443894, 1.02912636612018,
0.953879318876716, 0.506016590225045, -2.46852979989853, -1.29307204251745,
-0.361195165078243, 0.142310472620011, -0.545533438798884, 0.0622563582510338,
0.664697968204564, 0, -2.65178033678239, 1.65225289310911, 2.5845850508631,
0.743106457593967, 1.91502897378086, -2.12601029097641, 0.531378326195409,
-1.64881667524241, 0.658820966236817, 0.782823536428623, -0.430202234929311,
0.941061544290278, 1.38020377507928, -1.04732682539179, 0.918463659036206,
-0.891537194911507, 2.72019066906068, -0.480601724302687, 0.65309472320223,
0.334795709022728, 0.0443713630374987, -0.747195361418562, 0.921720304359042,
1.04346702937619, -1.57727738560425, 1.28708233642101)), row.names = c("Retorno D - 260",
"Retorno D - 259", "Retorno D - 258", "Retorno D - 257", "Retorno D - 256",
"Retorno D - 255", "Retorno D - 254", "Retorno D - 253", "Retorno D - 252",
"Retorno D - 251", "Retorno D - 250", "Retorno D - 249", "Retorno D - 248",
"Retorno D - 247", "Retorno D - 246", "Retorno D - 245", "Retorno D - 244",
"Retorno D - 243", "Retorno D - 242", "Retorno D - 241", "Retorno D - 240",
"Retorno D - 239", "Retorno D - 238", "Retorno D - 237", "Retorno D - 236",
"Retorno D - 235", "Retorno D - 234", "Retorno D - 233", "Retorno D - 232",
"Retorno D - 231", "Retorno D - 230", "Retorno D - 229", "Retorno D - 228",
"Retorno D - 227", "Retorno D - 226", "Retorno D - 225", "Retorno D - 224",
"Retorno D - 223", "Retorno D - 222", "Retorno D - 221", "Retorno D - 220",
"Retorno D - 219", "Retorno D - 218", "Retorno D - 217", "Retorno D - 216",
"Retorno D - 215", "Retorno D - 214", "Retorno D - 213", "Retorno D - 212",
"Retorno D - 211"), class = "data.frame")
``````

# Functional Programming Solution to Calc EWMA

Avoiding the assignment that ignores local scoping `<<-` is desirable. That little assignment can get missed when refactoring or copy/pasting code.

## Source example data and load require libraries

Copy pasting the `dput` output above into a text file allows us to source the file and store the value, a data.frame, in a variable (`df`).

``````DPUT_TEXT_FILE <- '/tmp/example_dput.txt'
df <- source(DPUT_TEXT_FILE)\$value
``````

We’ll use `purrr` to create a function on the fly, and `dplyr` will get used to apply a function to every column of the data frame.

``````library(dplyr)
library(purrr)
``````

## Inner calculation

The innermost calculation in the question’s body boils down to the following.
An important aspect of the original implementation that this eschews (for now) is that the result of this function gets fed back into subsequent calls.

``````# Calculate single statistic
single_ewa <- function(sig_p, val, lambda){
sig_p*lambda + (val^2)*(1 - lambda)
}
``````

## Solve using with partially applied function and an accumulator function.

``````# Calculate full weighted moving average
calc_ewma <- function(vals, lambda){
# Partially apply calc single stat function to set lambda
part_ewa <- partial(single_ewa, lambda=lambda)

# Reduce and accumulate to get the raw moving results
raw_result <- Reduce(f=part_ewa, x=vals, init=0, accumulate = TRUE )

# Square root finishes the calculation
result <- sqrt(raw_result)

# Finally, drop the initial condition from the accumulation
result <- result[2:length(result)]
return(result)
}
``````

### Partially applied function

Using `purrr::partial` we can set the lambda and get a function returned that no longer needs us to pass it as a parameter. This is also referred to as currying a function. It gets a function with the airity (number of parameters) we’re looking for. Namely, the accumulated value `sig_p` and a new value `val`.

### The accumulator function, `Reduce`

We’re using `Reduce` to start with an initial value of 0, pass it a value from the input vector, run the function that processes those two, and finally accumulate the result for the next iteration. This continues once for each member of the input vector. Using `accumulate=TRUE` yields a vector of the accumulated values instead of just the final value.

## Finally, hack around column names and do the work

Temporarily swapping out column names for enumerated names avoids the `dplyr` functions from throwing errors about non-unique column names.

``````# Save old colnames as hack around duplicate column names
old_colnames <- colnames(df)
colnames(df) <- as.character(1:ncol(df))

# Do calculation
ewma_df <- df %>% mutate_all(.funs=calc_ewma, lambda=0.94)

# re-assign colnames
colnames(df) <- old_colnames
colnames(ewma_df) <- old_colnames
``````