Skip to main content

jsharpe

PyPI version License: MIT Coverage Downloads CodeFactor

A Python library for rigorous Sharpe ratio analysis and statistical testing.

Overview

jsharpe provides comprehensive tools for evaluating trading strategies through the lens of statistical significance. Based on the research of Marcos Lopez de Prado, this library goes beyond simple Sharpe ratio calculations to answer the critical question: Is this strategy's performance statistically significant, or could it be due to chance?

Key Features

  • Probabilistic Sharpe Ratio (PSR) - Transform Sharpe ratios into probabilities that account for estimation uncertainty
  • Non-Gaussian Returns - Correct for skewness and excess kurtosis in return distributions
  • Autocorrelation Adjustment - Handle serial correlation in returns
  • Multiple Testing Corrections - Control False Discovery Rate (FDR) and Family-Wise Error Rate (FWER) when testing multiple strategies
  • Minimum Track Record Length - Determine how long you need to observe a strategy for statistical significance
  • Portfolio Optimization - Minimum variance portfolio weights for correlated assets

Installation

Install jsharpe from PyPI:

pip install jsharpe

Quick Start

Basic Probabilistic Sharpe Ratio

from jsharpe import probabilistic_sharpe_ratio

# Observed Sharpe ratio: 0.456 (e.g., 3.6% return / 7.9% volatility)
sr = 0.036 / 0.079

# Compute PSR with 24 monthly observations
# Testing against SR0=0 (no skill)
psr = probabilistic_sharpe_ratio(SR=sr, SR0=0, T=24)
print(f"PSR: {psr:.3f}")  # Output: PSR: 0.987

The PSR of 0.987 means there's a 98.7% probability that the true Sharpe ratio exceeds zero.

Accounting for Non-Gaussian Returns

Real returns often exhibit negative skewness and excess kurtosis (fat tails):

from jsharpe import probabilistic_sharpe_ratio

sr = 0.036 / 0.079

# Include skewness and kurtosis estimates
psr = probabilistic_sharpe_ratio(
    SR=sr, 
    SR0=0, 
    T=24, 
    gamma3=-2.448,  # Negative skewness
    gamma4=10.164   # Excess kurtosis
)
print(f"PSR (adjusted): {psr:.3f}")  # Output: PSR (adjusted): 0.987

Minimum Track Record Length

How long must you observe a strategy to claim it's significantly better than a benchmark?

from jsharpe import minimum_track_record_length

# Strategy with SR=0.5, testing against SR0=0 at 95% confidence
months_needed = minimum_track_record_length(SR=0.5, SR0=0, alpha=0.05)
print(f"Months needed: {months_needed:.1f}")

Testing Multiple Strategies

When testing many strategies, control the False Discovery Rate:

from jsharpe import control_for_FDR

# Test 10 strategies, controlling FDR at 25%
alpha, beta, SR_critical, q_hat = control_for_FDR(
    q=0.25,           # Target FDR
    SR0=0,            # Null hypothesis
    SR1=0.5,          # Alternative hypothesis
    p_H1=0.05,        # Prior prob of true signal
    T=24              # Observations per strategy
)

print(f"Critical SR threshold: {SR_critical:.3f}")
print(f"Only accept strategies with SR > {SR_critical:.3f}")

Variance of Sharpe Ratio Estimates

from jsharpe import sharpe_ratio_variance
import math

# Variance under Gaussian assumptions
var_gaussian = sharpe_ratio_variance(SR=0.5, T=24)
print(f"Std error (Gaussian): {math.sqrt(var_gaussian):.3f}")

# Variance with fat tails (higher kurtosis)
var_fat_tails = sharpe_ratio_variance(SR=0.5, T=24, gamma4=6.0)
print(f"Std error (fat tails): {math.sqrt(var_fat_tails):.3f}")
PSR: 0.987
PSR (adjusted): 0.987
Months needed: 10.8
Critical SR threshold: 0.479
Only accept strategies with SR > 0.479
Std error (Gaussian): 0.217
Std error (fat tails): 0.234

Core Functions

  • probabilistic_sharpe_ratio() - Compute PSR with various adjustments
  • sharpe_ratio_variance() - Variance of SR estimator under non-Gaussian returns
  • minimum_track_record_length() - Min observations for significance
  • critical_sharpe_ratio() - Threshold for hypothesis testing
  • sharpe_ratio_power() - Statistical power of SR test
  • control_for_FDR() - False Discovery Rate control for multiple testing
  • adjusted_p_values_bonferroni() - Bonferroni correction
  • adjusted_p_values_holm() - Holm's step-down procedure
  • adjusted_p_values_sidak() - Šidák correction
  • minimum_variance_weights_for_correlated_assets() - Portfolio optimization

Documentation

References

This library implements methods from:

  • Bailey, D. H., & López de Prado, M. (2012). "The Sharpe Ratio Efficient Frontier." Journal of Risk, 15(2), 3-44.
  • Bailey, D. H., & López de Prado, M. (2014). "The Deflated Sharpe Ratio: Correcting for Selection Bias, Backtest Overfitting and Non-Normality." Journal of Portfolio Management, 40(5), 94-107.

For Developers

Setup Development Environment

# Clone the repository
git clone https://github.com/tschm/jsharpe.git
cd jsharpe

# Install dependencies and setup environment
make install

This installs uv, creates a virtual environment, and installs all dependencies.

Development Workflow

# Run tests
make test

# Format code
make fmt

# Start interactive notebooks
make marimo

Project Structure

jsharpe/
├── src/jsharpe/       # Main package source code
│   ├── __init__.py    # Public API exports
│   └── sharpe.py      # Core implementations
├── tests/             # Test suite
│   ├── test_sharpe.py    # Unit tests
│   ├── test_migration.py # Parity tests vs. the original implementation
│   └── fuzz/             # Atheris fuzz harness
├── book/              # Documentation and interactive notebooks
│   └── marimo/        # Marimo notebooks for exploration
└── pyproject.toml     # Project metadata and dependencies

Contributing

We welcome contributions! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes and add tests
  4. Run make test and make fmt
  5. Commit your changes (git commit -m 'Add some amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

See CONTRIBUTING.md for more details.

Running Tests

# Run all tests with coverage
make test

# Run specific test file
pytest tests/test_sharpe.py -v

License

MIT License - see LICENSE file for details.

Citation

If you use jsharpe in your research, please cite:

@software{jsharpe,
  author = {Thomas Schmelzer},
  title = {jsharpe: Probabilistic Sharpe Ratio and Statistical Testing},
  year = {2024},
  url = {https://github.com/tschm/jsharpe}
}

Metadata

Release files for jsharpe 0.6.3

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

Source distribution (sdist)

Source distribution for jsharpe 0.6.3
File Size Uploaded
jsharpe-0.6.3.tar.gz 7.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for jsharpe 0.6.3
File Interpreter ABI Platform
jsharpe-0.6.3-py3-none-any.whl Python 3 none any Details

Total release size: 7.2 MB

Release files / jsharpe-0.6.3.tar.gz

Download URL jsharpe-0.6.3.tar.gz
Size 7.2 MB
Tags Source
SHA-256 checksum
How to use checksums
82f0bc9f3d325c9e0545b05e09f7c8a243e6b6a4c600cb4328cb4b46dee8112e
BLAKE2b-256 checksum
How to use checksums
5508880c43ff5890f498c9f5f770c5cb0f78be23d51783c3cf66df345560376b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 9, 2026.

Transparency log

Release files / jsharpe-0.6.3-py3-none-any.whl

Download URL jsharpe-0.6.3-py3-none-any.whl
Size 22.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2a0a715936ab6eeced16cec8ee70626c301f0d624ab0ccdfa2d8173b0b2ac674
BLAKE2b-256 checksum
How to use checksums
cc9829c83a86fb5ac98905799dde177bf3d6d123aae9bef51668a7bf714e2173
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

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 Jul 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.3 This release

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.2

2 release files

0.0.1

2 release files

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