Skip to content

feat(quantitative): deflated Sharpe ratio command - #7633

Open
ipezygj wants to merge 1 commit into
OpenBB-finance:developfrom
ipezygj:feat/deflated-sharpe-ratio
Open

feat(quantitative): deflated Sharpe ratio command#7633
ipezygj wants to merge 1 commit into
OpenBB-finance:developfrom
ipezygj:feat/deflated-sharpe-ratio

Conversation

@ipezygj

@ipezygj ipezygj commented Aug 8, 2026

Copy link
Copy Markdown

Why

obb.quantitative.performance ships Sharpe, Sortino and Omega — but no way to answer the question that decides whether any of them mean anything after optimization: was this result selected as the best of N attempts, and does it survive that selection? Under pure noise, the expected maximum Sharpe of N zero-skill strategies grows with N; a raw Sharpe from a parameter sweep is a best-of-N number.

What

obb.quantitative.performance.deflated_sharpe_ratio(data=returns, target="close", trials=100) — the Deflated Sharpe Ratio (Bailey & López de Prado, 2014): the probability that the true Sharpe exceeds the expected maximum of trials zero-skill attempts, adjusting for sample length and return skewness/kurtosis. Returns Sharpe, the expected-max bar, the DSR probability, observations and trials.

  • helpers.deflated_sharpe_stats() holds the pure computation; the router command follows the existing omega_ratio pattern (POST, DeflatedSharpeModel, lazy imports, PythonEx/APIEx examples).
  • trials_sr_std (cross-trial Sharpe dispersion) defaults to the null 1/sqrt(n-1); callers who track their optimizer's actual trial spread can pass it through the helper.
  • scipy only — already a dependency of this extension.

Tests

extensions/quantitative/tests/test_deflated_sharpe.py: parity at 1e-7 against the numguard reference implementation on a deterministic series, single-trial-reduces-to-PSR, monotonicity in trial count, input guards. 5/5 passing locally alongside the existing helper tests.

The same math was merged into ffn last week (pmorissette/ffn#311), and equivalents are under review in backtesting.py (kernc/backtesting.py#1388) and jesse (jesse-ai/jesse#611).

Note: I haven't regenerated the static package reference in this PR — happy to run the build step and push it if you'd like it included, or leave it to your release tooling, whichever matches your process.

Adds obb.quantitative.performance.deflated_sharpe_ratio (Bailey & Lopez
de Prado, 2014): the probability that a strategy's true Sharpe exceeds
the expected maximum Sharpe of N zero-skill trials, answering whether a
result selected as the best of N tested variants reflects skill or
selection luck. Adjusts for sample length and return skewness/kurtosis.

- helpers.deflated_sharpe_stats(): pure computation, parity-tested at
  1e-7 against the numguard reference implementation
- DeflatedSharpeModel + POST command in the performance router,
  following the omega_ratio pattern
- trials_sr_std defaults to the null 1/sqrt(n-1); callers who track
  their optimizer's actual cross-trial Sharpe dispersion can pass it
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants