A backtest report hands you three risk numbers: Sharpe, Sortino, and max drawdown. All three can look great and still be lying to you — not because the math is wrong, but because of how the inputs were built and how many times you rolled the dice before picking the result you’re looking at.
This post explains exactly how the PRUVIQ simulator computes each metric — the actual formulas running in our engine, not textbook approximations — and the three traps that inflate them. If you want the profit-side companion metric, we covered it in Understanding Profit Factor; for the full list of backtest hygiene rules, see How to Backtest a Crypto Strategy.
Sharpe: return per unit of total volatility
The Sharpe ratio answers: how much return did the strategy earn per unit of all volatility — up moves and down moves alike?
PRUVIQ computes it from daily returns and annualizes with √365, because crypto trades all 365 days of the year:
Sharpe = mean(daily_returns) / std(daily_returns, sample) × √365
Two implementation details matter more than the formula:
Flat days count as zero, not as nothing — and the fill window must be the whole backtest. For headline simulator results (/simulate), the engine zero-fills no-trade days across the entire backtest window before computing the standard deviation. The subtle failure mode isn’t skipping the fill — it’s filling too narrow a window. In a live measurement (BTCUSDT 1D, 2023–2024), a mean-reversion strategy whose trades covered only 10% of the backtest window scored Sharpe 1.78 when zeros were filled only between its first and last trade — and an honest 0.56 once the fill covered the full window. Same trades, same formula, three times smaller. One honest disclosure: the SL/TP optimizer’s grid cells currently compute their per-cell Sharpe from trade days only — a known asymmetry on our fix list — which is one more reason to treat the grid as a map, not as the verdict.
Too thin a track record returns zero, not a guess. If the strategy’s trading span covers fewer than 5 days, annualization is meaningless — a single +5% trade padded with zeros would annualize to Sharpe 8.5 — so the engine reports Sharpe (and Sortino) as 0.0 rather than extrapolating from noise.
What Sharpe can’t tell you: it penalizes upside volatility exactly as hard as downside. A strategy with a few huge winning days gets punished on Sharpe for the very thing you want. That’s what Sortino is for.
Sortino: return per unit of downside volatility
Sortino replaces total volatility in the denominator with target downside deviation (TDD) — the root-mean-square of only the negative daily returns:
Sortino = mean(daily_returns) / TDD × √365
TDD = √( mean( min(daily_returns, 0)² ) )
The detail that separates a correct Sortino from an inflated one: TDD averages over all N days, not just the down days. This is the original Sortino & van der Meer (1991) definition, and it’s what our engine implements. Dividing by the count of down days instead — a common shortcut — systematically inflates Sortino for strategies that rarely lose, which is precisely when you most need the number to stay honest.
Read Sharpe and Sortino together: if Sortino is far above Sharpe, the strategy’s volatility is mostly upside (asymmetric winners). If they’re close, gains and losses are roughly symmetric.
Max drawdown: the worst peak-to-trough hit — scope matters
Max drawdown (MDD) is the deepest peak-to-trough decline of the equity curve. But “percent of what” is where backtests quietly cheat, so here is our scope, stated precisely:
PRUVIQ’s MDD is measured on the account curve, as a percent of account equity at the peak. The engine builds a cumulative PnL curve in percentage points starting from 0 (fixed-notional, non-compounded), treats starting capital as 100, and computes:
drawdown = (peak − equity) / (100 + peak) × 100 # capped at 100%
The cap at 100% is not cosmetic — a cumulative loss of −100 means the account is gone, and the engine stops the curve there rather than simulating trades that could never have been placed.
Why the scope disclosure matters: measuring drawdown “relative to peak profit” on a 0-based curve makes the denominator collapse when the early peak is small, producing garbage. We hit this ourselves — the same 63 BTC trades measured MDD 19.33 on the account basis and a false 100.0 on the broken profit-peak basis. When you compare MDD across tools, first ask what the denominator is.
MDD is also backward-looking by construction: it’s the worst drawdown that happened in this sample. The next one can be worse. Use it for position sizing and for asking “would I have kept running this strategy at the bottom?” — not as a ceiling.
Trap 1: short windows + annualization = extrapolation
Annualizing means extrapolating: √365 stretches whatever your window showed onto a full year. The shorter the window, the wilder the extrapolation.
The cleanest illustration is Calmar (annual return / MDD), which our engine also reports. Naively annualizing a 30-day +10% run gives +219% per year; against a 3% MDD, that’s a Calmar of 73 — a meaningless number dressed up as an elite strategy. This is why the GIPS 2020 standard flatly says returns for periods under one year must not be annualized, and why our Calmar uses the raw window return for windows shorter than a year.
Honest disclosure: Sharpe and Sortino in the simulator are annualized with √365 regardless of window length. That’s the industry convention and it makes strategies comparable — but it means a Sharpe computed on a short window is an extrapolation, not an observation. Always read the metric next to the date range it came from, and prefer the longest window your data allows.
Trap 2: thin samples
A brilliant ratio on a handful of trades is an anecdote, not a statistic. Two guards in the product:
- Hard floor: fewer than 5 daily return observations → Sharpe and Sortino report 0.0 (see above).
low_sampleflag: in strategy rankings, any result built on fewer than 100 trades is flagged as statistically thin (fewer than 20 for one-day windows, which naturally trade less). The flag is shown in the UI rather than silently hidden — an unflattering fact on screen beats a flattering one off screen.
When you see the flag, treat every ratio on that row as provisional. More trades, longer windows, and per-coin breadth are what turn a number into evidence.
Trap 3: you picked the best of many tries
This is the trap that survives even perfect formulas. Run a stop-loss/take-profit grid with dozens of cells and pick the best Sharpe: that winner’s Sharpe is the maximum of many random draws, and the maximum of many draws is biased upward even if no strategy has any real edge.
The correction is the Deflated Sharpe Ratio (DSR) from Bailey & López de Prado (2014). Instead of asking “is this Sharpe above zero?”, DSR asks: “is this Sharpe above the maximum you’d expect from luck alone, given how many candidates were tried?” It computes the expected best Sharpe under the null hypothesis of zero true skill across your number of trials, then reports the probability that the winner’s Sharpe genuinely clears that bar — accounting for the skewness and kurtosis of its returns, since crypto returns are far from normal.
When you run the SL/TP optimizer on /simulate/, PRUVIQ computes DSR for the grid winner automatically and shows it under the heatmap — provided the grid has at least 2 valid cells and the winner has at least 30 daily observations; otherwise it is omitted rather than shown as a fake zero. How to read it:
- DSR > 0.95 means the winner survives the multiple-testing correction at the 5% significance level — the performance is unlikely to be just the luckiest cell.
- A high Sharpe with a low DSR is the classic signature of overfitting-by-selection: the number is real, but so was the number of tries behind it.
DSR is not a free pass, and the paper itself says so. First, the trial count only includes disclosed tries — the grid cells we actually ran. Ideas you tested and abandoned before this grid (the “file drawer”) aren’t counted, and undercounting trials overstates DSR. That’s why the response includes a sensitivity readout at three trial counts — roughly one-eighth of the grid, the full grid, and ten times the grid — so you can see how fragile the verdict is to that assumption. Second, DSR corrects for selection, not for a broken backtest: it cannot detect look-ahead bias or missing fees. Garbage in, deflated garbage out.
A reading checklist
Before believing any risk-adjusted number:
- Window: how long, and does it span more than one market regime? Anything under a year is an extrapolation when annualized.
- Sample: is the
low_sampleflag on? Fewer than 100 trades is thin. - Scope: what is MDD a percent of? (Ours: account equity, peak-relative, non-compounded, capped at 100%.)
- Selection: how many configurations were tried before this one was shown? If it came from a grid, check the DSR.
- Cross-check: Sharpe vs Sortino for asymmetry, MDD for survivability, and Profit Factor for edge quality. One number is never the answer.
The full formulas and data policies are documented on the methodology page. And the best way to build intuition is to generate these numbers yourself, on strategies you can inspect: run one in the PRUVIQ simulator and read its Sharpe, Sortino, and MDD with the three traps in mind.