Metadata-Version: 2.4
Name: katsustats
Version: 0.7.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 inputs work too:

```python
import pandas as pd

returns = pd.DataFrame({
    "date": dates,
    "returns": your_daily_returns,
})

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

### Migrating from quantstats

If your existing code passes a ``pd.Series`` or a ``pd.DataFrame`` with a
``DatetimeIndex`` (the quantstats convention), both work without modification:

```python
import pandas as pd

# pd.Series with DatetimeIndex
returns = pd.Series(your_daily_returns, index=date_index, name="returns")
results = katsustats.reports.full(returns)

# pd.DataFrame with DatetimeIndex
returns = pd.DataFrame({"returns": your_daily_returns}, index=date_index)
results = katsustats.reports.full(returns)
```

See also the runnable examples in [`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 an HTML tearsheet directly from a CSV or Parquet file — no script needed:

```bash
# From a CSV file (date and returns columns)
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
katsustats report trades.csv --date-col day --returns-col pnl -o report.html

# With a benchmark and a custom title
katsustats report trades.csv --benchmark benchmark.csv --title "My Strategy" -o report.html

# From a Parquet file with a custom risk-free rate
katsustats report trades.parquet --rf 0.04 -o report.html

# Crypto data (365 days/year) with Monte Carlo
katsustats report crypto.csv --periods 365 --monte-carlo --mc-method bootstrap -o report.html
```

If `-o` is omitted the report is written alongside the input file (for example `trades.html`, `trades.json`, or `trades.md`).

## HTML report

Generate a self-contained HTML report (similar to `qs.reports.html()`):

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

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

The report includes headline metric cards, performance tables, period performance, drawdown analysis, day-of-week statistics, and all 8 charts embedded as images — all in a single `.html` file that works offline.

When a benchmark is provided, the HTML report also includes regime analysis.

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

## JSON report

Generate an AI-friendly structured JSON report (see [example](examples/reports/btc_eth_report.json)):

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

# Or get JSON string
json_str = katsustats.reports.json(returns, title="My Strategy")
```

The JSON output is optimized for LLMs, agents, and other automation tools. It
includes raw numeric metrics, structured period performance, top drawdowns,
day-of-week statistics, and regime analysis when a benchmark is provided.

## Markdown report

Generate a Markdown backtest summary (see [example](examples/reports/btc_eth_report.md)):

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

# Or get Markdown string
md_str = katsustats.reports.markdown(returns, title="My Strategy")
```

The Markdown output is designed to be readable in editors, GitHub, chat tools,
and agent workflows. It includes an overview, headline metrics, performance
tables, period performance, top drawdowns, day-of-week statistics, and optional
regime analysis.

## Monte Carlo simulation

Enable Monte Carlo analysis by passing `monte_carlo=True` to `reports.html()` or `reports.full()`. The simulation resamples your historical returns thousands of times (bootstrap by default) to show the range of outcomes that luck alone could have produced — keeping the same return distribution while breaking the original time order.

```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"
)
```

The default `bootstrap` method samples returns **with replacement**, producing genuine variation in terminal return, Sharpe, and CAGR across paths. Use `mc_method="shuffle"` for the classic permutation approach (sampling without replacement), where terminal return is identical across all paths but max drawdown still varies due to path-dependent ordering.

The HTML report adds two panels to the Monte Carlo section:

| 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) |

- **Simulated paths** — fan of simulated cumulative return paths with the original path highlighted. Shows how differently the same returns could have played out under alternative orderings.
- **Max drawdown distribution** — histogram of the worst drawdown across each simulated path. Because drawdown is path-dependent (a run of losses early hurts far more than the same losses late), this distribution has genuine spread and tells you how lucky or unlucky your drawdown sequence was.

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())
```

## Using individual modules

You can also call the lower-level APIs directly:

```python
import katsustats

# --- Stats ---
katsustats.stats.total_return(returns)
katsustats.stats.cagr(returns)
katsustats.stats.sharpe(returns, rf=0.0)
katsustats.stats.sortino(returns)
katsustats.stats.max_drawdown(returns)
katsustats.stats.calmar(returns)
katsustats.stats.volatility(returns)
katsustats.stats.win_rate(returns)
katsustats.stats.profit_factor(returns)
katsustats.stats.value_at_risk(returns, alpha=0.05)

katsustats.stats.drawdown_details(returns, top_n=5)      # pl.DataFrame
katsustats.stats.day_of_week_stats(returns)              # pl.DataFrame
katsustats.stats.summary_metrics(returns, benchmark)     # pl.DataFrame

# --- Plots ---
katsustats.plots.plot_cumulative_returns(returns, benchmark)
katsustats.plots.plot_drawdown(returns)
katsustats.plots.plot_monthly_heatmap(returns)
katsustats.plots.plot_yearly_returns(returns, benchmark)
katsustats.plots.plot_return_distribution(returns, benchmark)
katsustats.plots.plot_rolling_sharpe(returns, benchmark)
katsustats.plots.plot_rolling_volatility(returns, benchmark)
katsustats.plots.plot_dow_returns(returns)
```

## 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**.
