Question

Je voudrais calculer le nombre de périodes qui se sont écoulées depuis le sommet de 200 période d'une série temporelle univariée. Par exemple, voici le cours de clôture de SPY:

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

Maintenant, je peux trouver les sommets de 200 périodes de cette série en utilisant la fonction Lag dans quantmod:

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

Mais maintenant, je suis coincé. Comment puis-je fusionner ce retour sur la série d'origine (Data) et calculer, pour chaque point de la série, le nombre de périodes se sont écoulées depuis le sommet précédent n-période?

Était-ce utile?

La solution 3

Je modifié le code des réponses précédentes telles qu'elles sont des fonctions qui prennent les mêmes entrées (une série temporelle univariée) et le retour de la même sortie (un vecteur de jours écoulés depuis le dernier Maximal jours):

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 deuxième fonction semble être le plus rapide, mais qu'ils fournissent des résultats légèrement différents:

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

Une fois de plus près, il semble qu'il ya des cas de pointe étranges dans la 1ère fonction:

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

Par conséquent, il semble que la deuxième fonction (à base de code de Andrie) est mieux.

Autres conseils

Cette petite fonction retourne une liste avec:

  • high le numéro d'index des dates élevées
  • recentHigh le numéro d'index du dernier jour haute
  • daysSince le nombre de jours écoulés depuis la dernière haute
  • data un XTS objet avec seulement les jours élevés. Utile pour le traçage.

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

Les résultats:

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

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

entrer image description ici

La réponse à votre question révisée:

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

Donc, pour la série XTS:

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

entrer dans la description d'image ici Vous ne pouvez pas fusionner évidemment rien de nouveau aux 200 premières dates, sauf si vous appliquez une définition plus souple de rouler au maximum. (Dans une autre session de SO impliquant données « fuyants » J'ai montré comment utiliser les intégrer au pad « de fuite » périodes: transformation des données en R mais je ne sais pas si vous voulez construire des matrices qui sont 200 fois plus grand que vos données d'entrée.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top