Usando Rollapply en dos columnas
-
13-10-2019 - |
Pregunta
Estoy tratando de hacer algo que estaba pidiendo similares aquí y por desgracia no puedo resolverlo.
Esta es mi trama de datos (datos), una serie temporal de precios:
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.
Me gustaría decirle R, a
- tome la 1ª valor de "Vol" y se divide por el valor de 20 "Precio", a continuación,
- toma el valor de la 2ª "Vol" y se divide por el valor de 21 "Precio", a continuación.
- tomar el valor de 3ST "Vol" y se divide por el valor de 22 "Precio", a continuación,
- etc.
En mi otro post, yo era capaz de usar esta función para calcular un retorno en un período de tenencia de 20 días:
> 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)
¿Hay una manera de hacer algo muy similar para el problema se ha señalado anteriormente? Así que algo como
f1 <- function(x,y) head(x, 1) / tail(y,1)
donde x es "Vol" ey es "precio" y luego aplicar "rollapply"?
Muchas gracias
UPDATE: @ Dr G: Gracias por sus sugerencias. Con un ligero cambio, se hizo lo que quería!
data.xts <- xts(data[, -1], data[, 1])
hold <- 20
data.xts$quo <- lag(data.xts[,2], hold) / data.xts[,1]
Ahora mi problema es, que las miradas resultantes de tramas de datos como este:
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
Yo sé que debe haber AN como un resultado, pero sólo en los últimos 20 observaciones, no los primeros 20 queridos. La fórmula se ha indicado anteriormente calcula los valores correctos, sin embargo los pone a partir de la fila 21a en lugar de la primera fila. ¿Sabe usted cómo podría cambiar eso?
Solución
It's actually easier than that. Just do this:
data.xts <- xts(data[, -1], data[, 1])
hold <- 20
returns.xts = data.xts[,2] / lag(data.xts[,1], hold)
Actually for this using zoo instead of xts would work as well:
data.zoo<- zoo(data[, -1], data[, 1])
hold <- 20
returns.zoo = data.zoo[,2] / lag(data.zoo[,1], -hold)
Only thing that changes is the sign of the lags (zoo convention is different than xts)
Otros consejos
Use by.column = FALSE
in rollapply
. In order to use the posted data we will divide the volume in the first row by the price in the 3rd row and so on for purposes of reproducible illustration:
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
By the way, note that zoo
uses the same convention for the sign of lag
as does R
but xts
uses the opposite convention so if you convert the above to xts
you will have to negate the lags.
You just need to use
data.xts$quo <- data.xts[,2] / lag( data.xts[,1], -hold)