I'm learning R (and its application to trading tasks via quantmod lib) and looking through the community pretty regularly to get a lot of new knowledge and tricks from here. My impression about R in general and quantmod lib in particular - it's awesome.
At this point I need help of seasoned R users. I'm using timeseries downloaded via getSymbols and I need to calculate cumulative growth/drawdown from local minimum/maximum respectively.
I can solve my task using FOR cycles as well as I can do necessary modelling in MS Excel, but I want to figure out more simple solution that does not require FOR cycles and that is more "native" in R.
Example. Input data:
20121121 79810
20121122 79100
20121123 80045
20121126 81020
20121127 80200
20121128 81350
20121129 81010
20121130 80550
20121203 80780
20121204 81700
20121205 83705
20121206 83350
20121207 83800
20121210 85385
Result:
CLOSE Cumulative gr/dd
20121121 79810 N/A
20121122 79100 0.58%
20121123 80045 1.55%
20121126 81020 2.37%
20121127 80200 -0.10%
20121128 81350 0.06%
20121129 81010 -0.76%
20121130 80550 -0.82%
20121203 80780 0.73%
20121204 81700 3.78%
20121205 83705 5.19%
20121206 83350 -1.50%
20121207 83800 1.67%
20121210 85385 2.22%
Finally, I've managed to solve it. Dirk and Darren, many thanks for your comments - the "maxdrawdown" function from PerformanceAnalytics package was not exactly what I needed, but this made me paying attention to PerformanceAnalytics and make some search through this site and the Internet. The findDrawdowns function from the same package that was close to my need, but anyway was not exacly what I was looking for (it needs the last high to be updated to start calculating new drawdown, while I need even local maxima and minima to be taken into account). Making further trials-and-errors, I made my own code that solves my task without FOR cycles. :) Here is the code. As a bonus - it returns vector with number of bars of constant growing/falling of the asset. I'll be happy if anyone can advise how to improve it.
library(rusquant)
library(quantmod)
library(tseries)
na.zero <- function(x) {
tmp <- x
tmp[is.na(tmp)] <- 0
return(tmp)
}
my.cumulative.grdd <- function(asset) {
# creating list for temporary data
tmp <- list()
#
# tmp$asset.lag <- na.locf(lag(asset), fromLast=TRUE)
# calculating ROC for the asset + getting ROC shifted by 1 element to the left and to the right
# to compare ROC[i] and ROC[i+1] and ROC[i-1]
tmp$asset.roc <- na.zero(ROC(asset))
tmp$asset.roc.lag <- na.zero(lag(tmp$asset.roc))
tmp$asset.roc.lag1 <- na.locf(lag(tmp$asset.roc, k=-1))
# calculating indices of consequent growth/drawdown waves start and end
tmp$indexfrom <- sapply(index(tmp$asset.roc[sign(tmp$asset.roc) * sign(tmp$asset.roc.lag) <= 0]), function(i) which(index(tmp$asset.roc) == i), simplify=TRUE)
tmp$indexto <- c(sapply(index(tmp$asset.roc[sign(tmp$asset.roc) * sign(tmp$asset.roc.lag1) <= 0]), function(i) which(index(tmp$asset.roc.lag1) == i), simplify=TRUE), length(index(tmp$asset.roc)))
# this is necessary to work around ROC[1] = 1
tmp$indexfrom <- tmp$indexfrom[-2]
tmp$indexto <- tmp$indexto[-1]
# calculating dates of waves start/end based on indices
tmp$datesfrom <- (sapply(tmp$indexfrom, FUN=function(x) format(index(asset)[x])))
tmp$datesto <- (sapply(tmp$indexto, FUN=function(x) format(index(asset)[x])))
tmp$dates <- apply(cbind(tmp$indexfrom, tmp$indexto), 2, FUN=function(x) format(index(asset)[x]))
# merging dates for selection (i.e. "2012-01-02::2012-01-05") and calculation of cumulative product
tmp$txtdates <- paste(tmp$datesfrom, tmp$datesto, sep="::")
# extracting consequent growth/drawdowns
tmp$drawdowns.sequences <- lapply(tmp$txtdates, function(i) tmp$asset.roc[i])
# calculating cumulative products for extracted sub-series
tmp$drawdowns.sequences.cumprods <- lapply(tmp$drawdowns.sequences, function(x) cumprod(1+x)-1)
# generating final result
result <- list()
result$len <- tmp$indexto - tmp$indexfrom + 1
result$cumgrdd <- xts(unlist(tmp$drawdowns.sequences.cumprods), index(tmp$asset.roc))
return(result)
}
# let's test
getSymbols("SPY", from="2012-01-01")
spy.cl <- Cl(SPY)
spy.grdd <- my.cumulative.grdd(spy.cl)
spy.grdd