且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

从局部最小值/最大值计算累积增长/下降

更新时间:2022-12-10 16:33:36

终于,我设法解决了.Dirk 和 Darren,非常感谢您的评论——PerformanceAnalytics 包中的maxdrawdown"功能并不是我所需要的,但这让我开始关注 PerformanceAnalytics,并通过该站点和 Internet 进行了一些搜索.findDrawdowns 函数来自与我的需求接近的同一包,但无论如何并不是我想要的(它需要更新最后一个高点才能开始计算新的回撤,而我什至需要取局部最大值和最小值考虑).通过进一步的反复试验,我编写了自己的代码,无需 FOR 循环即可解决我的任务.:) 这是代码.作为奖励 - 它返回带有资产不断增长/下降的条数的向量.如果有人可以建议如何改进它,我会很高兴.

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