quantstats-rs 0.1.0

Rust implementation of QuantStats-style performance tear sheets with SVG charts and HTML reports.
Documentation
# quantstats-rs

`quantstats-rs` is a Rust library that generates QuantStats-style HTML performance tear sheets
from return time series. It aims to closely match the behaviour and visuals of the original
Python [QuantStats](https://github.com/ranaroussi/quantstats) project.

Preview of the benchmark tear sheet:
![Quantstats-rs demo tear sheet with benchmark](tearsheet_with_benchmark.png)

## Features

- Generate full HTML tear sheets from:
  - A single strategy return series; or
  - A strategy + benchmark pair.
- Metrics table (see `PerformanceMetrics`), including:
  - CAGR, Sharpe, Sortino, Calmar
  - Max / average drawdown, longest drawdown
  - Gain-to-Pain and related ratios
- Charts (SVG, embedded in the HTML):
  - Cumulative Returns / Cumulative Returns vs Benchmark
    (including log-scaled and volatility-matched variants)
  - Daily Returns (Cumulative Sum)
  - Rolling Volatility / Rolling Sharpe / Rolling Sortino / Rolling Beta
  - Drawdown (Underwater)
    (average drawdown red dashed line, filled area below 0%)
  - Strategy – Worst 5 Drawdown Periods
  - EOY Returns / EOY Returns vs Benchmark (with red dashed mean line)
  - Monthly Returns Heatmap
  - Returns Distribution / Monthly Distribution
- Visual alignment with Python QuantStats:
  - Matching colour scheme (strategy `#348dc1`, benchmark `#ff9933`, etc.)
  - Proportional grid, labelled y-axis, bottom time axis
  - Dashed zero / mean lines and filled areas (e.g. Underwater Plot)

## Repository Layout

- `src/`
  - `lib.rs` – public API: `html`, `HtmlReportOptions`, `ReturnSeries`, `PerformanceMetrics`.
  - `reports.rs` – report assembly, metrics table rendering, and template filling.
  - `stats.rs` – performance statistics and drawdown segment logic.
  - `plots.rs` – all SVG chart generation.
  - `report_template.html` – HTML template, roughly mirroring QuantStats’ `report.html`.
- `examples/`
  - `html_report.rs` – strategy only; writes `tearsheet.html`.
  - `html_with_benchmark.rs` – strategy + benchmark; writes `tearsheet_with_benchmark.html`.
  - `common.rs` – shared demo data, generated from `data/` by the script.
- `data/` – CSVs / time series used to build the example report.
- `scripts/gen_examples_common.py` – generates `examples/common.rs` from `data/`.

## Build & Run

From the repository root:

```bash
cargo build

# Strategy-only demo report (writes `tearsheet.html`)
cargo run --example html_report

# Strategy + benchmark demo report (writes `tearsheet_with_benchmark.html`)
cargo run --example html_with_benchmark

# Tests (if present)
cargo test
```

The generated HTML files can be opened directly in a browser and visually compared against
reports produced by the Python QuantStats library.

## Library Usage

Add a dependency (path here assumes your project is a sibling of this repo):

```toml
[dependencies]
quantstats-rs = { path = "../quantstats-rs" }
```

Basic usage in Rust:

```rust
use chrono::NaiveDate;
use quantstats_rs::{ReturnSeries, HtmlReportOptions, html};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Prepare dates and returns (e.g. daily returns)
    let dates: Vec<NaiveDate> = /* ... */;
    let values: Vec<f64> = /* ... */; // e.g. 0.01 means +1%

    let strategy = ReturnSeries::new(dates, values, Some("Strategy".to_string()))?;

    // 2. Configure report options
    let options = HtmlReportOptions::default()
        .with_title("My Strategy Tearsheet")
        .with_strategy_title("My Strategy")
        .with_output("tearsheet.html");

    // 3. Generate HTML string and write to file (if `output` is set)
    let html_string = html(&strategy, options)?;

    println!("Report generated ({} bytes)", html_string.len());
    Ok(())
}
```

With a benchmark:

```rust
let strategy: ReturnSeries = /* ... */;
let benchmark: ReturnSeries = /* ... */;

let options = HtmlReportOptions::default()
    .with_benchmark(&benchmark)
    .with_title("Strategy vs Benchmark")
    .with_strategy_title("Strategy")
    .with_benchmark_title("Benchmark")
    .with_output("tearsheet_with_benchmark.html");

let html_string = html(&strategy, options)?;
```

## Example Data & Regeneration

The example binaries use `examples/common.rs`, which is generated from `data/`:

```bash
python3 scripts/gen_examples_common.py
```

After changing the data under `data/`, re-run the script and then rerun the examples
to regenerate `tearsheet.html` and `tearsheet_with_benchmark.html`.

## Alignment with Python QuantStats

This implementation uses the vendored Python QuantStats code and its HTML output
as the reference. The following aspects are intentionally aligned:

- Rolling Vol / Sharpe / Sortino / Beta:
  - Axis ranges, grid density, and line styles (including red dashed mean lines).
- Underwater Plot:
  - Filled area below 0% in strategy colour.
  - Red dashed line at the average drawdown.
  - Solid underwater curve.
- Strategy – Worst 5 Drawdown Periods:
  - Y-axis and grid styling.
  - Label positions for the “N: Xd” drawdown annotations.
- EOY Returns vs Benchmark:
  - Bar layout and colours.
  - Red dashed mean line for strategy returns.
- Time axis handling:
  - Bottom-aligned date labels for all time-series charts.
  - Label thinning to avoid overlap (e.g. around dense months like 2025‑10 / 2025‑11).

If you notice discrepancies compared to a Python QuantStats report (especially in a
specific chart such as “Rolling Sortino” or “Underwater Plot”), please open an issue or
PR and mention:

- Which chart (title),
- Which part differs (axis range, grid, colours, etc.),
- Optionally, a snippet or screenshot from the Python-generated HTML.