We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Everyday Standard Library Tools step 21 of 55
Find the Largest Drop from a Running Peak
A price report needs two things from a list of prices. One is the largest
fall from an earlier peak, and the other is the change from each day to the
next. Use accumulate for the running peaks and pairwise for the
neighbours.
max_drawdown([10.0, 100.0, 50.0, 200.0]) # 0.5, the fall from 100 to 50
deltas([10.0, 100.0, 50.0, 200.0]) # [90.0, -50.0, 150.0]
What to write
def max_drawdown(prices: Sequence[float]) -> float: ...
def deltas(prices: Sequence[float]) -> list[float]: ...
def solve(prices: list[float]) -> dict[str, object]: ...
The prices are finite floats in their original order. Do not change them.
max_drawdown(prices) returns 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)$$
- Skip points whose running peak is 0 or less. If no points remain, return
0.0. - Update the running peak as you go, so the function takes linear time. Do not scan every prefix again.
max(values, default=0.0)is one way to handle the case where no points remain.- Prices can be negative. After a positive peak, a negative price gives
a drawdown above
1.0.
deltas(prices) returns each price minus the one before it, in order.
solve(prices) returns a dict with three keys:
max_drawdown: the result ofmax_drawdown(prices).deltas: the result ofdeltas(prices).seeded_length: the number of results fromaccumulate(prices, max, initial=0.0), which islen(prices) + 1.
The seeded call only shows how initial changes the length. Its results start
with the extra 0.0, so its peaks do not line up with the prices. Do not use
them for the drawdown.
solve may make a separate linear pass for each key.
Your code must pass mypy --strict.
Edge cases
- Empty input, a single price, and prices that never fall all give a
drawdown of
0.0. - Fewer than two prices give
deltasof[]. - Empty input has a seeded length of
1, and the four-price example has5.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.