Appearance

Personalize your experience

Mode
Accent Color
Direction
Performance Metrics

Performance Metrics

Backtesting

What each figure on the results page is computed from, what it hides, and the order to read them in so the important ones are not drowned out by the return.

Read them in this order

The page is not ordered by importance, and the return is the most prominent number on it. That is exactly backwards. Reading in this order stops you from evaluating a on the one figure that says least about whether it is usable.

  1. 1
    1. Trade count
    Below 30, stop reading — nothing else on the page is meaningful. This is a gate, not a metric.
  2. 2
    2. Max drawdown
    Decides whether the is holdable. A 60% return through a 45% is a strategy almost nobody actually sits through.
  3. 3
    3. Profit factor and expectancy
    Whether there is an edge, and how it is per trade. Independent of how much capital was deployed.
  4. 4
    4. Win rate with payoff ratio
    Always together. Either one alone is uninterpretable.
  5. 5
    5. Sharpe or Sortino
    Return per unit of risk, which is what makes two strategies comparable.
  6. 6
    6. Total return
    Last. It is the consequence of everything above plus the position size you happened to choose.

P&L metrics

MetricTypeDescription
totalPnlcurrencyNet profit after costs. Depends on position size, so it does not across strategies.
totalPnlPercent%Net profit against initial capital. Comparable only if the risk taken was similar.
annualisedReturn%Return scaled to a year. Beware extrapolating from a short test — three good months annualised is a fiction.
averageWincurrencyMean profit on winning .
averageLosscurrencyMean loss on losing . against your : if it is much larger, stops are slipping or gapping.
profitFactorratioGross profit / gross loss. 1.0 is break-even. Above 1.5 suggests a real edge; far above 3 on a sample usually suggests overfitting rather than brilliance.
expectancycurrencyAverage P&L per trade. The single most practical number here: multiply by expected to project, and if it is negative no amount of helps.
how they are computed
const wins   = trades.filter(t => t.pnl > 0);const losses = trades.filter(t => t.pnl < 0);const grossProfit = wins.reduce((s, t) => s + t.pnl, 0);const grossLoss   = Math.abs(losses.reduce((s, t) => s + t.pnl, 0));const profitFactor = grossLoss === 0 ? Infinity : grossProfit / grossLoss;const winRate    = wins.length / trades.length;const averageWin = grossProfit / wins.length;const averageLos = grossLoss / losses.length;// expectancy — what one trade is worth on averageconst expectancy = winRate * averageWin - (1 - winRate) * averageLos;// equivalently, and more usefully for reasoning:const payoff   = averageWin / averageLos;const breakEven = 1 / (1 + payoff);      // the win rate you need
!
Caution:A of Infinity means zero losing , which in practice means the sample is too or something is wrong. It is never good news.

Win rate and payoff, together

Neither number means anything alone, and quoting one without the other is the most common way performance gets misrepresented — including to oneself.

Payoff ratioTypeDescription
1 : 1break-even at 50%Costs push the real requirement to roughly 53–55%. A thin margin for error.
2 : 1break-even at 33%Two losses in three is still profitable. Comfortable.
3 : 1break-even at 25%Where most trend-following strategies . Uncomfortable to run, robust to a bad streak.
1 : 2break-even at 67%Achievable for mean reversion. Fragile: one gapped stop erases four wins.
1 : 4break-even at 80%Even an 80% win rate only breaks even. Almost never worth running.
★
Pro tip:The asymmetry is worth internalising. A high win rate with a poor payoff feels better — most are pleasant — and is structurally more fragile, because the rare loss is enough to undo a long run of wins. A low win rate with a good payoff feels worse and breaks less.

Risk metrics

MetricTypeDescription
maxDrawdown%Largest peak-to-trough equity decline. The number that determines whether you can actually run the , as distinct from whether it is profitable.
drawdownDurationdaysHow long the worst trough lasted. Frequently more decisive than depth — a 15% over eight months is harder to hold than a 25% one over three weeks.
sharpeRatioratioExcess return divided by total volatility. Above 1 good, above 2 excellent. Penalises upside volatility as though it were risk, which is its main flaw.
sortinoRatioratioLike , but only downside deviation in the denominator. Fairer to strategies with wins and small losses, which is most trend-following.
calmarRatioratioAnnualised return / . Return per unit of worst-case pain. Above 1 acceptable, above 3 strong.
ulcerIndexindexDepth and of drawdowns combined. Captures the experience of holding a better than alone.
recoveryFactorratioNet profit / . How much return was earned per unit of drawdown endured.
maxConsecutiveLossescountThe longest losing streak. Ask honestly whether you would still be running the at the end of it — most abandonment happens here rather than at the low.

Drawdown deserves its own attention

is measured from the running peak, so it is the loss you would have experienced had you started at the worst possible moment. That is the definition, because that is the experience that ends strategies.

drawdown series
let peak = equity[0];const drawdown = equity.map(v => {  peak = Math.max(peak, v);  return (v - peak) / peak;        // 0 at a new high, negative below});const maxDrawdown = Math.min(...drawdown);// duration matters as much as depth — measure the longest run below a peaklet longest = 0;let current = 0;for (const d of drawdown) {  current = d < 0 ? current + 1 : 0;  longest = Math.max(longest, current);}
  • Depth tells you the capital requirement. A 30% means the must be funded to survive losing 30% without intervention.
  • tells you the psychological requirement, and it is the one people underestimate. Eight months below a previous high is eight months of wondering whether the is broken.
  • Frequency tells you what is normal. Several 10% drawdowns is a different proposition from one 30% , even at the same total return.
★
Pro tip:Ask the question concretely before deploying: if this loses maxDrawdown over drawdownDuration starting on day one, will I still be running it at the end? If the honest answer is no, the is unsuitable regardless of its return — and the response is smaller size, not more optimism.

Advanced metrics

MetricTypeDescription
systemQualityNumberratioExpectancy divided by the of trade P&L, scaled by the of . Combines edge, consistency and sample size into one figure.
annualisedVolatility% of returns, annualised. Useful for comparing against a benchmark.
skewnessnumberAsymmetry of the return . Positive means a long tail — occasional wins, which is the desirable .
kurtosisnumberTail weight. Above 3 means fatter tails than normal, so extreme moves are more likely than the volatility figure implies. Read alongside .
monthlyReturnsgridP&L by month. The fastest way to see whether a year’s result came from two months.
averageDurationbarsMean holding . Far shorter than intended usually means the stop sits inside normal noise.
ℹ
Note:The monthly returns grid is under-rated. A with a 24% annual return where twenty came from one month is not a 24% strategy — it is a strategy that caught one move, and the aggregate metrics cannot tell you that.

Thresholds worth holding to

MetricTypeDescription
Trades> 30, ideally > 100A gate before anything else is read.
Profit factor> 1.5Below 1.3 the edge is likely inside your cost uncertainty.
Max drawdown< 20–30%Depends on temperament and capital. Be conservative: the lived experience is worse than the chart.
Sharpe> 1.0Above 3 on a retail warrants suspicion rather than celebration.
Calmar> 1.0Return should at least match the worst .
Expectancypositive after costsNon-negotiable. A negative expectancy cannot be by position sizing.
!
Caution:These are filters, not targets. Tuning a until it clears them is precisely how overfitting happens. Use them to reject, never as an optimisation .

See also

Related articles

  • Step 7 — Strategy Testing

    Automation / Strategy Builder / Wizard Steps

    The testing step offers three modes, each answering different questions about strategy behavior. Use all three in sequence: backtest to validate logic,…

  • Strategy DSL — Execution Model

    Coding / Strategy DSL

    What the engine does on every bar: protective exits, exit signals, entries, layers and re-entries, sizing and costs, and where every statistic in the result…

  • Backtesting in Python and C++

    Backtesting / SDKs

    The quatick Python package and the header-only C++ library let you import indicators, backtest on your own machine and send the same file to Quatick.…

  • Backtesting Methodology

    Backtesting / Methodology

    What a backtest is actually evidence of, the assumptions built into it, how much data is enough, and the procedure that makes a result worth acting on.

  • C++ SDK Reference

    Backtesting / SDKs / C++

    Header-only C++20 (packages/quatick-backtest-cpp): the position simulator, an event-driven engine with the same order rules as Python, analytics, a parallel…

  • Execution Modelling

    Backtesting / Execution Modelling

    Commission, slippage, spread and fill assumptions — the difference between a backtest that means something and one that flatters. Costs are where most…

  • From Backtest to Live

    Backtesting / Going Live

    The staged path from a validated backtest to full size, what each stage can detect that the previous one cannot, and the monitoring that tells you when to stop.

  • Monte Carlo and Robustness

    Backtesting / Monte Carlo

    A backtest is one path through history. Monte Carlo asks how different the result could have been with the same edge: a different order of trades, a…

  • Orders and Fills

    Backtesting / SDKs / Orders and Fills

    The event-driven engines of the Python and C++ SDKs share one set of order types and fill rules, so the same strategy fills identically in both languages…

Browse all knowledge base articles →