Coding
Quant Python

Max Drawdown and Recovery

Difficulty

Asked at Two Sigma, Maven Securities

Theory: Quant Python That Survives Review

Read the problem, hints and solution here. The editor needs a bigger screen: open this page on a laptop to write and run your code.

Drawdown is the number allocators ask about first, because it is the one that decides whether a strategy survives long enough to earn its Sharpe. It is also the number people compute wrongly most often, by measuring the fall from the wrong peak.

Implement max_drawdown(equity), where equity is a list of integer account values in order.

Return a 4-tuple (depth, peak_index, trough_index, recovery_index):

  • depth is the largest fall from a running peak to a later point, that is the maximum of \( peak_i - equity_j \) over all \( j \ge i \) where \( peak_i \) is the highest value at or before \( i \). Depth is a positive number, or 0 if the series never falls.
  • peak_index is the index of the peak that fall was measured from.
  • trough_index is the index of the low point of that fall.
  • recovery_index is the first index after the trough whose value is greater than or equal to the peak's value, or -1 if it never gets back.

If the series never falls at all, return (0, -1, -1, -1). An empty list returns the same.

Two tie rules, both of which the tests check:

  • If several falls share the maximum depth, report the earliest trough.
  • If the running peak value occurs more than once, peak_index is its first occurrence.

Examples

max_drawdown([100, 120, 90, 130])
# (30, 1, 2, 3)

max_drawdown([100, 90, 80, 70])
# (30, 0, 3, -1)

The first falls 30 from the peak at index 1 and recovers at index 3. The second never recovers, so the recovery index is -1.

Constraints

  • 0 <= len(equity) <= 2 * 10^5, values are integers and may be negative.
  • The measurement is always from a peak that came before the trough. Scanning for the global maximum and the global minimum and subtracting is wrong whenever the minimum happens first.
  • The hidden performance test uses 200,000 points, so the pairwise \( O(n^2) \) search will not finish. One pass carrying the running peak is enough.
Rate this problem
Language: Pythonmax_drawdown
Sample tests

Run your code to check it against the sample tests. Results appear here.

Rate this problem