Monte Carlo Drawdown
So, the other day I was messing around with the returns of something and I wanted to see if, with the basic statistics of the returns, what are the risks implicit (at least the ones I can reasonably see).
Since I’m a naive fellow, I wrote a very naive program in Python that uses Monte Carlo to estimate the mean drawdown I’d suffer and the maximum drawdown.
First, from the empirical results I extract some statistics: the win rate
winrate, which is the probability of a positive return and the return to risk
rr, which measures how much I win for every loss, on average.
With these I generate (pseudo)random numbers (on a normal distribution; I know, naive). If the number is up to
winrate, I win; otherwise I lose. If I do this a many number of times (say, a thousand) I’ll have a (thousand) series of outcomes. From these I extract the mean drawdown and the maximum drawdown.
The jupyter notebook can be found here. The code is below:
First I load the libraries I need and read the file with the empirical results; I do some visualisation and so on.
import numpy as np import pandas as pd import matplotlib.pyplot as plt import math import random file_data = “trades2.csv” trades = pd.read_csv(file_data) cumulativo = trades.results.cumsum() plt.plot(cumulativo)
Then I find out the basic assumptions of this strategy:
loss = pd.DataFrame(list(filter(lambda x: x <= 0, trades.results))) gain = pd.DataFrame(list(filter(lambda x: x > 0, trades.results))) winrate = round((len(gain)/(len(gain)+len(loss))),2) lossrate = 1 - winrate rr = round(-gain.mean()/loss.mean(),2)
And here is where I generate the possible results (notice I normalize the possible outcome: so the loss is -1 and the gain is
montecarlo = [[rr if np.random.uniform(0,1,len(trades))[j] <= winrate else -1 for j in range(1,len(trades)-1)] for i in range(1,1000)] result = pd.DataFrame(montecarlo).transpose() plt.subplots(figsize=(10,7)) plt.axhline(y=0,linewidth=1, color=‘#000000’) plt.plot(result.cumsum(), alpha = 0.5) plt.show()
The calculation of the drawdown is pretty simple:
drawdown = result.cumsum() - result.cumsum().cummax() maxdd = -drawdown.min() # mean drawdown maxdd.mean() # maximum drawdown I take to be the one that occurs 5% of the cases maxdd.quantile(.95)
Mean DD is about 11 and maximum DD is about 19. One might say this is not a good strategy, but one has to consider other factors as well.