How to calculate periods from a 200-day maximum stock

I would like to calculate the number of periods that have passed since a maximum of 200 periods of a one-dimensional time series. For example, here is the closing price of SPY:

require(quantmod) getSymbols("SPY",from='01-01-1900') Data <- Cl(SPY) 

Now I can find the maximums of 200 periods of this series using the Lag function in quantmod:

 periodHigh <- function(x,n) { Lags <- Lag(x,1:n) High <- x == apply(Lags,1,max) x[High] } periodHigh(Data, 200) 

But now I'm stuck. How to combine this back into the original series ( Data ) and calculate for each point in the series how many periods have passed since the previous maximum of the n-period?

+4
source share
3 answers

I edited the code from the previous answers, so that they are functions that take the same inputs (one-dimensional time series) and return the same result (vector of days since the last n-day maximum):

 daysSinceHigh1 <- function(x,n) { as.vector(n-rollapply(x, n, which.max)) } daysSinceHigh2 <- function(x, n){ apply(embed(x, n), 1, which.max)-1 } 

The second function seems to be the fastest, but they give slightly different results:

 > getSymbols("^GSPC",from='01-01-1900') [1] "GSPC" > system.time(x <- daysSinceHigh1(Cl(GSPC), 200)) user system elapsed 0.42 0.00 0.42 > system.time(y <- daysSinceHigh2(Cl(GSPC), 200)) user system elapsed 0.24 0.00 0.24 > all.equal(x,y) [1] "Mean relative difference: 0.005025126" 

Upon closer examination, it turns out that in the first function there are some strange edge cases:

 data <- c(1,2,3,4,5,6,7,7,6,5,6,7,8,5,4,3,2,1) answer <- c(0,0,0,0,1,2,3,0,0,1,2,3,4,4) x <- daysSinceHigh1(data, 5) y <- daysSinceHigh2(data, 5) > x [1] 0 0 0 1 2 3 4 4 0 1 2 3 4 4 > y [1] 0 0 0 0 1 2 3 0 0 1 2 3 4 4 > answer [1] 0 0 0 0 1 2 3 0 0 1 2 3 4 4 > all.equal(x,answer) [1] "Mean relative difference: 0.5714286" > all.equal(y,answer) [1] TRUE 

Therefore, it seems that the second function (based on Andrie code) is better.

0
source

This small function returns a list with:

  • high higher date index number
  • recentHigh index number of the most recent high day
  • daysSince number of days since the last maximum
  • data object xts with only high days. Useful for printing. A.

Code:

 daysSinceHigh <- function(data, days){ highs <- days-1+which(apply(embed(data, days), 1, which.max)==1) recentHigh <- max(highs) daysSince <- nrow(data) - recentHigh list( highs=highs, recentHigh = recentHigh, daysSince = daysSince, data=data[highs, ]) } 

Results:

 daysSinceHigh(Data, 200)$daysSince [1] 90 plot(Data) points(daysSinceHigh(Data, 200)$data, col="red") 

enter image description here

+5
source

Answer to your revised question:

 require(zoo) x <- sample(300:500, 1000, replace=TRUE) str(rollapply(x, 200, function(x) which.max(x))) # int [1:801] 14 13 12 11 10 9 8 7 6 5 ... plot(x) plot(200:1000, rollapply(x, 200, function(x) 200-which.max(x))) 

So, for the xts series:

 plot( rollapply(coredata(Data), 200, function(x) 200-which.max(x))) 

enter image description here Obviously, you cannot combine anything back into the first 200 dates unless you apply a weaker definition of the maximum rolling number. (In another SO session that included β€œshifted” data, I showed how to use embed to populate β€œend” periods: Converting data to R , but I don’t know if you want to build matrices that are 200 times larger than your input. )

+3
source

All Articles