Search code examples
rdataframecalendarapplycovariance

Applying functions w.r.t. calendar days in R


I have daily (financial) time series. As every month does not end in the 30th or 31st, it has created problems for myself using apply functions. Using monthly time series I can just specify every n'th month. However, how can I specify every n'th month with daily series.

Let's say I have this date data set:

dates <- seq(as.Date("2000-01-01"), length = 1000, by = "days")

data <- cbind(rnorm(1000, mean = 0.01, sd = 0.001),
              rnorm(1000, mean = 0.01, sd = 0.001),
              rnorm(1000, mean = 0.01, sd = 0.001))

Particularly, I want to run covariance matrices for every n'th month similarly to:

cov.fixed <- lapply(as.data.frame(t(rollapply(1:nrow(data), 90, c))),
 function(i) cov(data[i,]))

But instead of 90 is it possible to write as every 3rd month such that it takes into account the calendar days?

Many thanks


Solution

  • If you want the covariances every month, you can do something like the following. The key is to split the matrix by month.

    library(zoo)
    
    month <- as.yearmon(dates)
    
    cov.month <- lapply(split(as.data.frame(data), month), cov)
    
    names(cov.month) <- sub(" ", "_", names(cov.month))
    cov.month$Jan_2000
    #             V1           V2           V3
    #V1 7.825062e-07 7.063689e-08 9.561721e-08
    #V2 7.063689e-08 8.989207e-07 1.293351e-07
    #V3 9.561721e-08 1.293351e-07 1.175318e-06
    
    cov.month[[1]]    # The same
    

    As for quarters, the code is similar, just substitute as.yearqtr for as.yearmon.

    quarter <- as.yearqtr(dates)
    cov.quarter <- lapply(split(as.data.frame(data), quarter), cov)
    

    Then make better names, without spaces, with sub like above.

    Data.

    Unlike in the question, I have set the RNG seed.

    set.seed(3658)    # Make the results reproducible
    data <- cbind(rnorm(1000, mean = 0.01, sd = 0.001),
                  rnorm(1000, mean = 0.01, sd = 0.001),
                  rnorm(1000, mean = 0.01, sd = 0.001))