Metadata-Version: 2.4
Name: katsustats
Version: 0.11.0
Summary: A modernized backtest report module powered by Polars
Project-URL: Homepage, https://github.com/katsu1110/katsustats
Project-URL: Repository, https://github.com/katsu1110/katsustats
Project-URL: Issues, https://github.com/katsu1110/katsustats/issues
Author-email: katsu1110 <code1110g-show@hotmail.co.jp>
License: Apache-2.0
License-File: LICENSE
Keywords: backtest,drawdown,finance,performance-analytics,polars,quant,quantitative-finance,returns,sharpe,trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: matplotlib>=3.9.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: polars>=1.0.0
Description-Content-Type: text/markdown

# Katsustats

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/)
[![CI](https://github.com/katsu1110/katsustats/actions/workflows/ci.yml/badge.svg)](https://github.com/katsu1110/katsustats/actions/workflows/ci.yml)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/katsu1110)

`katsustats` is a Polars-powered analytics and reporting library for daily return series, inspired by [quantstats](https://github.com/ranaroussi/quantstats).

Pass a DataFrame with `date` and `returns`, and get summary metrics, drawdown analysis, key metrics with visualizations, and a self-contained HTML report.

Highlights:

- Polars-first API with pandas input support
- Benchmark-aware performance comparison
- Self-contained offline HTML reports
- AI-friendly structured JSON reports
- Readable Markdown summaries for humans and agents
- Functional modules for `stats`, `plots`, and `reports`

## Preview

| Cumulative returns | Daily returns |
|-----------|-----------------|
| ![Cumulative returns preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/cumulative_returns.png) | ![Daily returns preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/daily_returns.png) |

| Drawdowns | Monthly returns |
|-----------|-----------------|
| ![Drawdown preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/drawdowns.png) | ![Monthly returns preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/monthly_returns.png) |

| Yearly returns | Rolling Sharpe |
|----------------|----------------|
| ![Yearly returns preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/yearly_returns.png) | ![Rolling Sharpe preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/rolling_sharpe.png) |

| Rolling volatility | Day-of-week returns |
|--------------------|---------------------|
| ![Rolling volatility preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/rolling_vol.png) | ![Day-of-week preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/dow.png) |

Those figures are also available in an HTML report generated by `katsustats.reports.html()`.

# How to use

## Installation

**As a Python library:**

```bash
pip install katsustats
# or
uv add katsustats
```

**As a standalone CLI** (no script needed — just install and run):

```bash
pipx install katsustats   # recommended for CLI-only use
# or
uv tool install katsustats
```

**Standalone binary** (no Python needed at all):

Download a pre-built binary for your platform from the [GitHub Releases page](https://github.com/katsu1110/katsustats/releases), make it executable, and run it directly:

```bash
# macOS / Linux
chmod +x katsustats-linux-x86_64
./katsustats-linux-x86_64 report trades.csv -o report.html
```

## Try it online

- [Open in Google Colab](https://colab.research.google.com/drive/1PnbZdvZboEtV8F8gjrF3oTrQ3IzC5CdT?usp=sharing)
- [Open in Kaggle](https://www.kaggle.com/code/code1110/katsustats-quickstart)

## Data format

`katsustats` accepts either a [Polars](https://pola.rs/) or pandas DataFrame
with two required columns:

| column | type | description |
|--------|------|-------------|
| `date` | date-like | Trading date |
| `returns`  | float-like | Daily return (e.g. `0.01` = +1%) |

When a pandas DataFrame or Series is passed, `katsustats` converts it to
Polars at the start of processing.

If `date` is datetime-like, it is normalized to `pl.Date` before analysis.

If multiple rows share the same `date`, `katsustats` compounds those same-day
`returns` values into one daily return, emits a warning, and continues.

Quantstats-style inputs (``pd.Series`` with a ``DatetimeIndex``, or a
``pd.DataFrame`` with a ``DatetimeIndex`` and a ``returns`` column) are
accepted automatically — the index is promoted to the ``date`` column.

## Basic usage

```python
import polars as pl
import katsustats

# Build your return series
returns = pl.DataFrame({
    "date": pl.date_range(pl.date(2020, 1, 1), pl.date(2023, 12, 31), "1d", eager=True),
    "returns": your_daily_returns,   # list / numpy array of floats
})

# Generate the full report (prints metrics + shows all plots)
results = katsustats.reports.full(returns)
```

Pandas DataFrames work the same way, and quantstats-style `DatetimeIndex`
inputs are accepted automatically (see [Data format](#data-format)). Runnable
examples: [`examples/quickstart.py`](examples/quickstart.py),
[`examples/with_benchmark.py`](examples/with_benchmark.py), and
[`examples/html_report.py`](examples/html_report.py).

`results` is a dict with the following keys:

| key | type | description |
|-----|------|-------------|
| `summary` | `dict[str, float]` | Raw numeric summary values |
| `metrics` | `pl.DataFrame` | Summary metrics table |
| `drawdowns` | `pl.DataFrame` | Top-5 drawdown periods |
| `dow_stats` | `pl.DataFrame` | Day-of-week statistics |
| `figures` | `dict[str, Figure]` | All 8 matplotlib figures |

## With a benchmark

```python
benchmark = pl.DataFrame({
    "date": pl.date_range(pl.date(2020, 1, 1), pl.date(2023, 12, 31), "1d", eager=True),
    "returns": benchmark_daily_returns,
})

results = katsustats.reports.full(returns, benchmark=benchmark)
```

When a benchmark is provided, the metrics table also includes **Alpha**, **Beta**, **Correlation**, **Information Ratio**, and **Excess Return**.

## Advanced options

```python
results = katsustats.reports.full(
    returns,
    benchmark=benchmark,
    rf=0.04,          # annualized risk-free rate (default 0.0)
    periods=252,      # trading days per year (default 252)
    show=False,       # suppress inline plot display
)
```

## CLI

Generate a report directly from a CSV or Parquet file — no script needed:

```bash
# HTML tearsheet (default)
katsustats report trades.csv -o report.html

# Structured JSON for AI agents / downstream tooling
katsustats report trades.csv --format json -o report.json

# Markdown summary for humans and agents
katsustats report trades.csv --format markdown -o report.md

# Custom column names, benchmark, and title
katsustats report trades.csv --date-col day --returns-col pnl --benchmark benchmark.csv --title "My Strategy" -o report.html
```

If `-o` is omitted the report is written alongside the input file (for example `trades.html`, `trades.json`, or `trades.md`). Run `katsustats report --help` for all options (including `--periods 365` for crypto data, `--rf`, and `--monte-carlo`).

## Reports

Generate a self-contained report in any of three formats:

```python
# Save to file
katsustats.reports.html(returns, benchmark=benchmark, title="My Strategy", output="report.html")
katsustats.reports.json(returns, benchmark=benchmark, title="My Strategy", output="report.json")
katsustats.reports.markdown(returns, benchmark=benchmark, title="My Strategy", output="report.md")

# Or get the string directly
html_str = katsustats.reports.html(returns, title="My Strategy")
```

| format | function | CLI | example |
|--------|----------|-----|---------|
| HTML | `reports.html()` | `katsustats report trades.csv -o report.html` | [btc_eth_report.html](examples/reports/btc_eth_report.html) |
| JSON | `reports.json()` | `katsustats report trades.csv --format json -o report.json` | [btc_eth_report.json](examples/reports/btc_eth_report.json) |
| Markdown | `reports.markdown()` | `katsustats report trades.csv --format markdown -o report.md` | [btc_eth_report.md](examples/reports/btc_eth_report.md) |

All formats include headline metrics, performance and period-performance tables, top drawdowns, and day-of-week statistics; a benchmark adds regime analysis.

The HTML report embeds all 8 charts in a single offline file:

[**View a BTC vs ETH backtest report**](https://htmlpreview.github.io/?https://github.com/katsu1110/katsustats/blob/main/examples/reports/btc_eth_report.html).

![HTML Report Preview](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/html_report.png)

## Monte Carlo simulation

Pass `monte_carlo=True` to `reports.html()` or `reports.full()` to resample your historical returns thousands of times and see the range of outcomes luck alone could have produced:

```python
katsustats.reports.html(
    returns,
    output="report.html",
    monte_carlo=True,
    mc_sims=1000,       # number of simulated paths (default 1000)
    mc_bust=-0.20,      # optional: probability of hitting this drawdown
    mc_goal=0.50,       # optional: probability of reaching this return
    mc_seed=42,         # optional: reproducibility seed
    mc_method="bootstrap",  # "bootstrap" (default) or "shuffle"
)
```

`bootstrap` samples returns **with replacement**, so terminal return, Sharpe, and CAGR vary across paths. `shuffle` permutes without replacement, so terminal return is identical across paths, but max drawdown still varies — drawdown is path-dependent: a run of losses early hurts far more than the same losses late.

The HTML report adds two panels:

| Simulated paths | Max drawdown distribution |
|-----------------|--------------------------|
| ![Monte Carlo paths](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/monte_carlo_simulations.png) | ![Max drawdown distribution](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/simulated_max_drawdown.png) |

You can also call the underlying stats directly:

```python
# Raw simulation paths as a wide Polars DataFrame
paths = katsustats.stats.monte_carlo_paths(returns, sims=1000, seed=42, method="bootstrap")

# Probabilistic summary: terminal return, max drawdown, Sharpe, CAGR distributions
summary = katsustats.stats.monte_carlo_summary(
    returns,
    sims=1000,
    bust=-0.20,   # drawdown threshold for bust probability
    goal=0.50,    # return threshold for goal probability
    seed=42,
    method="bootstrap",
)
```

## Snapshot report

Generate a compact, single-image performance card (a "snapshot") showing key metrics, an equity curve, and underwater drawdowns. This is perfect for quick sharing on social media or in chat.

| Light Theme | Dark Theme |
|-------------|------------|
| ![Snapshot light mode](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/snapshot_light.png) | ![Snapshot dark mode](https://raw.githubusercontent.com/katsu1110/katsustats/main/img/snapshot_dark.png) |

**Via CLI:**
```bash
# Save a snapshot for the last 1 Month
katsustats snapshot trades.csv --window 1M -o snapshot.png

# Custom title and longer window
katsustats snapshot trades.csv --title "My Strategy" --window 3M -o snapshot.png

# Dark theme for social media sharing
katsustats snapshot trades.csv --theme dark -o snapshot.png
```

**Via Python:**
```python
import katsustats

fig = katsustats.plots.plot_snapshot(returns, window="3M", title="My Strategy")
fig.savefig("snapshot.png")

# Dark mode
fig = katsustats.plots.plot_snapshot(returns, window="3M", title="My Strategy", theme="dark")
fig.savefig("snapshot_dark.png", facecolor=fig.get_facecolor())
```

## Metrics produced

| metric | description |
|--------|-------------|
| Total Return | Compounded return over the full period |
| CAGR | Compound Annual Growth Rate |
| Sharpe Ratio | Annualized risk-adjusted return |
| Sortino Ratio | Sharpe using only downside deviation |
| Max Drawdown | Largest peak-to-trough decline |
| Calmar Ratio | CAGR / \|Max Drawdown\| |
| Volatility (ann.) | Annualized standard deviation |
| Win Rate | % of days with positive returns |
| Profit Factor | Gross profit / gross loss |
| Best / Worst Day | Largest single-day gain / loss |
| Avg Win / Avg Loss | Mean return on winning / losing days |
| Daily VaR (95%) | 5th-percentile daily return |
| CVaR (95%) | Mean return in the worst 5% tail |
| Recovery Factor | Total return / \|Max Drawdown\| |
| Skewness / Kurtosis | Distribution shape statistics |
| Best / Worst Month | Largest / smallest monthly return |
| Best / Worst Year | Largest / smallest yearly return |
| Positive Months / Years | Share of profitable months / years |

When a benchmark is provided, `katsustats` also reports **Alpha**, **Beta**, **Correlation**, **Information Ratio**, and **Excess Return**.

## Lower-level APIs

`katsustats.stats` exposes 60+ metric functions (rolling metrics, drawdown details, benchmark comparisons, Monte Carlo, and more) and `katsustats.plots` exposes 18 chart functions — all documented in their docstrings. See [`examples/`](examples/) for runnable usage.
