Skip to main content

sharpebench (Python)

Is my Sharpe real, or an artifact of luck and multiple testing?

Python distribution of SharpeBench's luck-robust quantitative evaluation statistics, a pyo3 binding over the same deterministic Rust kernel used by the SharpeBench CLI and the @general-liquidity/sharpebench npm package. Bring your own return series; everything takes plain numeric sequences (lists, tuples, numpy arrays, df["ret"].to_numpy()) and returns plain floats, lists and dicts.

import numpy as np
from sharpebench import is_my_sharpe_real, bootstrap_dsr_ci

returns = df["strategy_ret"].to_numpy()          # per-period, NOT annualized

# n_trials is the honest one: how many variants did you try before keeping this?
# periods_per_year says what a row is (default 252, daily bars).
v = is_my_sharpe_real(returns, n_trials=200, periods_per_year=252)
print(v["sharpe"], v["deflated_sharpe"], v["verdict"], v["explanation"])

ci = bootstrap_dsr_ci(returns, n_trials=200)
print(ci["lower"], ci["point"], ci["upper"])

Surface

Function Answers
sharpe_ratio(returns) observed per-period Sharpe
moments(returns, target=0.0) mean / std / skew / kurtosis / downside deviation / Sortino
probabilistic_sharpe_ratio(returns, sr_benchmark=0.0) PSR: one minus the p-value of H0: SR <= benchmark (not the probability the true Sharpe exceeds it). sr_benchmark is per period
deflated_sharpe_ratio(returns, n_trials, trials_sr_std=None, periods_per_year=None) PSR against the best of n_trials zero-skill trials (DSR): one minus a p-value, not the probability of skill. trials_sr_std is per period; omitted, it is the annualized 0.5 prior over sqrt(periods_per_year) (default 252)
expected_max_sharpe(trials_sr_std, n_trials) the per-period Sharpe the best of n_trials shows with zero skill, from a per-period trials_sr_std
min_track_record_length(returns, ...) periods needed before the Sharpe is believable; sr_benchmark is per period
bootstrap_dsr_ci(returns, n_trials, ...) {point, se, lower, upper} on the DSR itself; trials_sr_std / periods_per_year as in deflated_sharpe_ratio
bootstrap_pvalue(excess, ...) stationary-bootstrap p-value for one series
is_my_sharpe_real(returns, n_trials=1, ..., periods_per_year=None) LITE verdict dict: pass | borderline | fail + explanation. trials_sr_std and sr_benchmark are annualized and periods_per_year (default 252, flagged) converts both
is_my_sharpe_real_full(field, ...) FULL verdict over a whole candidate field (LITE + snooping family + PBO + HLZ)
reality_check_pvalue(field, ...) White's Reality Check over the field
spa_pvalue / spa_consistent_pvalue(field, ...) Hansen's SPA (liberal / consistent)
step_down_significant(field, ..., alpha=0.05) Romano-Wolf step-down, per candidate, FWER-controlled
probability_of_backtest_overfitting(perf_matrix, s=16) CSCV PBO
benjamini_hochberg(p_values, q=0.05) / fdr_verdict(...) BH-FDR rejections and the operator summary
hlz_gate(t_stat, t_threshold=None) the Harvey-Liu-Zhu |t| >= 3.0 factor bar
selection_robustness(candidates, n_trials, ...) best vs median DSR: is the headline a lucky pick? trials_sr_std / periods_per_year as in deflated_sharpe_ratio
runs_for_power(effect, alpha, power) how many runs to detect an effect
pass_k(passed_per_run, mode="all", n=None) pass^k reliability: won on every run, not on average
budget_curve(...) DSR by search budget, marginal DSR, and the non-improvement onset. trials_sr_std is annualized (default 0.5) and converted by periods_per_year (default 252)
rank_board(submissions, config_json="") / score_one(...) Full composite scoring over the CLI-compatible JSON contract
rank_returns(field, config_json="") Build and rank a board from agent IDs and per-run return arrays
default_score_config() Serialize the default scoring configuration
never_catastrophic_config() Serialize the preset that asks only whether every run avoids catastrophe
relative_to_benchmark_config(id) Serialize the benchmark-relative pass preset

Units of the deflation prior

Every Sharpe here is per period. The verdicts (is_my_sharpe_real*) and budget_curve take trials_sr_std annualized, like the leaderboard's ScoreConfig, and divide it by sqrt(periods_per_year). The verdicts take their PSR and MinTRL sr_benchmark annualized too and convert it the same way; through 0.21.0 they read it per period. The raw probabilistic_sharpe_ratio and min_track_record_length take sr_benchmark per period. The raw primitives (deflated_sharpe_ratio, bootstrap_dsr_ci, selection_robustness, expected_max_sharpe) take it per period and use an explicit value as given. Omitted, the first three use the annualized 0.5 prior at periods_per_year (default 252): 0.5 / sqrt(252) = 0.0315 per period on daily returns. Through 0.19.0 they used 0.5 per period, an annualized dispersion of about 7.9 on daily returns.

deflated_sharpe_ratio(returns, n_trials=200)                         # 0.5 / sqrt(252) per period
deflated_sharpe_ratio(returns, n_trials=200, periods_per_year=8760)  # hourly: 0.5 / sqrt(8760)
deflated_sharpe_ratio(returns, n_trials=200, trials_sr_std=0.02)     # your per-period value, as given

Matrix orientation

Two conventions, deliberately unchanged from the papers they come from:

  • the data-snooping family (reality_check_pvalue, spa_*, step_down_significant, is_my_sharpe_real_full) takes a field: N rows (strategies) x T cols (time);
  • probability_of_backtest_overfitting takes the transpose: T rows (time) x N cols (strategies).

Determinism

No I/O, no clock, no ambient randomness. The bootstraps take an explicit seed (defaulted to a fixed constant, so a result is reproducible unless you ask for otherwise). The Python suite matches the public example board to the committed Rust golden on Ubuntu CI. Rust CI separately checks two committed golden fields on Linux, macOS, and Windows; neither check covers every possible input or host.

Relationship to sharpearena

sharpearena is the environment: a point-in-time market API where a trading agent produces a track, scored end-to-end by its score_run helper. It does not provide process containment. sharpebench is the judge for a track you already have: your own backtest, live P&L, or a field of candidate strategies. They share one Rust statistics kernel, so the verdict is identical either way; this package simply does not, and will not, duplicate arena run-scoring.

Building from source

python -m pip install maturin
python -m maturin develop --manifest-path crates/sharpebench-py/Cargo.toml
python -m pytest crates/sharpebench-py/tests

MIT OR Apache-2.0.

Metadata

Release files for sharpebench 0.22.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sharpebench 0.22.0
File Size Uploaded
sharpebench-0.22.0.tar.gz 392.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for sharpebench 0.22.0
File
sharpebench-0.22.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
sharpebench-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
sharpebench-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
sharpebench-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details

Total release size: 3.1 MB

Release files / sharpebench-0.22.0.tar.gz

Download URL sharpebench-0.22.0.tar.gz
Size 392.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d4f6cb9e96bdcff0d16761b4e872e9af92c705a1d78948b65deacb5af8a4190d
BLAKE2b-256 checksum
How to use checksums
579109254504b94c2edcb5a44b5fa59df9bbdd72266d7b1aa57500dc9a7fd797
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log

Release files / sharpebench-0.22.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL sharpebench-0.22.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 668.2 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
02ac55af3e1eedb74d166ac410b127b8cd9607a768b7e5c39b890321a3415aa3
BLAKE2b-256 checksum
How to use checksums
f574f90784ad6c9a08ba8d745a17638f47c06d42b1081659926dcb68d76b4a4c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log

Release files / sharpebench-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL sharpebench-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 668.8 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
58390ea61b6e4d036ecbaff5d8b7c16d341a5dc26ae57c609d2335b27b76c0ea
BLAKE2b-256 checksum
How to use checksums
0befdab0f3a670c4e4e6685f202eb3f918d4b50057f8b43ccf475bb43d73d466
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log

Release files / sharpebench-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL sharpebench-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 673.6 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
08d66a7240e41fdac6e53446da8a628cc7ffd66cf3f9bec7b0122cf53caaf5b4
BLAKE2b-256 checksum
How to use checksums
7786d397ef28ad67d878be2e1c99e1442c290b257fbee77a4c99af8b12945198
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log

Release files / sharpebench-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL sharpebench-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 673.6 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
16a586cdb5671169f7921a47491ca59546b65cb4691305ae6cc5a3a470cbf8a5
BLAKE2b-256 checksum
How to use checksums
5affeb911513ffacfec2f1f1228b4a48b0f7ac5d345d2e25dd55775a62dde47f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 10, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page