quantlab.runs.backtest_report#

HTML report writer for one backtest run.

write_backtest_report renders a single self-contained page for a run: a dark header naming the run, its window and benchmark, a sidebar of sections, a row of headline cards and, per section, cards holding each chart beside the tables that explain it. The tables compare the strategy with the benchmark by group (returns, risk, risk-adjusted), list the excess over the benchmark and the trading statistics, and, when the run has an in-sample part, set the in-sample and out-of-sample slices side by side. In-sample means the bars the model was trained on; out-of-sample means the bars it never saw, which are the honest test, so the cards and the main tables show the out-of-sample slice whenever the run has both. The sections are Overview (the windows, in-sample against out-of-sample, the Performance chart of equity, drawdown, monthly returns and their year-by-month heatmap, and strategy against benchmark), Excess (cumulative excess return and excess drawdown, and the relative table), Rolling (one-year rolling statistics), Portfolio (turnover, holdings and exposure per rebalance, and the trading table), Holdings when the run’s holdings are given (each bar’s targets, holdings and cash, stepped through by its own small script from data embedded in the page as JSON), Attribution for a model run, Factor attribution for a run with a risk model (quantlab.runs.factor_attribution_report, drawn from the run’s metrics and per-bar factor_attribution.zarr only: this layer imports no risk model) and Setup & notes. Every headline card, metric row and chart carries a plain-English explanation in its title, which the page shows as a tooltip on hover. Charts are drawn on a white plot area with a light grid. backtest_report_figure returns the Performance chart alone, as a plotly figure.

The module holds a catalogue of the metrics it knows, with each one’s group, label, unit and definition, but it renders every metric it is given: a key missing from the catalogue appears in an “Other” table with a unit guessed from its name, and a value it cannot render becomes a dash. That is deliberate, because the report is written inside a run’s staging directory, where an exception would discard the whole run rather than just the page. For the same reason every string that comes from the run passes through html.escape before it reaches the page, and plotly.js is loaded from its CDN so a run directory stays a few kilobytes (viewing the page needs network access).

The page is drawn from what the run recorded: the account record of quantlab.runs.run_metrics (value, returns, fills, settlements, the rebalance record, holdings, initial cash, bar interval and year), the run’s metrics, its target weights, its config mapping and its benchmark record, plus one ReportExtras slot for what only some runs have. Every chart input (turnover, the decided rebalances, the deepest drawdown, the Rolling window, the timeline, the Setup lines, the benchmark curve) is derived here from those, so an executor that simulates elsewhere (an event-driven replay of a quantlab run) writes a page in exactly this format by handing over its own record (ADR 0035). This module imports only the standard library, numpy, pandas, xarray, plotly, quantlab.runs.backtest_stats, quantlab.runs.run_metrics and quantlab.runs.factor_attribution_report.

Classes

ReportExtras

What only some runs put on their page: the one optional slot of write_backtest_report.

Functions

backtest_report_figure

Return the Performance chart of a run's report.html as a plotly figure.

write_backtest_report

Write the HTML report of one backtest run to path, drawn from its record.