I'm trying to calculate the drawdown of a portfolio over time of a portfolio using the code below. I have tried to use the .expanding() function but can't seem to get the desired output. I'd really appreciate if anyone could let me know where I am going wrong.
def drawdown_2(arr):
tot_return = arr.add(1).cumprod()
max_return = tot_return.add(1).cummax()
return (tot_return / max_return) - 1
df['Drawdown'] = df.groupby(df.portfolio)['performance'].expanding().apply(drawdown_2)
The input data is in the format below
portfolio period performance
port1 201501 0.003718
port1 201502 -0.004890
port1 201503 -0.004171
port1 201504 -0.006922
port1 201505 0.003545
port1 201506 0.003545
port1 201507 0.006901
port1 201508 0.000101
port1 201509 0.009081
port1 201510 0.003062
port1 201511 -0.008425
port1 201512 0.002580
port2 201501 0.009135
port2 201502 0.009149
port2 201503 -0.004252
port2 201504 -0.008788
port2 201505 -0.006210
port2 201506 0.006020
port2 201507 0.002983
port2 201508 0.008498
port2 201509 0.008080
port2 201510 0.000138
port2 201511 -0.008425
port2 201512 0.002580
The desired output isan array that is the difference between the portfolio's previous maximum value and the portfolio's current value. The drawdown figures for the above inputs are below in the desired format:
portfolio period performance Drawdown
port1 201501 0.003718 0.00000
port1 201502 -0.004890 -0.00490
port1 201503 -0.004171 -0.00900
port1 201504 -0.006922 -0.01590
port1 201505 0.003545 -0.01240
port1 201506 0.003545 -0.00890
port1 201507 0.006901 -0.00210
port1 201508 0.000101 -0.00200
port1 201509 0.009081 0.00000
port1 201510 0.003062 0.00000
port1 201511 -0.008425 -0.00842
port1 201512 0.002580 -0.00587
port2 201501 0.009135 0.00000
port2 201502 0.009149 0.00000
port2 201503 -0.004252 -0.00430
port2 201504 -0.008788 -0.01300
port2 201505 -0.006210 -0.01910
port2 201506 0.006020 -0.01320
port2 201507 0.002983 -0.01030
port2 201508 0.008498 -0.00190
port2 201509 0.008080 0.00000
port2 201510 0.000138 0.00000
port2 201511 -0.008425 -0.00860
port2 201512 0.002580 -0.00605
Thanks a million for the help in advance.
I am using this data from yfinance:
import yfnance as yf
df = yf.download('aapl', start='2020-01-01')[['Close']]
df['Chg'] = df['Close'].pct_change()
Close
Date
2019-12-31 73.412498
2020-01-02 75.087502
2020-01-03 74.357498
2020-01-06 74.949997
2020-01-07 74.597504
... ...
2020-09-03 120.879997
2020-09-04 120.959999
2020-09-08 112.820000
2020-09-09 117.320000
2020-09-10 118.930000
Calculate the cumulative returns, rolling max peaks and the drawdown from the trailing peak as:
df['Cum_ret'] = (1+ df['Chg']).cumprod() # cumulative return
df['Peaks'] = df['Cum_ret'].cummax() # cumulative peaks
df['Drawdown'] = (df['Cum_ret'] - df['Peaks']) / df['Peaks'] # drawdown from trailing peak
EDIT: just noticed you have 2 portfolio returns that you are dealing with, so this hasn't really answered your question...
I think this will do what you want:
df['Drawdown'] = df.groupby('portfolio')['performance'].apply(drawdown_2)
portfolio period performance Drawdown
0 port1 201501 0.003718 0.000000
1 port1 201502 -0.004890 -0.004890
2 port1 201503 -0.004171 -0.009041
3 port1 201504 -0.006922 -0.015900
4 port1 201505 0.003545 -0.012411
5 port1 201506 0.003545 -0.008910
6 port1 201507 0.006901 -0.002071
7 port1 201508 0.000101 -0.001970
8 port1 201509 0.009081 0.000000
9 port1 201510 0.003062 0.000000
10 port1 201511 -0.008425 -0.008425
11 port1 201512 0.002580 -0.005867
12 port2 201501 0.009135 0.000000
13 port2 201502 0.009149 0.000000
14 port2 201503 -0.004252 -0.004252
15 port2 201504 -0.008788 -0.013003
16 port2 201505 -0.006210 -0.019132
17 port2 201506 0.006020 -0.013227
18 port2 201507 0.002983 -0.010284
19 port2 201508 0.008498 -0.001873
20 port2 201509 0.008080 0.000000
21 port2 201510 0.000138 0.000000
22 port2 201511 -0.008425 -0.008425
23 port2 201512 0.002580 -0.005867