Skip to content

Interactive Backtest Report Demo

Below is an interactive backtest report generated by AKQuant. You can interact directly with the charts on this page to view detailed backtest data.

Benchmark Comparison

BacktestResult.viz.report accepts a benchmark return series:

benchmark_returns = (
    benchmark_df.set_index("date")["close"].pct_change().fillna(0.0)
)
result.viz.report(
    filename="akquant_report.html",
    benchmark=benchmark_returns,
    show=False,
)

When benchmark is provided, the HTML report adds a benchmark comparison section with strategy/benchmark/excess cumulative curves and relative metrics (total excess, annual excess, tracking error, information ratio, beta, alpha).

Structured Benchmark Analysis

AKQuant now exposes the benchmark comparison logic as a structured analysis payload that can be reused by web frontends, APIs, and offline pipelines instead of relying on HTML parsing.

benchmark_returns = (
    benchmark_df.set_index("date")["close"].pct_change().fillna(0.0)
)

payload = result.benchmark_analysis(
    benchmark=benchmark_returns,
    curve_freq="D",
)

print(payload["schema_version"])
print(payload["summary"]["annual_excess"])
print(payload["series"][0])

The payload includes:

  • schema_version: contract version for downstream consumers
  • available: whether benchmark analysis is available
  • reason: validation or alignment message when analysis is unavailable
  • benchmark.label: display label of the selected benchmark
  • summary: aggregate metrics such as total_excess, annual_excess, tracking_error, information_ratio, beta, and alpha
  • series: aligned daily points with strategy, benchmark, excess, and cumulative series
  • meta: sample count, start/end date, and annualization settings

Recommended practice:

  • Prepare the benchmark return series on the backend
  • Call result.benchmark_analysis(...) once after the backtest
  • Let the frontend render summary + series + meta
  • Reuse the same analysis payload for both result.viz.report(..., benchmark=...) and the frontend view

Export for Frontend or Archival

You can persist the benchmark analysis as part of the backtest artifacts:

result.export_benchmark_analysis(
    path="artifacts/benchmark_analysis.json",
    benchmark=benchmark_returns,
    format="json",
    curve_freq="D",
)

format="parquet" is also supported and writes:

  • series.parquet: aligned benchmark time series
  • metadata.json: summary metrics and metadata

Interactive LWC Trade Review

result.viz.review() renders an offline, self-contained single-file HTML powered by TradingView Lightweight Charts, overlaying buy/sell markers on the K-line for large-volume or intraday trade review.

It complements result.viz.report() rather than replacing it: analytical charts (equity curve, drawdown, heatmaps, attribution) stay with report()'s plotly output; review() only fills the "interactive candlesticks + trade markers" gap for bar-by-bar timing review.

# market_data is a single DataFrame or a {symbol: df} dict
path = result.viz.review(
    market_data=df,
    title="AKQuant Trade Review",
    theme="dark",          # initial theme "light" / "dark"; toggled in-page
    filename="akquant_review.html",
    show=False,            # True opens the browser automatically
)

Notes:

  • The HTML inlines lightweight-charts with no CDN dependency, so it opens and archives offline.
  • A light/dark toggle button sits in the top bar; theme only sets the initial theme. Switching recolors instantly with no file regeneration.
  • Multi-symbol input ({symbol: df}) adds a symbol selector at the top; initial_symbol sets which one is shown first.
  • Column names are case-insensitive and Chinese names are supported (开盘/最高/最低/收盘/成交量/日期, etc.).
  • Daily data uses a YYYY-MM-DD axis; intraday data automatically switches to a time-of-day axis.
  • Optimized for large / intraday datasets: the payload is built with vectorized ops and timestamps are de-duplicated, so tens of thousands of candles stay smooth (the core advantage over the plotly analytical charts).

See examples/67_lwc_trade_review.py for a full example.