Skip to main content

A modernized backtest report module powered by Polars

Project description

Katsustats

License Python CI Ruff Sponsor

katsustats is a Polars-powered analytics and reporting library for daily return series, inspired by 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
  • Functional modules for stats, plots, and reports

Preview

Cumulative returns Daily returns
Cumulative returns preview Daily returns preview
Drawdowns Monthly returns
Drawdown preview Monthly returns preview
Yearly returns Rolling Sharpe
Yearly returns preview Rolling Sharpe preview
Rolling volatility Day-of-week returns
Rolling volatility preview Day-of-week preview

Live example

View a BTC vs ETH backtest report — generated by katsustats.reports.html() with a benchmark, showing headline metrics, period performance, drawdown analysis, regime breakdown, and all 8 charts in a single self-contained HTML file.

How to use

Installation

As a Python library:

pip install katsustats
# or
uv add katsustats

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

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, make it executable, and run it directly:

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

Try it online

Data format

katsustats accepts either a Polars 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

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:

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:

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/with_benchmark.py, and 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

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

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:

# From a CSV file (date and returns columns)
katsustats report trades.csv -o report.html

# 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

If -o is omitted the report is written alongside the input file (e.g. trades.html).

HTML report

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

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

Using individual modules

You can also call the lower-level APIs directly:

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

katsustats-0.4.0.tar.gz (831.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

katsustats-0.4.0-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

File details

Details for the file katsustats-0.4.0.tar.gz.

File metadata

  • Download URL: katsustats-0.4.0.tar.gz
  • Upload date:
  • Size: 831.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for katsustats-0.4.0.tar.gz
Algorithm Hash digest
SHA256 26f2b028ae081eb0edbb69b6ab2e805ef288329192aba69944f2d9d51605c7b2
MD5 10751e6d26655ba1cfca4ae96e3417b3
BLAKE2b-256 3bfb2f6ae7cd553f7d25ed0ea861d36c4528cca388e65fca0b466707a2d2a441

See more details on using hashes here.

Provenance

The following attestation bundles were made for katsustats-0.4.0.tar.gz:

Publisher: publish.yml on katsu1110/katsustats

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file katsustats-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: katsustats-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 32.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for katsustats-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a79fb231e3b1171453d666080e69cc373346bbc03da9c36478539d07a4eb3d23
MD5 2d3be2f2718f65318cf2595b00d6998c
BLAKE2b-256 dfaeb214d874425316954f84181e11d1f88f452743b1aecd4cd4c632a2f7c5f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for katsustats-0.4.0-py3-none-any.whl:

Publisher: publish.yml on katsu1110/katsustats

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page