En utilisant Rollapply sur deux colonnes
-
13-10-2019 - |
Question
Je suis en train de faire quelque chose de semblable que je demandais et, malheureusement, je ne peux pas travailler dehors.
Ceci est mon trame de données (données), une série chronologique des prix:
Date Price Vol
1998-01-01 200 0.3
1998-01-02 400 0.4
1998-01-03 600 -0.2
1998-01-04 100 0.1
...
1998-01-20 100 0.1
1998-01-21 200 -0.4
1998-01-21 500 0.06
....
1998-02-01 100 0.2
1998-02-02 200 0.4
1998-02-03 500 0.3
1998-02-04 100 0.1
etc.
Je voudrais dire R, à
- prendre la 1ère valeur de « Vol » et le diviser par la valeur 20 « Prix », puis
- prendre la valeur 2er de « Vol » et le diviser par la valeur de 21 « Prix », puis.
- prendre la valeur 3pc de « Vol » et le diviser par la valeur de 22 « Prix », puis
- etc.
Dans mon autre post, j'ai pu utiliser cette fonction pour calculer un retour sur une période de détention de 20 jours:
> data.xts <- xts(data[, -1], data[, 1])
> hold <- 20
> f <- function(x) log(tail(x, 1)) - log(head(x, 1))
> data.xts$returns.xts <- rollapply(data.xts$Price, FUN=f,
width=hold+1, align="left", na.pad=T)
Y at-il un moyen de faire quelque chose de très similaire pour le problème indiqué ci-dessus? Donc, quelque chose comme
f1 <- function(x,y) head(x, 1) / tail(y,1)
où x est "Vol" et y est "Prix" et appliquer "rollapply"?
Merci beaucoup
MISE À JOUR: @ Dr G: Merci pour vos suggestions. Avec un léger changement, il a fait ce que je voulais!
data.xts <- xts(data[, -1], data[, 1])
hold <- 20
data.xts$quo <- lag(data.xts[,2], hold) / data.xts[,1]
Maintenant, mon problème est que la trame de données résultant se présente comme suit:
Date Price Vol quo
1 1998-01-01 200 0.3 NA
2 1998-01-02 400 0.4 NA
3 1998-01-03 600 -0.2 NA
4 1998-01-04 100 0.1 NA
...
21 1998-01-20 180 0.2 0.003
Je sais qu'il doit y avoir NA est comme un résultat, mais seulement pour les 20 dernières observations, et non les 20 premiers petits. La formule indiquée ci-dessus calcule les valeurs correctes, mais les met en commençant au 21e rang au lieu de la première rangée. Savez-vous comment je pourrais changer cela?
La solution
Il est plus facile que cela. Il suffit de faire ceci:
data.xts <- xts(data[, -1], data[, 1])
hold <- 20
returns.xts = data.xts[,2] / lag(data.xts[,1], hold)
En fait, pour ce zoo en utilisant au lieu de XTS fonctionnerait aussi bien:
data.zoo<- zoo(data[, -1], data[, 1])
hold <- 20
returns.zoo = data.zoo[,2] / lag(data.zoo[,1], -hold)
La seule chose qui change est le signe des retards (convention de zoo est différent de XTS)
Autres conseils
Utilisation by.column = FALSE
dans rollapply
. Pour utiliser les données affichées, nous allons diviser le volume de la première ligne par le prix dans la 3ème ligne et ainsi de suite à des fins d'illustration reproductible:
library(zoo)
Lines <- "Date Price Vol
1998-01-01 200 0.3
1998-01-02 400 0.4
1998-01-03 600 -0.2
1998-01-04 100 0.1
1998-01-20 100 0.1
1998-01-21 200 -0.4
1998-01-21 500 0.06
1998-02-01 100 0.2
1998-02-02 200 0.4
1998-02-03 500 0.3
1998-02-04 100 0.1"
# read in and use aggregate to remove all but last point in each day.
# In reality we would replace textConnection(Lines) with something
# like "myfile.dat"
z <- read.zoo(textConnection(Lines), header = TRUE,
aggregate = function(x) tail(x, 1))
# divide Volume by the Price of the point 2 rows ahead using by.column = FALSE
# Note use of align = "left" to align with the volume.
# If we used align = "right" it would align with the price.
rollapply(z, 3, function(x) x[1, "Vol"] / x[3, "Price"], by.column = FALSE,
align = "left")
# and this is the same as rollapply with align = "left" as above
z$Vol / lag(z$Price, 2)
# this is the same as using rollapply with align = "right"
lag(z$Vol, -2) / z$Price
Par ailleurs, notez que zoo
utilise la même convention pour le signe de lag
comme le fait R
mais xts
utilise la convention contraire, donc si vous convertissez le dessus xts
vous devrez annuler les LAG.
Vous avez juste besoin d'utiliser
data.xts$quo <- data.xts[,2] / lag( data.xts[,1], -hold)