Skip to content

Backtest Results & Metrics

This document details the performance metrics in AKQuant backtest results (metrics_df), including their meanings, units, and calculation methods. It also covers the visualization capabilities for analyzing these results.

Visualization (Plotting)

AKQuant provides a comprehensive visualization module to analyze backtest results. You can generate professional-grade interactive HTML reports or individual plots directly from the BacktestResult object.

Quick Start

The easiest way to visualize your backtest results is using the report() method:

# Generate a full HTML report
result.report(
    title="My Strategy Report",
    filename="report.html",
    show=True,  # Set to True to open in browser automatically (default is False)
    compact_currency=True,  # Format amount columns as K/M/B in report tables
    curve_freq="raw",  # "raw" keeps all bars, "D" uses end-of-day points
)

If you prefer raw amount precision in report tables:

result.report(
    title="My Strategy Report",
    filename="report_raw_amount.html",
    compact_currency=False,
    curve_freq="D",
)

This generates a consolidated dashboard including:

  • Equity Curve: Interactive chart of account equity over time.
  • Drawdown: Historical drawdown analysis.
  • Monthly Heatmap: Monthly return performance grid.
  • Key Metrics: A summary of important performance statistics.

Intraday Support (New)

The plotting module automatically detects and adapts to intraday (minute-level) backtests:

  • Smart Downsampling: For large datasets (>10k points), it switches to WebGL rendering (Scattergl) for high performance.
  • Adaptive X-Axis: Automatically formats time labels (e.g., %Y-%m-%d %H:%M) and prevents label overlap.
  • Adaptive Duration Units: Trade duration analysis automatically switches units (Days, Hours, or Minutes) based on the strategy's average holding period.

Advanced Plotting

You can also access individual plotting functions for more granular control:

import akquant.plot as aqp

# 1. Plot Dashboard (Equity, Drawdown, Heatmap)
aqp.plot_dashboard(result)

# 2. Analyze Trade Distribution (PnL vs Duration)
aqp.plot_trades_distribution(result.trades_df)

# 3. Analyze PnL vs Duration
aqp.plot_pnl_vs_duration(result.trades_df)

Metrics Overview

Name Description Unit/Type Calculation
start_time Backtest Start Time Datetime Time of the first bar.
end_time Backtest End Time Datetime Time of the last bar.
duration Backtest Duration Timedelta end_time - start_time.
total_bars Total Bars Int Total number of bars in backtest.
trade_count Trade Count Int Total number of closed trades (Round-trip).
initial_market_value Initial Market Value Float Initial capital (usually Cash).
end_market_value End Market Value Float Total asset value at the end (Cash + Position Value).
total_pnl Total PnL Float end_market_value - initial_market_value.
unrealized_pnl Unrealized PnL Float Floating PnL of open positions at the end.
total_return_pct Total Return % (End MV - Initial MV) / Initial MV * 100.
annualized_return Annualized Return Ratio (1 + Total Return)^(1/Years) - 1.
volatility Annualized Volatility Ratio Return Std Dev * sqrt(252).
total_profit Total Profit Float Sum of profits from winning trades.
total_loss Total Loss Float Sum of losses from losing trades.
total_commission Total Commission Float Total commission paid.
max_drawdown Max Drawdown Ratio Max drawdown magnitude (e.g., 0.1 for 10%).
max_drawdown_value Max Drawdown Value Float Absolute value of max drawdown.
max_drawdown_pct Max Drawdown % % max_drawdown * 100.
win_rate Win Rate % Winning Trades / Total Trades * 100.
loss_rate Loss Rate % Losing Trades / Total Trades * 100.
winning_trades Winning Trades Int Count of trades with PnL > 0.
losing_trades Losing Trades Int Count of trades with PnL < 0.
avg_pnl Avg PnL Float Average net PnL per trade.
avg_return_pct Avg Return % % Average return percentage per trade.
avg_trade_bars Avg Trade Bars Float Average bars held per trade.
avg_profit Avg Profit Float Average profit of winning trades.
avg_profit_pct Avg Profit % % Average return of winning trades.
avg_winning_trade_bars Avg Win Trade Bars Float Average bars held for winning trades.
avg_loss Avg Loss Float Average loss of losing trades.
avg_loss_pct Avg Loss % % Average return of losing trades.
avg_losing_trade_bars Avg Loss Trade Bars Float Average bars held for losing trades.
largest_win Largest Win Float Max profit in a single trade.
largest_win_pct Largest Win % % Max return in a single trade.
largest_win_bars Largest Win Bars Float Duration (bars) of the largest win trade.
largest_loss Largest Loss Float Max loss in a single trade.
largest_loss_pct Largest Loss % % Max loss rate in a single trade.
largest_loss_bars Largest Loss Bars Float Duration (bars) of the largest loss trade.
max_wins Max Consecutive Wins Int Max number of consecutive winning trades.
max_losses Max Consecutive Losses Int Max number of consecutive losing trades.
sharpe_ratio Sharpe Ratio Ratio (Ann. Return - Risk Free) / Ann. Volatility.
sortino_ratio Sortino Ratio Ratio (Ann. Return - Risk Free) / Downside Volatility.
profit_factor Profit Factor Ratio Total Profit / abs(Total Loss).
ulcer_index Ulcer Index Ratio Measure of drawdown depth and duration.
upi Ulcer Performance Index Ratio (Ann. Return - Risk Free) / Ulcer Index.
equity_r2 Equity R² Ratio Linear regression fit of equity curve (0-1).
std_error Standard Error Float Standard error of equity curve regression.
calmar_ratio Calmar Ratio Ratio Annualized Return / Max Drawdown.
exposure_time_pct Exposure Time % % Percentage of time with open positions.
var_95 VaR 95% Ratio Value at Risk at 95% confidence (daily).
var_99 VaR 99% Ratio Value at Risk at 99% confidence (daily).
cvar_95 CVaR 95% Ratio Conditional VaR at 95% (Expected Shortfall).
cvar_99 CVaR 99% Ratio Conditional VaR at 99% (Expected Shortfall).
sqn SQN Float System Quality Number.
kelly_criterion Kelly Criterion Ratio Win Rate - (Loss Rate / Profit Factor).

Key Metrics Explained

Risk Metrics

  • Max Drawdown: Measures the worst-case scenario. E.g., 30% means buying at the peak results in a 30% loss at the trough.
  • Volatility: Measures uncertainty of returns. Higher volatility means larger price swings.
  • VaR & CVaR:
    • VaR (Value at Risk): Max expected loss over a day at a given confidence level (e.g., 95%).
    • CVaR (Conditional VaR): Average loss exceeding VaR (Expected Shortfall).

Risk-Reward Metrics

  • Sharpe Ratio: Excess return per unit of total risk. >1 is good, >2 is excellent.
  • Sortino Ratio: Similar to Sharpe but considers only downside volatility.
  • Calmar Ratio: Annualized Return / Max Drawdown.
  • SQN: System Quality Number. Measures system stability.
  • Kelly Criterion: Optimal position size based on win rate and payoff ratio.

Equity, Cash & Margin Curves

The result object provides equity/cash/margin curves over time, useful for plotting and risk analysis.

Property Description Type Explanation
equity_curve Equity Curve pandas.Series Index is Datetime, values are Total Equity. Shows the trend of net asset value.
cash_curve Cash Curve pandas.Series Index is Datetime, values are Available Cash. Shows the trend of liquid capital, useful for money management analysis.
margin_curve Margin Curve pandas.Series Index is Datetime, values are Used Margin. Useful for leveraged/margin account monitoring.
equity_curve_daily Daily Equity Curve pandas.Series End-of-day equity_curve values, useful for fast reporting and long-horizon comparisons.
cash_curve_daily Daily Cash Curve pandas.Series End-of-day cash_curve values.
margin_curve_daily Daily Margin Curve pandas.Series End-of-day margin_curve values.

For long intraday backtests, you can speed up HTML report rendering by using daily curve mode:

result.report(filename="report_daily.html", curve_freq="D")

Trades

result.trades_df contains details of every closed trade.

Name Description Unit/Type Calculation
symbol Symbol String Trading symbol.
entry_time Entry Time Datetime Time of entry.
exit_time Exit Time Datetime Time of exit.
entry_price Entry Price Float Average entry price.

| exit_price | Exit Price | Float | Average exit price. | | quantity | Quantity | Float | Traded quantity. | | side | Side | String | long or short. | | pnl | Gross PnL | Float | PnL before commission. | | net_pnl | Net PnL | Float | pnl - commission. | | return_pct | Return | Float | Trade return (decimal). | | commission | Commission | Float | Commission paid. | | duration_bars | Duration (Bars) | Int | Number of bars held. | | duration | Duration | Timedelta | exit_time - entry_time. | | mae | MAE | % | Maximum Adverse Excursion (max loss during trade). | | mfe | MFE | % | Maximum Favorable Excursion (max profit during trade). | | entry_tag | Entry Tag | String | Tag of the entry order. | | exit_tag | Exit Tag | String | Tag of the exit order. | | entry_portfolio_value | Entry Portfolio Value | Float | Total account equity at entry. | | max_drawdown_pct | Max Drawdown % | % | Max drawdown percentage during the trade. |

Orders

result.orders_df contains all order history.

Name Description Unit/Type Calculation
id Order ID String Unique identifier.
symbol Symbol String Trading symbol.
side Side String buy or sell.
order_type Type String market, limit, stop.
quantity Quantity Float Order quantity.
filled_quantity Filled Qty Float Executed quantity.
limit_price Limit Price Float Price for limit orders.
stop_price Stop Price Float Trigger price for stop orders.
avg_price Avg Price Float Average execution price.
commission Commission Float Commission paid.
status Status String filled, cancelled, rejected, etc.
time_in_force TIF String gtc, day, ioc, etc.
created_at Created At Datetime Creation time.
updated_at Updated At Datetime Last update time.
duration Duration Timedelta updated_at - created_at.
filled_value Filled Value Float filled_quantity * avg_price.
tag Tag String User defined tag.
reject_reason Reject Reason String Reason for rejection (if any).

Positions

result.positions_df contains daily (or per-bar) position snapshots.

Name Description Unit/Type Calculation
date Date Datetime Snapshot time.
symbol Symbol String Trading symbol.
long_shares Long Shares Float Long position quantity.
short_shares Short Shares Float Short position quantity.
close Close Price Float Closing price.
equity Equity Float Total account equity.
market_value Market Value Float Market value of positions.
margin Margin Float Margin used.
unrealized_pnl Unrealized PnL Float Floating PnL.
entry_price Entry Price Float Average entry price.

Attribution & Capacity

BacktestResult also exposes structured analysis outputs that are easy to reuse:

exposure = result.exposure_df()  # net/gross exposure and leverage
attr_by_symbol = result.attribution_df(by="symbol")
attr_by_tag = result.attribution_df(by="tag")
capacity = result.capacity_df()  # order count, fill rates, turnover
orders_by_strategy = result.orders_by_strategy()  # strategy-level order summary
exec_by_strategy = result.executions_by_strategy()  # strategy-level execution summary
risk_by_strategy = result.risk_rejections_by_strategy()  # strategy-level risk rejection summary
risk_trend = result.risk_rejections_trend(freq="D")  # daily trend of risk rejections
risk_trend_by_strategy = result.risk_rejections_trend_by_strategy(freq="D")

# margin-account forced liquidation audit (when enabled)
liquidation_audit = result.liquidation_audit_df

When margin mode is enabled and forced liquidation occurs, result.report(...) automatically includes:

  • a forced liquidation audit table (date, daily interest, symbols, priority)
  • daily liquidation charts in the risk chart section (shown when data exists)