ruin
A Polars-first risk metrics library for quant hedge funds.
Installation
pip install pyruin
# or with optional SciPy extras (reserved for future use):
pip install "pyruin[stats]"
Distributed on PyPI as
pyruin(the nameruinwas taken). The import name is unchanged:import ruin.
Quickstart
import polars as pl
import ruin
returns = pl.Series([0.01, -0.02, 0.03, -0.01, 0.02, ...]) # daily returns
sr = ruin.sharpe_ratio(returns, periods_per_year=252)
mdd = ruin.max_drawdown(returns)
df = ruin.summary(returns, periods_per_year=252)
Module Overview
| Module | What it computes |
|---|---|
ruin.returns |
from_prices, total_return, annualize_return, cagr |
ruin.volatility |
volatility, annualize_volatility, downside_deviation, semi_deviation |
ruin.drawdown |
drawdown_series, max_drawdown, average_drawdown, max_drawdown_duration, recovery_time, time_underwater, drawdown_start, drawdown_end |
ruin.ratios |
sharpe_ratio, sortino_ratio, calmar_ratio, information_ratio, treynor_ratio, omega_ratio |
ruin.tail |
value_at_risk, conditional_value_at_risk / expected_shortfall |
ruin.market |
beta, downside_beta, upside_beta, alpha, tracking_error, correlation, up_capture, down_capture |
ruin.distribution |
skewness, excess_kurtosis, jarque_bera, autocorrelation |
ruin.activity |
hit_rate, average_win, average_loss, win_loss_ratio, profit_factor, best_period, worst_period, longest_winning_streak, longest_losing_streak |
ruin.rolling |
Rolling versions of all major metrics, returning length-aligned pl.Series |
ruin.periods |
mtd, qtd, ytd, trailing, since_inception, periods_per_year_for, annual_to_periodic, periodic_to_annual |
ruin.inference |
sharpe_standard_error, sharpe_confidence_interval, bootstrap_metric |
ruin.report |
summary — the one bundled function |
Composition Principle
This library provides building blocks. If you want a bundled metric, call summary() or compose the primitives yourself. Every function returns exactly one thing. We will not add bundled convenience functions.
Composition in Polars is cheap. A custom bundle is two lines:
import polars as pl
import ruin
# Rolling Sharpe with bootstrap confidence intervals
returns = pl.Series(your_returns)
# Rolling Sharpe (returns a Series)
rs = ruin.rolling_sharpe(returns, window=60, periods_per_year=252)
# Bootstrap CI on the scalar Sharpe
point, lo, hi = ruin.bootstrap_metric(
lambda r: ruin.sharpe_ratio(r, periods_per_year=252),
returns,
n_samples=1000,
confidence=0.95,
)
print(f"Sharpe: {point:.3f} ({lo:.3f}, {hi:.3f})")
Call multiple functions and compose:
metrics = {
"sharpe": ruin.sharpe_ratio(returns, periods_per_year=252),
"sortino": ruin.sortino_ratio(returns, periods_per_year=252),
"max_dd": ruin.max_drawdown(returns),
"cvar": ruin.conditional_value_at_risk(returns),
}
What This Library Is Not
The following are explicitly out of scope. Do not open issues requesting them.
- Money-weighted returns / IRR / fee crystallization — needs cash flows; belongs in a sibling library.
- Portfolio construction — optimization, risk parity, mean-variance, Black-Litterman.
- Factor models — Fama-French, Barra-style attribution, Brinson attribution.
- Backtesting engine — trade simulation, transaction costs, execution modeling.
- Data fetching — no yfinance, no Bloomberg, no CSV readers.
- Time series hygiene — resampling, calendar alignment, gap filling, corporate actions.
- Stress testing / Monte Carlo / scenario analysis.
- Forecasting — no GARCH, EWMA, regime models, volatility prediction.
- Plotting — use Polars + Altair/Plotly/Matplotlib directly.
- Pandas support — use Polars.
pd.Series.to_numpy()converts in one call if needed. - Cornish-Fisher VaR — reserved for a future
ruin[stats]extra.
Design Principles
- Returns in, numbers out. No prices, no positions, no trades, no I/O.
- Polars-first, minimal deps. Runtime:
polars+numpyonly. - Pure functions. No side effects, no hidden state.
- One function, one metric, one return type. Scalar →
float, rolling →pl.Series. - Explicit over implicit.
periods_per_yearis always explicit.risk_freeis per-period. - NaN handling. Drop by default;
strict=Trueinsummary()raises instead.
Sign Conventions
- Drawdowns are non-positive:
-0.23means 23% drawdown. - VaR and CVaR are positive loss magnitudes (desk convention):
0.02means "lose at most 2%."
See docs/conventions.md for library-wide behaviour
(sign conventions, NaN policy, input types, alignment).
See docs/metrics.md for per-metric definitions, formulas,
assumptions, and citations.
Metadata
Release files for pyruin 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyruin-0.1.1.tar.gz | 19.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyruin-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.2 kB
Release files / pyruin-0.1.1.tar.gz
| Download URL | pyruin-0.1.1.tar.gz |
|---|---|
| Size | 19.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a9e0e50263087f9fe7afdbe9dab7d35f46504124078109abe04522f37d5392e3
|
|
BLAKE2b-256 checksum How to use checksums |
fd065d49d3d0d7997975ca813280b8718bae1d95e5c60302a120d79fe90fc0be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 17, 2026.
Transparency logRelease files / pyruin-0.1.1-py3-none-any.whl
| Download URL | pyruin-0.1.1-py3-none-any.whl |
|---|---|
| Size | 25.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f0935ff4d99c8d94da6159de60ef63b2b10bd68e0cf46dd7e23974b5f38bf404
|
|
BLAKE2b-256 checksum How to use checksums |
265d2a6f999b2faa64f7568378b41c0ca6a7c3f67df88bc4f31f0c2a1b03869b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 17, 2026.
Transparency log