Skip to contents

Compute standard metrics from backtest results

Usage

ledgr_compute_metrics(
  bt,
  metrics = "standard",
  metric_context = NULL,
  risk_free_rate = NULL
)

Arguments

bt

A ledgr_backtest object. This function does not accept an equity tibble directly.

metrics

Only "standard" is supported.

metric_context

Optional metric context override for this computation. When omitted, ledgr uses the metric context stored with the run.

risk_free_rate

Optional scalar annual risk-free-rate override as a decimal. For example, 0.02 means two percent per year. Supply either metric_context or risk_free_rate, not both.

Value

A list-like ledgr_metrics object.

Details

Standard metrics are derived from the ledger and equity curve:

  • total_return: last public equity row divided by the first public equity row minus 1.

  • annualized_return: geometric annualized return from the first and last public equity rows using the metric context's annualization calendar.

  • volatility: annualized standard deviation of adjacent public equity-row returns.

  • sharpe_ratio: annualized Sharpe ratio over adjacent public equity-row excess returns, using the metric context's scalar annual risk-free rate converted to a per-period return. Flat, constant-return, invalid, or short return series return NA_real_.

  • max_drawdown: maximum peak-to-trough percentage decline, min(equity / cummax(equity) - 1).

  • n_trades: number of closed trade rows. Open-only fills do not count until a later fill closes quantity.

  • win_rate: share of closed trade rows with strict realized P&L > 0; breakeven is not a win, and open-position gains remain in equity until closed.

  • avg_trade: mean realized P&L across closed trade rows.

  • time_in_market: share of equity timestamps with absolute positions_value > 1e-6.

Examples

bars <- data.frame(
  ts_utc = as.POSIXct("2020-01-01", tz = "UTC") + 86400 * 0:3,
  instrument_id = "AAA",
  open = c(100, 101, 102, 103),
  high = c(101, 102, 103, 104),
  low = c(99, 100, 101, 102),
  close = c(100, 101, 102, 103),
  volume = 1000
)
strategy <- function(ctx, params) {
  targets <- ctx$flat()
  targets["AAA"] <- 1
  targets
}
bt <- ledgr_backtest(data = bars, strategy = strategy, initial_cash = 1000, cost_model = ledgr_cost_zero())
ledgr_compute_metrics(bt)
#> $total_return
#> [1] 0.002
#> 
#> $annualized_return
#> [1] 0.1827382
#> 
#> $volatility
#> [1] 0.009160577
#> 
#> $sharpe_ratio
#> [1] 18.3303
#> 
#> $max_drawdown
#> [1] 0
#> 
#> $n_trades
#> [1] 0
#> 
#> $win_rate
#> [1] NA
#> 
#> $avg_trade
#> [1] NA
#> 
#> $time_in_market
#> [1] 0.75
#> 
#> attr(,"metric_context")
#> ledgr_metric_context
#> ====================
#> Version:        1
#> Risk-free rate: 0.0000%
#> Calendar:       US equity daily (252 days/year * 1 bars/day = 252 bars/year)
#> Hash:           794b69bd7f9c704447d4b0208b8420cdf132ec7bd6582eaa037bf1066133c1bb
#> attr(,"metric_kernel")
#> attr(,"metric_kernel")$metric_context
#> attr(,"metric_kernel")$metric_context$metric_context_version
#> [1] 1
#> 
#> attr(,"metric_kernel")$metric_context$risk_free_rate
#> attr(,"metric_kernel")$metric_context$risk_free_rate$annual_rate
#> [1] 0
#> 
#> attr(,"metric_kernel")$metric_context$risk_free_rate$source
#> [1] "manual"
#> 
#> 
#> attr(,"metric_kernel")$metric_context$calendar
#> attr(,"metric_kernel")$metric_context$calendar$trading_days_per_year
#> [1] 252
#> 
#> attr(,"metric_kernel")$metric_context$calendar$bars_per_day
#> [1] 1
#> 
#> attr(,"metric_kernel")$metric_context$calendar$bars_per_year
#> [1] 252
#> 
#> attr(,"metric_kernel")$metric_context$calendar$source
#> [1] "us_equity"
#> 
#> attr(,"metric_kernel")$metric_context$calendar$label
#> [1] "US equity daily"
#> 
#> 
#> 
#> attr(,"metric_kernel")$metric_context_hash
#> [1] "794b69bd7f9c704447d4b0208b8420cdf132ec7bd6582eaa037bf1066133c1bb"
#> 
#> attr(,"metric_kernel")$metric_context_version
#> [1] 1
#> 
#> attr(,"metric_kernel")$bars_per_year
#> [1] 252
#> 
#> attr(,"metric_kernel")$rf_period_return
#> [1] 0
#> 
#> attr(,"metric_kernel")$calendar
#> attr(,"metric_kernel")$calendar$trading_days_per_year
#> [1] 252
#> 
#> attr(,"metric_kernel")$calendar$bars_per_day
#> [1] 1
#> 
#> attr(,"metric_kernel")$calendar$bars_per_year
#> [1] 252
#> 
#> attr(,"metric_kernel")$calendar$source
#> [1] "us_equity"
#> 
#> attr(,"metric_kernel")$calendar$label
#> [1] "US equity daily"
#> 
#> 
#> attr(,"class")
#> [1] "ledgr_metrics" "list"         
close(bt)