Skip to main content

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: > 1 is good, > 2 is excellent, > 3 is 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.5 is good, > 3 is 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.5 is acceptable, > 1 is good, > 3 is 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.142 means 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.45 and still profit; mean-reversion grids often exceed 0.65. Read alongside profit_factor and expected_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.0 means breakeven; values above 1 are net-profitable.
  • Interpretation: > 1.5 is healthy, > 2 is strong, > 3 is 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, where years = duration_seconds / 31_557_600.
  • Units: annualized fraction. 0.187 means 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_drawdown may be inferior to a moderate CAGR with a shallow drawdown — see calmar.

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_trades to estimate exchange wear.