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