Skip to content

Tear Sheets

QuantWave includes built-in HTML tear sheets for analyzing backtest results. These are standalone, zero-dependency HTML files containing interactive equity curves, drawdowns, performance metrics, and a paginated trades table.

Usage

Once you generate a BacktestReport using backtest_with_report(), you can either get the raw HTML string or save it directly to a file:

import polars as pl
from quantwave import tearsheet

# 1. Run your backtest
df = pl.DataFrame({
    "timestamp": list(range(20)),
    "close": [100.0 + i * 0.5 for i in range(20)],
    "signal": [0.0, 1.0, 1.0, 1.0, 1.0, 0.0] + [0.0] * 14,
})

report = (
    df.lazy()
    .bt.backtest_with_report(
        signal="signal",
        commission_bps=0.0,
        slippage_bps=0.0,
    )
)

# 2. Save as a standalone HTML tear sheet
tearsheet.save_html(report, "report.html", title="My Strategy Backtest")

# Or get the HTML string directly
html_content = tearsheet.render_html(report, title="My Strategy Backtest")

The resulting HTML file can be opened in any web browser and contains: - Summary Metrics: Sharpe ratio, CAGR, Max Drawdown, Win Rate. - Equity Curve: Interactive chart of portfolio equity over time. - Drawdown Curve: Interactive chart of portfolio drawdown percentage over time. - Rolling Sharpe / Rolling Volatility: Trailing-window (default 20-bar) annualized Sharpe and volatility charts. - Monthly Returns Heatmap: Year × month grid, green/red shaded by return magnitude. - Trade Blotter: Full per-trade table (entry/exit time, side, prices, quantity, net PnL) — in addition to the existing aggregate Trade Summary card. - Run Metadata: Title, generated-at (UTC) timestamp, and — when supplied — a reproducibility seed and arbitrary run_metadata config key/values.

Reproducible run metadata & benchmark-relative section

to_html() / save_html() (and the tearsheet.render_html() / tearsheet.save_html() helpers) accept optional keyword arguments, all additive and backward compatible:

report.to_html(
    title="My Strategy Backtest",
    seed=42,                                   # shown in the Run Metadata card
    run_metadata={"commission_bps": "5", "execution_delay": "same_bar"},
    benchmark_returns=benchmark_daily_returns,  # per-bar simple returns, aligned by index
    rolling_window=20,                          # rolling Sharpe/vol window, in bars
)

Passing benchmark_returns adds a Benchmark-Relative card (alpha, beta, strategy vs. benchmark cumulative return) computed from PerformanceMetrics.benchmark. Omit it and the section is left out entirely — no empty card, no broken layout.