Search code examples
rtime-seriesmapplyrollapply

applying rollmean to multiple time series, with multiple windows


I need to produce rolling averages of different lengths for several time series objects. Ideally, I would be left with a dataframe for each time series object with the rolling averages stored in adjacent columns. I was able to produce the output I desired for one of the objects, but it was slow and I need to be able to replicate this across multiple series. I've tried using mapply and cbind but, I don't end up with usable results... thanks for any help you can offer!

library(zoo)
library(quantmod)
library(plyr)

symbollist <- c("SPY", "FXY", "FXE", "GLD", "JJC", "TLT")

getSymbols(symbollist, from="2014-01-01")

#list of symbols
snp <- SPY[,6]
jpy <- FXY[,6]
eur <- FXE[,6]
gld <- GLD[,6]
cop <- JJC[,6]
lut <- TLT[,6]

#poving average periods
periods<- c(10,20,50)

datalist <- list(snp,jpy,eur,gld,cop,lut)

rm <- function(a,b){
  rollmean(a, b, align="right")
}

mapply(rm, datalist, periods)

Using the code below I can produce what I want, but I'd like to replicate this across several different time series using a wider array of windows.

snp <- SPY[,6]
m.av.10 <- rollmean(snp, 10, align = "right")
m.av.20 <- rollmean(snp, 20, align = "right")
m.av.50 <- rollmean(snp, 50, align = "right")

snp$ma.10 = m.av.10
snp$ma.20 = m.av.20
snp$ma.50 = m.av.50

It should look something like this, with a dataframe like the one below for each time series object.

           SPY.Adjusted ma.10 ma.20 ma.50
2014-01-02     175.7868    NA    NA    NA
2014-01-03     175.7579    NA    NA    NA
2014-01-06     175.2486    NA    NA    NA
2014-01-07     176.3249    NA    NA    NA
2014-01-08     176.3634    NA    NA    NA
2014-01-09     176.4787    NA    NA    NA

2015-12-31     203.8700 204.2948 204.5172 205.8787
2016-01-04     201.0200 204.0320 204.3485 205.8859
2016-01-05     201.3600 204.1660 203.9975 205.8322
2016-01-06     198.8200 203.8810 203.5826 205.6830
2016-01-07     194.0500 202.9360 202.9988 205.4485
2016-01-08     191.9200 201.5260 202.3886 205.1793
2016-01-11     192.1100 200.1690 201.7615 204.8672
2016-01-12     193.6600 199.0140 201.4102 204.5886

Solution

  • 1) First produce a list L of three components containing the rolling means of the three periods respectively. The remaining lines rework that into a list L1 of the same length as datalist (and symbollist) such that each component has a column for each element of p1.

    For example, L1$SPX is an xts object whose columns are rolling means of SPX based on the periods in p1 respectively and whose column names are the period numbers (where the series itself is a rolling mean of 1 so it is labelled "1").

    p1 <- c(1, periods)
    L <- lapply(p1, rollmeanr, x = do.call(merge, datalist))
    f <- function(i) setNames(do.call(merge, lapply(L, function(x) x[, i])), p1)
    L1 <- setNames(lapply(seq_along(datalist), f), symbollist)
    

    2) Another approach is:

    p1 <- c(1, periods)
    f2 <- function(i) setNames(do.call(cbind, 
             lapply(p1, function(p) rollmeanr(datalist[[i]], p))), p1)
    L2 <- setNames(lapply(seq_along(datalist), f2), symbollist)