Computing Drawdown Statistics

Enrico Schumann

## Keywords

performance measures, risk measures, drawdown, portfolio optimisation, R

Unreviewed

# Overview

This tutorial briefly describes how to compute drawdown statistics with R.

# Definitions

Let $v$ be a time series of portfolio values, with observations at $t=0, 1, 2 \ldots T$. Then the drawdown $\mathcal{D}_t$ of this series at time $t$ is defined as

(1)
\begin{align} \mathcal{D}_t = v^{\max}_t - v_t \end{align}

where $v^{\max}_t$ is the running maximum, that is $v^{\max}_t=\max\{v_s\,|\,s \in [0,t]\}$. Following this definition, the drawdown will be a positive number; it will be 0 if the portfolio value reaches a new high. (A tiny detail: If the drawdown was a negative number, ie is computed as $v_t - v^{\max}_t$, we would strictly speaking be interested in its minimum.)

The symbol $\mathcal{D}$ stands for the whole vector of length $T+1$; subscripts indicate a scalar value, for instance the drawdown's mean or maximum value, or the drawdown at a particular point in time. Other functions may be computed to capture the information in the drawdown vector, for example the mean time underwater (ie, the average time elapsed between two consecutive values in $\mathcal{D}$ that are sufficiently close to 0), or the correlation between a portfolio's drawdown and the drawdown of an alternative asset like an index (then non-stationarity may have to be taken into account).

Typical drawdown functions could then be its mean, maximum or standard deviation:

(2)
\begin{split} \mathcal{D}_{\mathrm{mean}} =& \frac{1}{T}\sum_{t=1}^{t=T}{\mathcal{D}_t}\, , \\ \mathcal{D}_{\max} =& \max(\mathcal{D})\, ,\\ \mathcal{D}_{\mathrm{std}} =& \sqrt{\frac{1}{T-1}\sum_{t=1}^{t=T}{\left(\mathcal{D}_t - \mathcal{D}_{\mathrm{mean}}\right)^2}}\, .\\ \end{split}

# Absolute drawdown

The definition in Equation 1 gives $\mathcal{D}$ in currency terms (ie, the absolute drawdown). In R this can be written as:

# create random series
v     <- rnorm(20, mean = 0, sd = 0.02)
v     <- cumprod(c(100,1 + v))
# compute absolute drawdown
ad    <- cummax(v) - v


The maximum drawdown, for instance, can be then computed as

max(ad)


# Relative drawdown

Usually a relative drawdown is preferred, obtained by using the logarithm of $v$ or by dividing Equation 1 by $v^{\max}_t$. The ‘log-variant’ in R:

V   <- log(v)
rd  <- cummax(V) - V
rd  <- 1 - 1/exp(rd)


The last line converts the continuous returns back into discrete ones. Alternatively,
cv  <- cummax(v)
rd  <- cv - v
rd  <- rd/cv


Though it depends on the given time series, this second method is usually faster.

Sometimes we may have to compute the drawdown via loops. (For instance Matlab, though vector-oriented, does not have a cummax-function.) Then we should update the current maximum of $v$ when going through the observations.

V       <- log(v)
vmax    <- V[1]
nObs    <- length(V)
for (i in 2:nObs){
vmax    <- max(vmax,V[i])
rd[i]   <- vmax - V[i]
}
rd  <- 1 - 1/exp(rd)


This method is usually slower than the vectorised version given above. It would be much slower (by orders of magnitude) if we used
vmax <- max(V[1:i])


within the loop, that is not update the maximum.

# Example

The following code downloads the time series of the S&P 500 from Yahoo (using the tseries package [3]), and computes the drawdowns.

# get data
require(tseries)
sp500     <- get.hist.quote("^gspc",quote="Close")

par(mfrow=c(3,1), mar = c(2,6,2,3))
# time series
plot(sp500, las=1, ylab="S&P 500", xlab="")

# absolute dd
plot(cummax(sp500) - sp500, las=1, ylab="absolute drawdown", xlab="")

# relative dd
plot((cummax(sp500) - sp500)/cummax(sp500), las=1, ylab="relative drawdown", xlab="")


The results should look like