We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Stdlib Mastery step 17 of 55
accumulate and pairwise: max drawdown in one pass
Compute the maximum drawdown of a price series in a single pass, plus the consecutive deltas.
def max_drawdown(prices: Sequence[float]) -> float: ...
def deltas(prices: Sequence[float]) -> list[float]: ...
def solve(prices: list[float]) -> dict[str, object]: ...
Max drawdown is the largest fractional fall from a running peak:
$$\text{drawdown} = \max_i \left(1 - \frac{p_i}{\text{peak}_i}\right), \qquad \text{peak}_i = \max(p_0 \ldots p_i)$$
Empty and single-element series give 0.0, as does any monotonically
non-decreasing series. Skip any point whose running peak is not positive.
Note that this is not max(prices) - min(prices): the trough has to come
after the peak. On [10, 100, 50, 200] the largest fall is 100 to 50, and
the naive formula reports a drawdown that never happened.
deltas returns the consecutive differences via itertools.pairwise —
[] for fewer than two prices, no special case required.
solve returns:
{"max_drawdown": float, "deltas": list[float], "seeded_length": int}
where seeded_length is len(list(accumulate(prices, max, initial=0.0))).
That last one exists to make you notice the off-by-one: initial prepends
the seed, so the output is one longer than the input. It is the standard cause
of a mysterious length change when someone adds initial=0 to make the empty
case work.
The production consequence. The index-arithmetic reading of the drawdown
definition — for each point, scan backwards for the peak — is $O(n^2)$. It is
fine on a fixture of ten prices and unusable on a year of ticks. The peak
sequence is itself a running maximum, which accumulate(prices, max) produces
in one pass, so zipping prices against their peaks makes the whole thing
linear with no explicit mutable state.
Your submission must pass mypy --strict, and max(..., default=0.0) is what
keeps the empty case from raising ValueError.
Loading visualization…
Stuck?
Python reference solution
Sign in to attempt this problem and reveal the reference solution.