Backtest Metrics
Definitions for the metrics returned in result.metrics of a completed backtest job. Field names below match the JSON response exactly. All decimal values are returned as quoted strings to preserve precision.
sharpe
Annualized return per unit of total volatility, computed from daily returns of the equity curve.
- Formula:
sharpe = mean(daily_returns) / stddev(daily_returns) * sqrt(252) - Units: ratio, dimensionless.
- Interpretation:
> 1is good,> 2is excellent,> 3is exceptional. Negative values mean the strategy underperformed cash on a risk-adjusted basis.
sortino
Like Sharpe, but the denominator only counts downside volatility. Penalizes losing days while ignoring large up-days.
- Formula:
sortino = mean(daily_returns) / stddev(negative_daily_returns) * sqrt(252) - Units: ratio, dimensionless.
- Interpretation: Generally higher than Sharpe for the same strategy.
> 1.5is good,> 3is excellent.
calmar
Annualized return divided by the absolute value of max drawdown. Captures how much pain you endured to earn each unit of return.
- Formula:
calmar = cagr / abs(max_drawdown) - Units: ratio, dimensionless.
- Interpretation:
> 0.5is acceptable,> 1is good,> 3is excellent. Sensitive to a single deep drawdown.
max_drawdown
Largest peak-to-trough decline in equity over the backtest period, expressed as a fraction of the peak.
- Formula:
max_drawdown = min((equity_t - max(equity_0..t)) / max(equity_0..t)) - Units: fraction in
[-1, 0]. A value of-0.142means a 14.2% drawdown. - Interpretation: Closer to 0 is better.
< -0.30(deeper than 30%) is generally uncomfortable for live capital.
win_rate
Fraction of closed trades that ended with positive PnL (after fees).
- Formula:
win_rate = count(trades where pnl > 0) / total_trades - Units: fraction in
[0, 1]. - Interpretation: Context-dependent. Trend-following strategies routinely run at
0.30–0.45and still profit; mean-reversion grids often exceed0.65. Read alongsideprofit_factorandexpected_value.
profit_factor
Sum of winning-trade PnL divided by absolute sum of losing-trade PnL.
- Formula:
profit_factor = sum(pnl where pnl > 0) / abs(sum(pnl where pnl < 0)) - Units: ratio, dimensionless.
1.0means breakeven; values above 1 are net-profitable. - Interpretation:
> 1.5is healthy,> 2is strong,> 3is rare and warrants overfitting checks.
expected_value
Mean PnL per trade in quote currency (e.g. USDT for a USDT-quoted symbol), net of fees.
- Formula:
expected_value = sum(pnl) / total_trades - Units: quote currency per trade.
- Interpretation: Must be meaningfully positive for a strategy to be worth running once realistic slippage and fees are layered on top. Compare against typical fees-per-trade to confirm headroom.
cagr
Compound Annual Growth Rate of the equity curve over the simulated period.
- Formula:
cagr = (equity_end / equity_start)^(1 / years) - 1, whereyears = duration_seconds / 31_557_600. - Units: annualized fraction.
0.187means 18.7% per year. - Interpretation: Compare against a relevant benchmark (BTC buy-and-hold, S&P 500, risk-free rate). A high CAGR with a high
max_drawdownmay be inferior to a moderate CAGR with a shallow drawdown — seecalmar.
avg_trade_duration
Mean holding time across all closed trades. Returned as avg_trade_duration_seconds (integer seconds).
- Formula:
avg_trade_duration_seconds = mean(trade.exit_time - trade.entry_time) - Units: seconds.
- Interpretation: Diagnostic only; useful for sanity-checking that a "swing" template is not in fact scalping, or vice-versa. Pair with
total_tradesto estimate exchange wear.