Pregunta

Me gustaría calcular el número de períodos que han transcurrido desde el período de 200 período de una serie temporal univariada. Por ejemplo, aquí está el precio de cierre del espía:

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

Ahora, puedo encontrar los máximos de 200 períodos de esta serie utilizando el Lag función en cuantmod:

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

Pero ahora estoy atascado. ¿Cómo me fusiono esto en la serie original (Data) Y calcule, para cada punto de la serie, ¿cuántos períodos han transcurrido desde el punto de N-Periot anterior?

¿Fue útil?

Solución 3

Edité el código de las respuestas anteriores de modo que son funciones que toman las mismas entradas (una serie de tiempo univariada) y devuelven la misma salida (un vector de días desde el último máximo de N-Day):

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

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

La segunda función parece ser la más rápida, pero están proporcionando resultados ligeramente diferentes:

> 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"

Tras una inspección más cercana, parece que hay algunos casos de borde extraño en la primera función:

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

Por lo tanto, parece que la segunda función (basada en el código de Andrie) es mejor.

Otros consejos

Esta pequeña función devuelve una lista con:

  • high el número de índice de fechas altas
  • recentHigh El número de índice del día alto más reciente
  • daysSince el número de días desde el último máximo
  • data Un objeto XTS con solo los días altos. Útil para trazar.

El código:

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, ])
}       

Los resultados:

daysSinceHigh(Data, 200)$daysSince
[1] 90

plot(Data)
points(daysSinceHigh(Data, 200)$data, col="red")

enter image description here

La respuesta a su pregunta revisada:

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)))

Entonces, para la serie XTS:

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

enter image description hereObviamente, no puede fusionar nada a las primeras 200 fechas a menos que aplique una definición más flexible de máximo de rodadura. (En otra sesión de SO que involucra datos "cambiantes", mostré cómo usar la incrustación para rellenar los períodos "finales": Transformación de datos en R Pero no sé si desea construir matrices que sean 200 veces más grandes que sus datos de entrada).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top