3

I am familiar with the zoo function rollapply which allows you to do rolling computations on zoo or xts objects and you can specify the rolling increment via the by parameter. I am specifically interested in applying a function every month but using all of the past daily data in the computation. For example say my data set looks like this:

dte, val
1/01/2001, 10
1/02/2001, 11
...
1/31/2001, 2
2/01/2001, 54
2/02/2001, 34
...
2/30/2001, 29

I would like to select the end of each month and apply a function that uses all the daily data. This doesn't seem like it would work with rollapply since the by argument would be 30 sometimes, 29 other months, etc. My current idea is:

f <- function(xts_obj) { coef(lm(a ~ b, data=as.data.frame(xts_obj)))[1] }
month_end <- endpoints(my_xts, on="months", k=1)
rslt <- apply(month_end, 1, function(idx) { my_xts[paste0("/",idx)] })

Surely there is a better way to do this that would be quicker no? To clarify: I would like to use overlapping periods just the rolling should be done monthly.

Alex
  • 19,533
  • 37
  • 126
  • 195

3 Answers3

3

If I understand correctly, you can get the dates of your endpoints, then for each endpoint (i.e. using lapply or for), call rollapply using data up to that point.

getSymbols("SPY", src='yahoo', from='2012-01-01', to='2012-08-01')
idx <- index(SPY)[endpoints(SPY, 'months')]
out <- lapply(idx, function(i) {
  as.xts(rollapplyr(as.zoo(SPY[paste0("/", i)]), 5, 
                    function(x) coef(lm(x[, 4] ~ x[, 1]))[2], by.column=FALSE))
})
sapply(out, NROW)
#[1]  16  36  58  78 100 121 142 143

I temporarily coerce to zoo for the rollapplyr to make sure the rollapply.zoo method is being used (as opposed to the unexported rollapply.xts method), then coerce back to xts

GSee
  • 48,880
  • 13
  • 125
  • 145
  • Is the zoo/xts conversion needed? I get the same result when I take them out. – Darren Cook Aug 19 '12 at 00:57
  • @DarrenCook, It doesn't look like it's necessary, but I wanted to cover my bases. – GSee Aug 19 '12 at 01:13
  • @DarrenCook, If you want the results to be `xts`, then the `as.xts` is required assuming you're using `rollapply.zoo` which you will be unless you have PerformanceAnalytics loaded. If you have PerformanceAnalytics loaded, then you'll be using `rollapply.xts` – GSee Aug 19 '12 at 14:57
  • @Gsee, I have been wondering how to solve a similar problem, less complex because I have to calculate function for each month using monthly data i.e. calculate trend using all the data availaible upto that time. How will I modify the above method given? What will be the width specified? Can I do this without rollapply? – Anusha Nov 05 '12 at 22:06
  • @Anusha, this is the last question of yours I'm answering in the comments of another answer. The next question you ask you should post as a proper question. Try this: `m <- to.monthly(SPY); m$trend <- sapply(seq_len(NROW(m)), function(i) coef(lm(as.numeric(Ad(m[1:i])) ~ c(1:i)))[2]); m`. and as an added bonus `chartSeries(OHLC(m), TA='addTA(m$trend)')` – GSee Nov 06 '12 at 00:55
  • @Gsee Thank you for the answer. I wanted to post a proper question but had this feeling that this question will be deemed highly related and so its better ask here itself if I am missing something basic. – Anusha Nov 06 '12 at 01:36
  • @Gsee Also, this is the first question I have put in the comments of another question, ..surprised by your response. – Anusha Nov 06 '12 at 01:37
  • @Anusha, sorry, I guess it was another Anusha. I hope my answer was helpful. – GSee Nov 06 '12 at 01:41
  • @Gsee Would you prefer that this question be posted separately? – Anusha Nov 06 '12 at 01:43
  • @Anusha, if you understand the answer and you're satisfied with it, then no. If you need further clarification, or if it doesn't answer your question, then yes. – GSee Nov 06 '12 at 01:47
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19129/discussion-between-anusha-and-gsee) – Anusha Nov 06 '12 at 03:04
2

As an answer to "Is the zoo/xts conversion needed?": It isn't needed in this case, but rollapply won't work if you send it a dataframe, as I recently discovered from this StackOverflow answer

Community
  • 1
  • 1
user128494
  • 21
  • 2
  • 1
    `rollapply.xts` is now registered as an S3 method in the development version of **xts**. However, it is not yet perfect; there is at least one case where it fails, but rollapply.zoo does not. – GSee Nov 16 '12 at 15:49
0

You want period.apply(), or its convenience helper apply.monthly(), both in xts.

Example:

R> foo <- xts(1:100, order.by=Sys.Date()+0:99)
R> apply.monthly(foo, sum)
           [,1]
2012-08-31  105
2012-09-30  885
2012-10-31 1860
2012-11-25 2200
R> 

or equally

R> apply.monthly(foo, quantile)
           0%   25%  50%   75% 100%
2012-08-31  1  4.25  7.5 10.75   14
2012-09-30 15 22.25 29.5 36.75   44
2012-10-31 45 52.50 60.0 67.50   75
2012-11-25 76 82.00 88.0 94.00  100
R> 

just to prove that functions returning more than one value can be used too.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • but won't this simply do non overlapping periods? that is the stuff passed to sum are going to be the non-overlapping data in the months. i am trying to use all of the past data so that my periods are overlapping.. – Alex Aug 18 '12 at 18:34
  • Oh, I see, that would indeed be different. But as you did not in fact provide a full example, I missed that. Depending on what your aggregation function is, you could possibly still use `apply.monthly()` and aggregate afterwards. It all depends... – Dirk Eddelbuettel Aug 18 '12 at 18:37
  • ok i just updated the question to make it more clear. sorry about that. – Alex Aug 18 '12 at 18:39