# Implementation of Maximum Drawdown in python working directly with returns

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?

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)


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)