Skip to main content

An honest reality-check for trading strategies — Deflated Sharpe Ratio + sealed out-of-sample holdout.

Project description

OverfitGuard

An honest reality-check for trading strategies. Before you risk a dollar on a backtest, answer the one question that actually matters: is this a real edge, or did I fool myself?

Search hard enough over historical data and you will always find something that looks brilliant in-sample — by pure luck. OverfitGuard applies the discipline that separates a real edge from a data-mined mirage, and it refuses to bless anything that can't survive it:

  • Deflated Sharpe Ratio (Bailey & López de Prado, 2014) — penalises your Sharpe for how many strategies you tried, how long your track record is, and how fat-tailed your returns are.
  • Sealed out-of-sample holdout — the "does it still work on data it has never seen" test that catches regime-fitting the deflation math can't.
  • White's Reality Check (Sullivan, Timmermann & White) — judges a whole search at once: was the best of your 500 configs real, or just the luckiest?

Two independent defenses on a single strategy, plus a family-wise test for a search. Dependency-light (just numpy/pandas), framework-agnostic, and it never sees your data source, broker, or secret sauce.

Install

pip install overfitguard          # once published to PyPI
# or from source:
pip install -e ".[test]"

Library — 30 seconds

import pandas as pd
from overfitguard import validate, screen

# One strategy — be honest about how many configs you tried:
result = validate(my_returns, n_trials=250, benchmark=spy_returns)
print(result.verdict)             # LIKELY_REAL / INCONCLUSIVE / LIKELY_OVERFIT / ...
print(result.report())

# A whole search — was the best candidate real?
print(screen(all_candidate_returns).report())   # candidates = DataFrame, one column each

Command line

overfitguard validate returns.csv --trials 250 --benchmark spy.csv --html report.html
overfitguard screen candidates.csv --bootstrap 2000 --html screen.html

--html writes a self-contained, theme-aware report you can open in any browser or hand to a client. See two real outputs without installing anything: a caught mirage (FAILS_OUT_OF_SAMPLE) and a genuine edge (LIKELY_REAL) — proof the verdict swings both ways. Regenerate either with the command above on the matching *_returns.csv.

The verdicts

Verdict Meaning
LIKELY_REAL Survives deflation for the trials you tried and holds up out-of-sample.
SURVIVES_DEFLATION_BUT_DECAYS_OOS Significant, but the edge shrinks on unseen data. Caution.
INCONCLUSIVE Out-of-sample positive, but too short / too modest to prove for the trials tried.
FAILS_OUT_OF_SAMPLE The edge vanishes or reverses on data the search never saw — the classic mirage.
LIKELY_OVERFIT A search that wide would produce a Sharpe this good by luck.
BEST_IS_SIGNIFICANT / NO_STRATEGY_BEATS_LUCK (search screen) the best candidate beats — or doesn't — what that many random tries throw up.

Why it's honest

The number that fools most people is the in-sample Sharpe — and OverfitGuard treats a high one as expected, not as evidence. If you tell it you tried one strategy when you really tried a thousand, the sealed holdout is there to catch the decay anyway.

It will not tell you that you found alpha. It will tell you whether you have earned the right to believe it — which is rarer, and worth far more.

Learn the ideas — the companion course

Fooled by Backtests is a short, free course that teaches these defenses by using this tool on real data — including a research program that rigorously tested a dozen strategy families and found buy-and-hold beat essentially all of them. It ends with hands-on labs: manufacture a mirage and watch it get caught, screen 250 candidates for the one real edge, and — the capstone — audit your own strategy in one command.

Limitations & how to read the verdict

OverfitGuard is deliberately a skeptic. Understand these before you use it:

  • INCONCLUSIVE is common, and it does not mean "fake." The engine is tuned for a low false-positive rate (≈5% at the 95% bar, confirmed by Monte-Carlo calibration), which costs it power: a genuine edge with a modest Sharpe or a short track record — especially one found after many trials — will often read INCONCLUSIVE. That is the honest answer ("promising, not proven"), not a rejection. More data is the cure.
  • A LIKELY_REAL at n_trials=1 is still a 5%-false-positive test. If you under-report how many configurations you tried, you are weakening the deflation — the sealed holdout is the backstop, but be honest with n_trials.
  • screen() tests each candidate's mean return against zero (cash), not against a benchmark. It answers "does the best of these have positive expected return beyond luck?" — not "does it beat buy-and-hold." Bring your own benchmark by screening excess-over-benchmark returns.
  • Approximations, stated plainly: the deflation's multiplicity bar uses the strategy's own Sharpe estimator variance as a proxy for the dispersion of your trial Sharpes; and the out-of-sample check is a single 35% holdout, which is itself noisy (purged K-fold cross-validation is on the roadmap).
  • It is a research / due-diligence tool, not financial advice. LIKELY_REAL means "you have earned the right to believe it," not "trade this."

Project layout

overfitguard/
  pyproject.toml            # pip-installable, exposes the `overfitguard` CLI
  index.html                # self-contained landing page (GitHub Pages front door)
  src/overfitguard/         # core.py · screen.py · report.py · cli.py
  tests/                    # 23 tests (core, screener, CLI)
  examples/                 # quickstart.py + two sample HTML reports (a catch and a pass)
  course/                   # "Fooled by Backtests" — 5 chapters + hands-on labs + capstone
  .github/workflows/ci.yml  # tests on 3.9 / 3.11 / 3.12

License

MIT. OverfitGuard is a research/due-diligence tool — it does not give financial advice, and LIKELY_REAL is not a recommendation to trade.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

overfitguard-0.2.0.tar.gz (86.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

overfitguard-0.2.0-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file overfitguard-0.2.0.tar.gz.

File metadata

  • Download URL: overfitguard-0.2.0.tar.gz
  • Upload date:
  • Size: 86.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for overfitguard-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ff3d74b09ad0ded7944bfec7c3b94603fea60d97318f303a1dd61b1f37dcafd9
MD5 e20224a32c0bc1786077396d97a5100b
BLAKE2b-256 0005a1c1f335cd1527d79614a44806493560a65f8b558dc16ae17ccd252ae74e

See more details on using hashes here.

Provenance

The following attestation bundles were made for overfitguard-0.2.0.tar.gz:

Publisher: publish.yml on anpeterlin/overfitguard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file overfitguard-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: overfitguard-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for overfitguard-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4e9259664bbcd0f3b35fd94c0ccf25b14481c299fb3db877437bbbc2ece2c28f
MD5 871604c582b0fa757b33f77b3fb247a1
BLAKE2b-256 db84f4df179cd507b87e6d9fe79003ba92d773a9456141e694e4b289f55acf99

See more details on using hashes here.

Provenance

The following attestation bundles were made for overfitguard-0.2.0-py3-none-any.whl:

Publisher: publish.yml on anpeterlin/overfitguard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page