A modernized backtest report module powered by Polars
Project description
Katsustats
A simple backtest tool for your return series, inspired by quantstats.
Put your return series, and you get backtest results with visualizations and key metrics.
How to use
Installation
pip install katsustats
Or with uv:
uv add katsustats
Data format
katsustats accepts either a Polars or pandas DataFrame
with two required columns:
| column | type | description |
|---|---|---|
date |
pl.Date |
Trading date |
pnl |
pl.Float64 |
Daily return (e.g. 0.01 = +1%) |
When a pandas DataFrame is passed, katsustats converts it to Polars at the
start of processing.
Basic usage
import polars as pl
import katsustats
# Build your return series
pnl = pl.DataFrame({
"date": pl.date_range(pl.date(2020, 1, 1), pl.date(2023, 12, 31), "1d", eager=True),
"pnl": your_daily_returns, # list / numpy array of floats
})
# Generate the full report (prints metrics + shows all plots)
results = katsustats.reports.full(pnl)
Pandas inputs work too:
import pandas as pd
pnl = pd.DataFrame({
"date": dates,
"pnl": your_daily_returns,
})
results = katsustats.reports.full(pnl)
results is a dict with the following keys:
| key | type | description |
|---|---|---|
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 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),
"pnl": benchmark_daily_returns,
})
results = katsustats.reports.full(pnl, base_pnl=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(
pnl,
base_pnl=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
)
HTML report
Generate a self-contained HTML report (similar to qs.reports.html()):
# Save to file
katsustats.reports.html(pnl, base_pnl=benchmark, title="My Strategy", output="report.html")
# Or get HTML string
html_str = katsustats.reports.html(pnl, title="My Strategy")
The report includes headline metric cards, performance tables, drawdown analysis, day-of-week statistics, and all 8 charts embedded as images — all in a single .html file that works offline.
Using individual modules
import katsustats
# --- Stats ---
katsustats.stats.total_return(pnl)
katsustats.stats.cagr(pnl)
katsustats.stats.sharpe(pnl, rf=0.0)
katsustats.stats.sortino(pnl)
katsustats.stats.max_drawdown(pnl)
katsustats.stats.calmar(pnl)
katsustats.stats.volatility(pnl)
katsustats.stats.win_rate(pnl)
katsustats.stats.profit_factor(pnl)
katsustats.stats.value_at_risk(pnl, alpha=0.05)
katsustats.stats.drawdown_details(pnl, top_n=5) # pl.DataFrame
katsustats.stats.day_of_week_stats(pnl) # pl.DataFrame
katsustats.stats.summary_metrics(pnl, base_pnl) # pl.DataFrame
# --- Plots ---
katsustats.plots.plot_cumulative_returns(pnl, base_pnl)
katsustats.plots.plot_drawdown(pnl)
katsustats.plots.plot_monthly_heatmap(pnl)
katsustats.plots.plot_yearly_returns(pnl, base_pnl)
katsustats.plots.plot_return_distribution(pnl, base_pnl)
katsustats.plots.plot_rolling_sharpe(pnl, base_pnl)
katsustats.plots.plot_rolling_volatility(pnl, base_pnl)
katsustats.plots.plot_dow_returns(pnl)
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 |
| Recovery Factor | Total return / |Max Drawdown| |
| Skewness / Kurtosis | Distribution shape statistics |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file katsustats-0.2.3.tar.gz.
File metadata
- Download URL: katsustats-0.2.3.tar.gz
- Upload date:
- Size: 165.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc61c92f67045079c5a8679048092a0dfb77157ef887e4ccc4aaa161ea2f5335
|
|
| MD5 |
4847043cc64b1e47bcd00b87f92833c7
|
|
| BLAKE2b-256 |
cc29a7feec938ca450ea5b178287ed47daeb768c27e6e1db10bf9c720be238e1
|
Provenance
The following attestation bundles were made for katsustats-0.2.3.tar.gz:
Publisher:
publish.yml on katsu1110/katsustats
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
katsustats-0.2.3.tar.gz -
Subject digest:
dc61c92f67045079c5a8679048092a0dfb77157ef887e4ccc4aaa161ea2f5335 - Sigstore transparency entry: 1386007202
- Sigstore integration time:
-
Permalink:
katsu1110/katsustats@b5ca413ef26de755692790aaf02e0cf2c7a9921f -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/katsu1110
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b5ca413ef26de755692790aaf02e0cf2c7a9921f -
Trigger Event:
release
-
Statement type:
File details
Details for the file katsustats-0.2.3-py3-none-any.whl.
File metadata
- Download URL: katsustats-0.2.3-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f3ea067fe15dce7618a6bb186a11b1fdb4683c25dec3ccea8fcc76da052cde6
|
|
| MD5 |
b267276c852ba2f6633e470a63b8daac
|
|
| BLAKE2b-256 |
665461aeb4dcc699852a0691090f3a8a5a66ebf944377c23f0d68c1f10d68670
|
Provenance
The following attestation bundles were made for katsustats-0.2.3-py3-none-any.whl:
Publisher:
publish.yml on katsu1110/katsustats
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
katsustats-0.2.3-py3-none-any.whl -
Subject digest:
0f3ea067fe15dce7618a6bb186a11b1fdb4683c25dec3ccea8fcc76da052cde6 - Sigstore transparency entry: 1386007311
- Sigstore integration time:
-
Permalink:
katsu1110/katsustats@b5ca413ef26de755692790aaf02e0cf2c7a9921f -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/katsu1110
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b5ca413ef26de755692790aaf02e0cf2c7a9921f -
Trigger Event:
release
-
Statement type: