Как найти СРЕДНЮЮ просадку 7 активов?

#python #pandas #finance #quantitative-finance

Вопрос:

В настоящее время мне поручено найти среднюю просадку 7 активов. Это то, что у меня есть до сих пор:

 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()
 

Однако это дает мне максимальную просадку только тогда, когда мне действительно нужно среднее значение.

Комментарии:

1. Разве валовая прибыль не была бы более подходящей при расчете средней просадки по нескольким активам? Возврат журнала не является суммированием по различным активам.

Ответ №1:

Вам понадобится scipy, чтобы найти местное максимальное/минимальное:

 from scipy.signal import argrelextrema
 

Я определил функцию, которая вычисляет локальные минимальные и максимальные значения временного ряда. Затем просто вычислите относительную разницу между каждым локальным максимумом и следующим локальным минимумом и вычислите среднее значение:

 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)
 

Оба оператора if в функции находятся здесь, чтобы убедиться, что вы также учитываете первую и последнюю просадку в зависимости от того, каковы локальные экстремумы в начале и в конце временного ряда.

Вам просто нужно применить эту функцию ко времени обработки данных

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