How to modify drawdown functions in PerformanceAnalytics package for value

728 views Asked by At

I am calculating the average drawdown, average length, recovery length, etc. in R for a PnL data series rather than return data. This is data frame like this

            PNL
2008-11-03  3941434
2008-11-04  4494446
2008-11-05  2829608
2008-11-06  2272070
2008-11-07 -2734941
2008-11-10 -2513580

I used the maxDrawDown function from fTrading package and it worked. How could I get the other drawdown functions? If I directly run AverageDrawdown(quantbook) function, it will give out error message like this

Error in if (thisSign == priorSign) { : missing value where TRUE/FALSE needed  

I checked the documentation for AverageDrawdown and it is as below:

findDrawdowns(R, geometric = TRUE, ...)

R    an xts, vector, matrix, data frame, timeSeries or zoo object of asset returns

My quantbook is a data frame but doesn't work for this function. Or do you have anything other packages to get the same funciton, please advise.

1

There are 1 answers

0
iamchrisa On

I've modified the package's functions. Here is one solution in PnL case (or any other case you want to get the value rather than the return) and hope you find it useful. The parameter x is a dataframe and the row.names for x are dates so you don't bother to convert amongst different data types (which I actually suffer a lot). With the function findPnLDrawdown, you could perform a lot other functions to calculate averageDrawDown, averageLength, recovery, etc.

PnLDrawdown <- function(x) {
  ts = as.vector(x[,1])
  cumsum = cumsum(c(0, ts))
  cmaxx = cumsum - cummax(cumsum)
  cmaxx = cmaxx[-1]
  cmaxx = as.matrix(cmaxx)
  row.names(cmaxx) = row.names(x)
  cmaxx = timeSeries(cmaxx)
  cmaxx
}


findPnLDrawdown <- function(R) {
  drawdowns = PnLDrawdown(R)
  draw = c()
  begin = c()
  end = c()
  length = c(0)
  trough = c(0)
  index = 1
  if (drawdowns[1] >= 0) {
    priorSign = 1
  } else {
    priorSign = 0
  }
  from = 1
  sofar = as.numeric(drawdowns[1])
  to = 1
  dmin = 1
  for (i in 1:length(drawdowns)) {
    thisSign =ifelse(drawdowns[i] < 0, 0, 1)
    if (thisSign == priorSign) {
      if (as.numeric(drawdowns[i]) < as.numeric(sofar)) {
        sofar = drawdowns[i]
        dmin = i
      }
      to = i+ 1
    }
    else {
      draw[index] = sofar
      begin[index] = from
      trough[index] = dmin
      end[index] = to
      from = i
      sofar = drawdowns[i]
      to = i + 1
      dmin = i
      index = index + 1
      priorSign = thisSign
    }
  }
  draw[index] = sofar
  begin[index] = from
  trough[index] = dmin
  end[index] = to
  list(pnl = draw, from = begin, trough = trough, to = end, 
       length = (end - begin + 1),
       peaktotrough = (trough - begin + 1),
       recovery = (end - trough))
}