Rollapply & xts. Can I output the time of max value in the window?
I'm studying some yahoo finance data via quantmod.
How would I determine not only the Max and Min price over a rolling window of data, but also the exact Timestamp of those highs and lows? I have tried which.max() with rollapply but this only reports the seq of the value in the rolling window itself, and not the .index() of the row that holds the timestamp.
Can anyone suggest a solution?
a reproducible example is below, and some sample output I'd like to have...
> library(quantmod)
> getSymbols("BET.L")
xmin <- rollapply(BET.L$BET.L.Close,10,min, ascending = TRUE)
names(xmin) <- "MinClose"
xmax <- rollapply(BET.L$BET.L.Close,10,max, ascending = TRUE)
开发者_运维技巧names(xmax) <- "MaxClose"
head(cbind(BET.L$BET.L.Close, as.xts(xmax), as.xts(xmin)),15)
BET.L.Close MaxClose MinClose
2010-10-22 1550.00 NA NA
2010-10-25 1546.57 NA NA
2010-10-26 1545.00 NA NA
2010-10-27 1511.26 NA NA
2010-10-28 1490.00 1550.00 1395
2010-10-29 1435.00 1546.57 1381
2010-11-01 1447.00 1545.00 1347
2010-11-02 1420.00 1511.26 1347
2010-11-03 1407.00 1490.00 1347
2010-11-04 1395.00 1447.00 1347
2010-11-05 1381.00 1447.00 1347
2010-11-08 1347.00 1490.00 1347
2010-11-09 1415.00 1490.00 1347
2010-11-10 1426.00 1490.00 1347
2010-11-11 1430.00 1490.00 1347
and the type of output I would like to generate would look something like:
BET.L.Close MaxClose MinClose MaxDate MinDate
2010-10-22 1550.00 NA NA NA NA
2010-10-25 1546.57 NA NA NA NA
2010-10-26 1545.00 NA NA NA NA
2010-10-27 1511.26 NA NA NA NA
2010-10-28 1490.00 1550.00 1395 2010-10-22 2010-11-04
2010-10-29 1435.00 1546.57 1381 2010-10-25 2010-11-05
Ideally any approach I take must cater for the fact of duplicate prices which is common, and in this case I would order my window to take the first of the max values, and the last of the min values.
There is a big problem with this plan. The coredata element is a matrix, hence all elements must be classless and of the same mode. You cannot have objects of Date class in an xts object, and if you insist on a character class then it will force all of the other elements to also be character. So with that understood it's still possible to do something by calculating the which.max
result, then creating a row-number from which that which.max
-value is an offset, and finally using that result as an index into the index
of the object. (Sorry for the double uses of "which" and "index". Hope the meaning is clear from the code.)
xmin <- rollapply(BET.L$BET.L.Close,10,min)
names(xmin) <- "MinClose"
xmax <- rollapply(BET.L$BET.L.Close,10,max, ascending = TRUE)
names(xmax) <- "MaxClose"
head(dat <- cbind(BET.L$BET.L.Close, as.xts(xmax), as.xts(xmin)),15))
w.MaxDate <- rollapply(BET.L$BET.L.Close,10, which.max)
names(w.MaxDate) <- "w.maxdt"
dat <- cbind(dat, as.xts(w.MaxDate) )
dat<-cbind(dat,as.xts(seq.int(236), order.by=index(dat)))
> head(dat)
BET.L.Close MaxClose MinClose w.maxdt ..2
2010-10-22 1550.00 NA NA NA 1
2010-10-25 1546.57 NA NA NA 2
2010-10-26 1545.00 NA NA NA 3
2010-10-27 1511.26 NA NA NA 4
2010-10-28 1490.00 1550.00 1395 1 5
2010-10-29 1435.00 1546.57 1381 1 6
dat$maxdate <- xts( index(dat)[dat$..2-5+dat$BET.L.Close.1], order.by=index(dat))
> head(dat)
BET.L.Close MaxClose MinClose w.maxdt ..2 maxdate
2010-10-22 1550.00 NA NA NA 1 NA
2010-10-25 1546.57 NA NA NA 2 NA
2010-10-26 1545.00 NA NA NA 3 NA
2010-10-27 1511.26 NA NA NA 4 NA
2010-10-28 1490.00 1550.00 1395 1 5 14904
2010-10-29 1435.00 1546.57 1381 1 6 14907
So I got you the integer representation of the date. You can see that they are the correct values by just looking at the head of the input vector:
> head(index(dat)[dat$..2-5+dat$w.maxdt])
[1] NA NA NA NA "2010-10-22" "2010-10-25"
I think you can add one more numeric column representing date to your original xts object and then use rollapply. Look at xminmax from example below:
require(quantmod)
getSymbols("BET.L")
## add Date as numeric
BET.L$dt <- as.numeric(format(index(BET.L), "%Y%m%d"))
xmin <- rollapply(BET.L, 10, align='r', by.column = FALSE,
FUN = function(dw)
return(dw[which.min(dw[,'BET.L.Close']), c('BET.L.Close', 'dt')])
)
xmax <- rollapply(BET.L, 10, align='r', by.column = FALSE,
FUN = function(dw)
return(dw[which.max(dw[,'BET.L.Close']), c('BET.L.Close', 'dt')])
)
xminmax <- cbind(xmin, xmax)
## to get back to dates use:
## as.Date(as.character(as.integer(xminmax$dt.xmin)), format = "%Y%m%d")
## left edge of data window
x_ldt <- rollapply(BET.L$dt, 10, align='r', function(dw) return(dw[1]))
Results:
head(xminmax)
BET.L.Close.xmin dt.xmin BET.L.Close.xmax dt.xmax
2010-11-04 1395 20101104 1550.00 20101022
2010-11-05 1381 20101105 1546.57 20101025
2010-11-08 1347 20101108 1545.00 20101026
2010-11-09 1347 20101108 1511.26 20101027
2010-11-10 1347 20101108 1490.00 20101028
2010-11-11 1347 20101108 1447.00 20101101
精彩评论