Search code examples
rxtsquantmodperformanceanalytics

Trying to create a rolling period cummax


I am trying to create a function that buys an N period high. So if I have a vector:

  x = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)

I want to take the rolling 3 period high. This is how I would like the function to look

 x =  c(1, 2, 3, 4, 5, 5, 5, 3, 4, 5)

I am trying to do this on an xts object. Here is what I tried:

    rollapplyr(SPY$SPY.Adjusted, width = 40, FUN = cummax)
    rollapply(SPY$SPY.Adjusted, width = 40, FUN = "cummax")
    rapply(SPY$SPY.Adjusted, width  = 40, FUN = cummax)

The error I am receiving is:

      Error in `dimnames<-.xts`(`*tmp*`, value = dn) : 
      length of 'dimnames' [2] not equal to array extent

Thanks in advance


Solution

  • You're close. Realize that rollapply (et al) is this case expecting a single number back, but cummax is returning a vector. Let's trace through this:

    1. When using rollapply(..., partial=TRUE), the first pass is just the first number: 1
    2. Second call, the first two numbers. You are expecting 2 (so that it will append to the previous step's 1), but look at cummax(1:2): it has length 2. Conclusion from this step: the cum functions are naïve in that they are relatively monotonic: they always consider everything up to and including the current number when they perform their logic/transformation.
    3. Third call, our first visit to a full window (in this case): considering 1 2 3, we want 3. max works.

    So I think you want this:

    zoo::rollapplyr(x, width = 3, FUN = max, partial = TRUE)
    #  [1] 1 2 3 4 5 5 5 3 4 5
    

    partial allows us to look at 1 and 1-2 before moving on to the first full window of 1-3. From the help page:

    partial: logical or numeric. If 'FALSE' (default) then 'FUN' is only
             applied when all indexes of the rolling window are within the
             observed time range.  If 'TRUE', then the subset of indexes
             that are in range are passed to 'FUN'.  A numeric argument to
             'partial' can be used to determin the minimal window size for
             partial computations. See below for more details.
    

    Perhaps it is helpful -- if not perfectly accurate -- to think of cummax as equivalent to

    rollapplyr(x, width = length(x), FUN = max, partial = TRUE)
    #  [1] 1 2 3 4 5 5 5 5 5 5
    cummax(x)
    #  [1] 1 2 3 4 5 5 5 5 5 5