0

I looked at this answer where they have a really smart solution to find the point where the maximum drawdown starts, and where the maximum drawdown has it's lowest point. However, according to Wikipedia this is not the end of the period (as is claimed in the answer). The end of the period is when you reach the same peak value you had before the drawdown period began.

This implies that the drawdown period does not have an end for the graph given in the answer I linked to. I'm trying to write a code that can solve this, for both cases {1) it has an end period, 2) it has no end period}.

If the period never ends, I just want it to return the last index of the array (so basically the length of the array), and if the period does indeed end, I want the correct index. Here is a simplified example where I've tried to solve the first case - when it has an end period:

import numpy as np

an_array = [21, 22, 23, 40, 19, 35, 37, 45, 42, 39, 28]
running_maximum = np.maximum.accumulate(an_array)
# running_maximum = [21, 22, 23, 40, 40, 40, 40, 45, 45, 45, 45]

bottom_index = np.argmax(running_maximum - an_array)
start_index = np.argmax(an_array[:bottom_of_period])
# bottom_index = 4, start_index = 3

difference = running_maximum - an_array
# difference = [0, 0, 0, 0, 21, 5, 3, 0, 3, 6, 17]

The reason I compute difference, is because it makes it easy to see that end_index=7. This is because the maximum drawdown is 21 at index 4, and since difference=0 again at index 7, that means I have gone past (or just reached) my peak again. I tried writing np.argmin(difference[bottom_index:]) to get the index, but of course this doesn't give me 7 since I slice the vector difference, it gives me 3 instead which is incorrect.

Any tips on how I could solve this, and also make it so it returns the last index in cases where there is no end period would be amazing.

armara
  • 535
  • 3
  • 17

1 Answers1

0

I think this solves it;

import numpy as np

an_array = [21, 22, 23, 40, 19, 35, 37, 45, 42, 39, 28]
running_maximum = np.maximum.accumulate(an_array)
difference = running_maximum - an_array

bottom_index = np.argmax(difference)
start_index = np.argmax(an_array[:bottom_index])

if difference[bottom_index:].__contains__(0):
    end_index = len(difference[:bottom_index]) + np.argmin(difference[bottom_index:])
else:
    end_index = len(difference)

With the given example array, I get end_index = 7. If I change an_array[4]=39, the maximum drawback no longer has an end, and I get end_index = 11. Not sure if __contains__(0) is efficient though.

armara
  • 535
  • 3
  • 17