Comment calculer les périodes depuis 200 période haute d'un stock
-
28-10-2019 - |
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?
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")
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)))
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.)