3
$\begingroup$

I have a strategy on a stock (such as Buy and Hold) on which I have to calculate the maximum drawdown. The problem is that I'm working on returns expressed in percentages, so I do not have the time series of prices but the one of returns obtained at each step. So I wrote this code:

def MDD(returns):
 rend_cum=returns.cumsum()
 rend_max=pd.Series(rend_cum).cummax()
 drawdown=rend_cum-rend_max
 MDD=max(abs(drawdown))

 return(MDD)

Is it correct?

$\endgroup$

2 Answers 2

5
$\begingroup$

You are missing a few things. The function below assumes that returns is either a pandas series or a column of a pandas dataframe. Try this:

def MDD(returns):
 
    cum_rets = (1 + returns).cumprod() - 1
    nav = ((1 + cum_rets) * 100).fillna(100)
    hwm = nav.cummax()
    dd = nav / hwm - 1

    return min(dd)
$\endgroup$
3
$\begingroup$

The empyrical package has an efficient function for max drawdown. Here's an example:

import empyrical as ep

returns = np.array([-0.02089651,
                    -0.023142165,
                    0.016320209,
                    0.009323824,
                    -0.048883758,
                    -0.003912041,
                    0.005281875,
                    0.029637668,
                    -0.012299053,
                    0.040005685])

max_dd = ep.max_drawdown(returns)

The function that @amdopt provided in an answer to your question will sometimes produce a different answer than the empyrical function because empyrical uses a starting value of 100. This modified version would provide the equivalent results:

def MDD(returns):
    cum_rets = (1 + returns).cumprod() - 1
    nav = ((1 + cum_rets) * 100).fillna(100)
    nav = pd.Series([100]).append(nav) # start at 100
    hwm = nav.cummax()
    dd = nav / hwm - 1
    return min(dd)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.