Every trading dashboard shows a Sharpe ratio and a max drawdown, and a surprising share of them compute both wrong. Not subtly wrong — wrong in ways that flatter the account, which is why the bugs survive: nobody debugs a number that makes them look good. We hit both mistakes building MetaKit's analytics engine, so this post is written from the scar tissue.
Max drawdown: measure equity, not profit-from-zero
Max drawdown is the largest peak-to-trough fall, expressed as a percentage of the peak. The classic mistake is measuring it on the cumulative P&L curve starting at zero instead of on the equity curve.
Why it matters: percentages need a denominator. On a from-zero P&L curve, the early denominator is tiny or meaningless — a $300 dip after $500 of profit reads as a "60% drawdown" on an account that actually fell from $10,500 to $10,200, a 2.9% move. The same bug in the other direction makes later drawdowns look small because the P&L peak understates the capital actually at risk.
The correct procedure:
equity_0 = starting equity (balance before the period's trading)
equity_t = running equity after each closed trade / each day
peak_t = max(equity_0 … equity_t)
drawdown_t = (peak_t − equity_t) / peak_t
max_drawdown = max over t of drawdown_tTwo practical notes. First, you need a real starting equity — reconstruct it from current balance minus net profit, or from deposits — because without it there is no honest denominator. Second, decide whether you measure on closed equity or include floating P&L: closed-only is standard for performance reports, but risk systems (and every prop firm) track the floating version, because your account can breach intraday without a single close.
Sharpe ratio: only count days that traded
Sharpe is mean excess return over the standard deviation of returns, annualized:
sharpe = (mean(daily_returns) / std(daily_returns)) × √252The subtle question is what a "daily return" is for a discretionary or part-time strategy that doesn't trade every day. The tempting answer — build a calendar series and fill non-trading days with 0% — quietly changes the number, and materially: when we tested both approaches on real accounts, the zero-padded version overstated Sharpe by roughly a third. Strings of artificial zero-return days compress the measured volatility more than they dilute the mean, and the ratio drifts up on inactivity — a strategy would "improve" by taking two weeks off.
The defensible convention: compute returns over trading sessions only — days on which at least one position closed — and annualize with √252 as the standard factor. Whatever you choose, the non-negotiable part is disclosure and consistency: a Sharpe compared across accounts is meaningless unless both were computed on the same convention.
Two more Sharpe hygiene rules while you're in the code: use returns (profit ÷ equity at the time), not raw dollar P&L, or accounts of different sizes aren't comparable; and resist annualizing from a handful of sessions — √252 scales noise as happily as it scales signal, and a two-week-old account sporting a Sharpe of 4 is a small-sample artifact, not a discovery.
The upstream bug that corrupts both
Both metrics consume a series of trades — and in MetaTrader 5, building that series is itself a place to go wrong. MT5 records deals, and a round-trip trade is two deals sharing a position id; count deals as trades and every win-rate, average-win, and per-trade return that feeds these formulas is corrupted before the formulas run. The orders, deals, and positions post covers the reconstruction; do that first, or the metrics math is precision applied to garbage.
A short checklist
- Drawdown on the equity curve, denominated by the running peak equity — never on cumulative P&L from zero.
- Reconstruct starting equity so early-period percentages are honest.
- Sharpe on trading sessions only; don't pad the calendar with zeros.
- Annualize with √252, and say so.
- Returns, not dollars; positions, not deals.
- Disclose the convention next to the number.
MetaKit's /v1/accounts/{id}/performance endpoint implements exactly these
conventions server-side — drawdown against reconstructed equity, Sharpe over
trading sessions — so every account on the platform is measured the same way.
If you'd rather verify than trust: pull the raw deals from the API, run the
checklist above, and compare. That's what it's there for.