Search code examples
pythonpandasfinancequantitative-finance

How to find AVERAGE drawdown of 7 assets?


I'm currently tasked with finding the average drawdown of 7 assets. This is what I have so far:

end = dt.datetime.today()
start = end - dt.timedelta(365)

tickers = ["SBUX", "MCD", "CMG", "WEN", "DPZ", "YUM", "DENN"]
bench = ['SPY', 'IWM', 'DIA']

table_1 = pd.DataFrame(index=tickers)
data = yf.download(tickers+bench, start, end)['Adj Close']

log_returns = np.log(data/data.shift())


table_1["drawdown"] = (log_returns.min() - log_returns.max() ) / log_returns.max()

However, this only gives me the maximum drawdown, when I actually want the average.


Solution

  • You will need scipy to find local max/min:

    from scipy.signal import argrelextrema
    

    I've defined a function that calculates the local min and max of the time series. Then simply calculate the relative difference between each local maximum and next local minimum and compute the mean:

    def av_dd(series):
        series = series.values # convert to numpy array
        drawdowns = []
        loc_max = argrelextrema(series, np.greater)[0] # getting indexes of local maximums
        loc_min = argrelextrema(series, np.less)[0] # getting indexes of local minimums
    
        # adding first value of series if first local minimum comes before first local maximum (you want the first drawdown to be taken into account)
        if series[0]>series[1]:
            loc_max = np.insert(loc_max,0,0)
        # adding last value of series if last local maximum comes after last local minimum (you want the last drawdown to be taken into account)
        if len(loc_max)>len(loc_min):
            loc_min = np.append(loc_min, len(series)-1) 
    
        for i in range(len(loc_max)):
            drawdowns.append(series[loc_min[i]]/series[loc_max[i]]-1)
    
        return sum(drawdowns)/len(drawdowns)
    

    Both if statements in the function are here to make sure that you also take into account the first and last drawdown depending what are the local extremas at the beginning and end of the time series.

    You simply need to apply this function to your data time

    table_1['drawdown'] = df.apply(lambda x: av_dd(x))