Home Verified Methods Reports Papers Methodology About
Home › Worked examples › PSR Verification Report: A Published Example, Corrected

PSR Verification Report: A Published Example, Corrected

Verdict

The worked example previously published on this site was arithmetically wrong, for months. It was found by computing it rather than reading it, corrected against scipy, and every intermediate value is now shown so it can be checked by hand.

Verification record
v1.0 · first run 16 August 2026 · published as a report 4 September 2026
Implementation under test
tools/probabilistic-sharpe-ratio-calculator.html and the worked example on the paper, in the public repository
Environment
Python 3.11.9; numpy 2.4.6; pandas 3.0.5; scipy 1.17.1 — all newer than the package pins, so this doubles as a forward-compatibility check
Verifier
Cemil Ertürk
Status
Independent. Not peer reviewed. Synthetic data only; no claim about any real security.

With an observed Sharpe of 1.50, 24 observations, skewness of −1.20 and kurtosis of 7.00, the Probabilistic Sharpe Ratio against a zero benchmark is 99.81%. Here is the arithmetic behind that result, including the denominator that is easy to miscalculate.

Use consistent units

Sharpe and the benchmark must be expressed at the observation frequency. For monthly observations, use monthly Sharpe values; do not enter an annualized Sharpe alongside a count of monthly returns. Kurtosis here is ordinary kurtosis, where a normal distribution has value 3, not excess kurtosis.

Inputs

Observed Sharpe SR1.50 per observation period
Benchmark SR*0.00 per observation period
Observations n24
Skewness g1−1.20
Kurtosis g27.00

Calculate without intermediate rounding

denominator = sqrt(1 - g1*SR + ((g2 - 1)/4)*SR^2) = sqrt(1 + 1.80 + 1.5*2.25) = sqrt(6.175) = 2.484954727958 z = (SR - SR*) * sqrt(n - 1) / denominator = 1.5 * sqrt(23) / sqrt(6.175) = 2.8949208628 PSR = standard_normal_cdf(z) = 0.9981037293 = 99.81% (rounded)

The normal-return case still has a kurtosis term. Setting skewness to zero and kurtosis to 3 gives sqrt(1 + 0.5 × 1.50²) = 1.4577, not 1. Zero excess kurtosis does not remove (g2 − 1)/4 from this formula.

Change the question

Raise the benchmark from 0 to 1 while keeping the other inputs fixed. The z-statistic becomes 0.9650 and PSR falls to 83.27%, below a 95% threshold. The observed record is the same; the claim being tested is stronger.

Open the free calculator with these default inputs. It calculates locally in your browser and displays both the denominator and z.

Reproduce with Python

from math import erf, sqrt sr, benchmark, n, skew, kurtosis = 1.5, 0.0, 24, -1.2, 7.0 den = sqrt(1 - skew*sr + ((kurtosis - 1)/4)*sr**2) z = (sr - benchmark)*sqrt(n - 1)/den psr = (1 + erf(z/sqrt(2)))/2 print(f"den={den:.10f}, z={z:.10f}, PSR={psr:.10f}")

This check uses Python's standard library. The browser calculator uses an error-function approximation, so compare at the displayed precision rather than requiring identical last digits.

What the percentage does not mean

PSR is not the probability of a profitable next trade. Its interpretation depends on the statistical assumptions, including independent returns and reliable moment estimates. It does not account for costs or the number of strategy variants tried. Selection across many backtests needs a separate correction such as the Deflated Sharpe Ratio.

Arithmetic checked 4 September 2026. The earlier worked example printed z = 2.8955; the correct value rounded to four decimals is 2.8949. This correction leaves the displayed PSR of 99.81% unchanged.

Defect found during verification

Quantity (SR 1.50, SR* 0, n 24)As originally publishedCorrect
Denominator, γ₁ = 0, γ₂ = 31.0001.4577
Denominator, γ₁ = −1.20, γ₂ = 7.002.3182.4850
z-statistic (skewed, fat-tailed case)2.89552.8949
PSR (skewed, fat-tailed case)—0.9981
The kurtosis term does not vanish at γ₂ = 3

The original example treated the “normal” case as having a denominator of exactly 1, as though zero excess kurtosis removed the term. It does not: the formula uses (γ₂ − 1)/4, which at γ₂ = 3 is 0.5, so the denominator is √(1 + 0.5·1.5²) = √2.125 = 1.4577. The same slip propagated to the skewed case: √(1 + 1.80 + 1.5·2.25) = √6.175 = 2.4850, not 2.318. Throughout, γ₂ is Pearson (non-excess) kurtosis: a normal distribution has γ₂ = 3, not 0.

The z-statistic that followed was published as 2.8955. It does not follow from the corrected denominator: 1.5·√23 / 2.484955 = 2.8949; 2.8955 would need a denominator of 2.4845. A reader on r/quant pinned this on 10 September 2026, and the table above now records both values. PSR is 0.9981 either way.

Detection: evaluating the formula in scipy instead of trusting the prose. Fix: paper, explainer and calculator now agree and show every intermediate. Guard: the calculator computes rather than quotes, and scripts/test_psr.js exercises it.

Why it matters

PSR is a test people use to decide whether a backtest is trustworthy. An implementation that understates the denominator overstates the z-statistic and reports more confidence than the data supports — in the direction that makes bad strategies look good.

What this verification does not establish

Reproduce

from scipy.stats import norm; norm.cdf(1.5*23**0.5/2.4850) → 0.9981. Or open the calculator with SR 1.50, SR* 0, n 24, skew −1.20, kurtosis 7.00.