Advertisement IC Markets

Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Share, develop, and backtest custom MQL4/MQL5 Expert Advisors, Python data-scraping scripts, trading bots, and automated market alert systems.
Post Reply
Fairman
Posts: 6757
Joined: Tue Jul 21, 2026 7:11 am
Location: Abuja

Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by Fairman »

Maximum drawdown in pandas from an equity list: a worked example you can check by hand

A quick recipe, then a check by hand. Equity after each trade: 10000, 10150, 10080, 10400, 10260, 9980, 10300.

In pandas:
equity = pd.Series(list_of_values)
peak = equity.cummax()
dd = equity / peak - 1
max_dd = dd.min()

By hand, the running peak is 10000, 10150, 10150, 10400, 10400, 10400, 10400. The drawdowns are 0, 0, minus 0.69%, 0, minus 1.35%, minus 4.04% (9980 divided by 10400, minus 1) and minus 0.96%. The maximum drawdown is 4.04%, which is $420 from the 10400 peak to the 9980 trough.

Mistakes I'd watch for. Using equity minus peak gives dollars where you wanted a percentage, which is easy to miss in a table. Running the same code on the balance column, which only changes when trades close, understates drawdown while a position is floating at a loss, so it needs equity. And checking a function on 2,000 rows can hide a bug that a seven row list exposes immediately, so test on a list small enough to do on paper first.
It’s Fairman :geek:
Recommended broker for automated trading & scalping IC Markets
Fairman
Posts: 6757
Joined: Tue Jul 21, 2026 7:11 am
Location: Abuja

Re: Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by Fairman »

If you journal in R, the calculation is additive. Take the R results 1.5, -1, -1, 2, -1, -1, -1, 1.5. The cumulative sum is 1.5, 0.5, -0.5, 1.5, 0.5, -0.5, -1.5, 0. The running peak reaches 1.5 on the first trade and again on the fourth, and the lowest point after that is -1.5 on the seventh. The drawdown is peak minus cumulative, so 1.5 minus (-1.5) is 3R. In pandas it's cumsum, then cummax, then subtract. At a steady 1% risk per R that's roughly a 3% drawdown, though compounding makes the real figure slightly different. R curves strip out position size and make strategies comparable.
It’s Fairman :geek:
Amanhasnoname
Posts: 1506
Joined: Fri Oct 30, 2026 9:45 am

Re: Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by Amanhasnoname »

I'm glad you included the warning about the balance column, because that one fooled me for months. My journal export only had balance after each closed trade, and my max drawdown looked like a comfortable 3%. When I finally pulled equity snapshots from the platform every minute, the real figure was closer to 5.5%, mostly from two trades that went deep against me before coming back to a small loss.

The seven-row check is a good habit. I keep a tiny test file with nine values I worked out on paper and run every new drawdown function against it before trusting it on real data. It caught a bug once where I had sorted the equity series by value instead of by time, which made the drawdown zero and looked perfectly plausible at a glance.

One addition I'd suggest is also recording the duration of the drawdown, the number of trades or days between the peak and the recovery. A 4% drawdown that recovers in a week feels very different from one that takes three months, and the duration was the part that really tested my discipline.
Fairman
Posts: 6757
Joined: Tue Jul 21, 2026 7:11 am
Location: Abuja

Re: Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by Fairman »

Maximum drawdown says how deep. How long matters too. Using the same drawdown series, underwater periods are where dd is below zero. One line gets the longest stretch in observations: dd.lt(0).groupby(dd.eq(0).cumsum()).cumsum().max(). The grouping starts a new bucket every time the equity returns to its peak, and the cumulative sum counts the steps spent below it. For the seven value example the answer is 3, and the account isn't back at its peak at the end. A system with a 6% maximum drawdown that spends 90 days underwater is a different thing to sit through than one that recovers in 9 days.
It’s Fairman :geek:
Fairman
Posts: 6757
Joined: Tue Jul 21, 2026 7:11 am
Location: Abuja

Re: Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by Fairman »

The sampling frequency changes the answer. If you record equity only at the close of each trade, you miss everything in between. Say the 10260 close came from a trade that, mid way, had equity dip to 9800. From the 10400 peak that's 5.77% where the closed trade series showed 1.35%. MT5 doesn't keep a record of equity tick by tick, so the intraday low is lost unless you logged it. An EA or script that writes equity to a file every minute or on every change solves it. If you can't, treat the maximum drawdown from closed trades as a lower bound, not the real number.
It’s Fairman :geek:
Fairman
Posts: 6757
Joined: Tue Jul 21, 2026 7:11 am
Location: Abuja

Re: Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by Fairman »

Withdrawals fake drawdowns. If you take $2,000 out of a $12,000 account, equity goes from 12000 to 10000, which looks like minus 16.7% on the drawdown calculation, though no trade lost anything. The fix is to adjust the series before computing: add back the cumulative withdrawals, and subtract the cumulative deposits. A tidier way is to track it like a fund, where each deposit or withdrawal buys or sells units at the current value. The percentage return per unit is then independent of cash moves. For a small journal the add back method is enough and takes a single extra column.
It’s Fairman :geek:
FXS HongKong Scalper
Posts: 407
Joined: Sat Oct 24, 2026 10:15 pm

Re: Maximum drawdown in pandas from an equity list: a worked example you can check by hand

Post by FXS HongKong Scalper »

A good worked example. One mistake I have seen is calculating drawdown from closed trade balances only, which ignores open losses during trades. For accounts with long trades, the real drawdown can be larger. If the data allows it, using equity snapshots during trades gives a more accurate number. Another point is to report the length of the drawdown along with its depth, since a short deep drawdown feels very different from a long shallow one.
FXS Official Team | Hong Kong Session Desk
Post Reply