[R-SIG-Finance] Rolling through fixed-length time windows

Gabor Grothendieck ggrothendieck at gmail.com
Fri Nov 4 14:24:23 CET 2011


On Fri, Nov 4, 2011 at 9:09 AM, Matthew Clegg <matthewcleggphd at gmail.com> wrote:
> Hello R-Sig-Finance members:
>
> I was wondering if anyone has contributed functions that are similar
> to the zoo roll* functions but which operate on fixed-length time
> windows?  For example, suppose I have a zoo-based object consisting
> of the daily closing prices of a stock, and I wish to know for each
> date, what was the volatility over the succeeding 30 calendar days?
> Probably many people would settle for something like:
>  rollapply (log(lag(P))-log(P), 21, sd, align="left") * sqrt(252)
> (where P is the price series).  However, this is an approximation.
> Not all periods of 30 calendar days include precisely 21 trading days.
>
> This seems like an obvious enough question that I would think that it
> has been asked (and answered) many times before, but I could not find
> a reference to the recommended solution.
>
> If no one has tackled this problem before, I might try to put together
> a small library of functions that are like roll* but which operate
> on fixed time windows.  I am including an example of one such function
> below.
>
> Matthew Clegg
>
> ztw_sum <- function (X, delta, align="right", partial=FALSE) {
>  # Zoo Time Window Sum
>  #
>  # On input, X is a zoo-based numeric vector and delta is a time
> difference.
>  # Constructs a zoo-based numeric vector of partial sums from X.  The
> values
>  # included in a partial sum are those whose associated timestamps are
>  # within delta of the corresponding element from X.
>  #
>  # If align="right", then result[i] is a sum of those elements
>  # X[j] such that
>  #    0 <= timestamp[i] - timestamp[j] <= delta,
>  # where timestamp[i] is the timestamp (index) associated with the
>  # i-th element of X.  Conversely, if align="left", then result[i] is a
>  # sum of those elements X[j] such that
>  #    0 <= timestamp[j] - timestamp[i] <= delta.
>  #
>  # Parameters:
>  # X:        A zoo-based numeric vector with a time-based index type.
>  # delta:    An object of type difftime specifying the size of
>  #           the time window.
>  # align:    Specifies whether the sum for a given index should
>  #           be computed using elements of lower timestamps ("right")
>  #           or higher timestamps ("left").
>  # partial:  If TRUE, then partial sums are computed for elements
>  #           at the left (respectively, right) end of the vector.
>  #
>  # Returns a zoo-based numeric vector of partial sums.
>  #
>  # Running time is O(length(X)).
>
>  if (!inherits(X, "zoo") || !inherits(coredata(X), "numeric")) {
>    stop ("X must be a numeric vector of type zoo");
>  } else if (delta <= 0) {
>    stop ("delta must be positive");
>  } else if ((align != "left") && (align != "right")) {
>    stop ("align must be from c('left', 'right')");
>  }
>
>  timestamp <- index(X)
>  R <- zoo(NA, order.by = timestamp); # The result vector
>  sum <- 0;  # The current partial sum
>
>  if (align == "right") {
>    # Invariants:
>    #   (a) 0 < i <= j <= length(X)
>    #   (b) 0 <= timestamp(j) - timestamp(i) <= delta
>    i <- 1;  # The leftmost index in the current window
>    for (j in 1:length(X)) {
>      if (!is.na(X[j])) {
>        sum <- sum + as.numeric(X[j]);
>      }
>      while (timestamp[j] - timestamp[i] > delta) {
>        if (!is.na(X[i])) {
>          sum <- sum - as.numeric(X[i]);
>        }
>        i <- i+1;
>      }
>      if ((i > 1) || partial) {
>        R[j] <- sum;
>      }
>    }
>  } else { # align == "left"
>    # Invariants:
>    #   (a) 0 < j <= i <= length(X)
>    #   (b) 0 <= timestamp(i) - timestamp(j) <= delta
>    i <- length(X);  # The rightmost index in the current window
>    for (j in length(X):1) {
>      if (!is.na(X[j])) {
>        sum <- sum + as.numeric(X[j]);
>      }
>      while (timestamp[i] - timestamp[j] > delta) {
>        if (!is.na(X[i])) {
>          sum <- sum - as.numeric(X[i]);
>        }
>        i <- i-1;
>      }
>      if ((i < length(X)) || partial) {
>        R[j] <- sum;
>      }
>    }
>  }
>
>  R
> }
>

Here is a one liner (two if you count making the result into a zoo object):

> z <- zoo(1:25)
> zz <- sapply(seq_along(z), function(i) sum(z[time(z) <= time(z)[i] & time(z) > time(z)[i] - 3]))
> zoo(zz, time(z))
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 1  3  6  9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72

-- 
Statistics & Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com



More information about the R-SIG-Finance mailing list