Compute standard metrics from backtest results
Source:R/backtest-results.R
ledgr_compute_metrics.RdCompute standard metrics from backtest results
Arguments
- bt
A
ledgr_backtestobject. 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.02means two percent per year. Supply eithermetric_contextorrisk_free_rate, not both.- x
A
ledgr_metricsobject.- ...
Unused.
Details
Metrics cover the persisted equity prefix. When the run's achieved
window is shorter than requested, annualized_return, volatility and
sharpe_ratio are withheld (NA, named in the withheld attribute), as
summary(bt) withholds them; summary(bt) also labels the achieved prefix.
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 returnNA_real_.max_drawdown: maximum peak-to-trough percentage decline,min(equity / cummax(equity) - 1).n_trades: number of closed trade rows. A closed trade row is a fill that closes quantity, fully or in part, so a rebalance that trims a position counts as one. 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 absolutepositions_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)
#> ledgr Metrics
#> =============
#> Total Return: 0.20%
#> Annualized Return: 18.27%
#> Volatility (annual): 0.92%
#> Sharpe Ratio: 18.330
#> Max Drawdown: 0.00%
#> Closed Trades: 0
#> Win Rate: N/A
#> Avg Trade: N/A
#> Time in Market: 75.00%
#> Context: risk-free 0.00% annual; 252 periods/year (US equity daily (default)); hash 794b69bd7f9c
#> Scope: persisted equity prefix; use summary(bt) for completion-aware reporting
close(bt)