Cómo calcular los períodos desde el máximo de 200 períodos de un stock
-
28-10-2019 - |
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?
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 altasrecentHigh
El número de índice del día alto más recientedaysSince
el número de días desde el último máximodata
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")
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)))
Obviamente, 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).