Methodology

Every number, finding and status in a Quantgrounds report comes from the fixed rules on this page. A deterministic strategy run with the same settings always gets the same numbers.

What a run does

  1. Security pre-check. The code is parsed, not run, and checked against an import and syntax allowlist. Code that fails is rejected and never executed.
  2. Static code review. The parsed code is checked for known look-ahead patterns and other issues (see Other checks).
  3. Baseline backtest. The strategy runs once over the full history in the sandbox. The engine turns its target weights into positions, costs and returns.
  4. Experiments. The strategy runs again for each parameter change, on each held-out asset, for the look-ahead test and for a determinism check. Cost, execution-delay, regime, out-of-sample and resampling results are computed from the baseline positions and returns.
  5. Findings, statuses, verdict and score are derived from those results by the rules below.

Data

Two fixed data sets, so results are reproducible. Random shards (the default score) draw from the Ken French Data Library: the whole US market and 49 industry portfolios, daily from 1926, value-weighted over every US stock including delisted ones (no survivorship bias). "Your setup" uses adjusted daily closes for SPY (1993–2019) and 20 US stocks (to 2018), a small survivor set for picking specific tickers. Returns are daily simple returns; a year is 252 trading days.

Execution model

The twelve tests

Each test below lists its method and the rule that produces a finding. Severities are critical, high, medium and low.

Test 1

Out-of-sample periods

You declare the development period: the dates you used to design and tune the strategy. One continuous backtest is split into the development period and everything before and after it. A slice needs at least 126 trading days to be reported.

When it raises a finding
  • Finding when the in-sample Sharpe is above 0.3 and the out-of-sample Sharpe is below half of it. High if it is at or below a quarter of it, or if the period after development has a Sharpe at or below zero; otherwise medium.
  • If no development period is declared, a medium finding says the test could not separate the two.
Test 2

Parameter sensitivity

Each numeric value in PARAMS is multiplied by 0.8, 0.9, 1.1 and 1.2 while the others stay fixed, and the strategy is re-run. Integers are rounded; if rounding lands on the original value, the nearest different integer is used.

When it raises a finding
  • Finding ("parameter cliff") when a ±10% change keeps less than 50% of the baseline Sharpe. High below 25%. The test needs a baseline Sharpe above 0.05.
Test 3

Transaction costs

The baseline positions are re-costed at 0x, 1x, 2x, 3x and 5x the cost you set. The break-even cost is the per-side cost at which net CAGR reaches zero, found by bisection between 0 and 1,000 basis points.

When it raises a finding
  • High when there is no positive return even before costs, or when the break-even cost is below 2x your cost. Medium below 3x.
Test 4

Execution delay

The baseline decisions are shifted one trading day later, so each is filled two closes after the signal instead of one, and the result is re-costed.

When it raises a finding
  • Finding when the delayed Sharpe is less than half the baseline Sharpe. High if the delayed Sharpe is at or below zero. The test needs a baseline Sharpe above 0.05.
Test 5

Unseen assets

The same code and parameters run on each declared asset alone and on up to 10 held-out assets with at least three years of data, preferring assets of the same kind (stock or ETF) as the ones you declared.

When it raises a finding
  • Finding when the declared assets' median Sharpe is above 0.2 and either the held-out median Sharpe is below half of it or fewer than half of the held-out assets are profitable. High if fewer than 30% are profitable.
  • A medium finding is also raised if the strategy raises errors on held-out assets.
Test 6

Market regimes

Each day is labeled from trailing SPY data only. The first matching rule wins:

RegimeRule
Bear / crashSPY trailing 126-day return below −10%
High volatilityNot bear, and SPY trailing 21-day realized volatility above 25% annualized
BullNeither of the above, and SPY trailing 126-day return above +10%
SidewaysEverything else
When it raises a finding
  • Medium finding when the worst regime with at least 126 days has a Sharpe below −0.3 and a lower return than the benchmark over the same days.
Test 7

Look-ahead bias

on_bar() cannot see future prices by construction. prepare() can, so when a strategy has one it is tested:

  1. Truncation test. prepare() is recomputed with all data after a cut date deleted, at cuts 30%, 50%, 70% and 90% of the way through the history. Its outputs before each cut are compared with the full-history outputs. Any change proves that past values depend on future data.
  2. Point-in-time re-run. If look-ahead is confirmed, the strategy is re-run with prepare() recomputed on every bar from data up to that bar only. The report shows both results.
When it raises a finding
  • Critical finding when look-ahead is confirmed. The score is capped at 20 and every performance-based test is marked "Not valid".
  • Static look-ahead patterns (see Other checks) are reported as code notes. They are heuristics; the truncation test is the proof.
Test 8

Resampled histories

The strategy's daily net returns are resampled 1,000 times with a circular block bootstrap. The block length is the cube root of the number of days, between 5 and 63 days, so short-range patterns and volatility clustering are kept and overlapping days are never treated as independent. The random seed is fixed. Reports show 90% ranges (5th to 95th percentile) for the Sharpe ratio, CAGR and maximum drawdown. These ranges assume the future resembles this history; they are not forecasts.

When it raises a finding
  • Medium finding when the Sharpe ratio is positive but the lower end of its 90% range is at or below zero.
Test 9

Random timing

A strategy earns money two ways: by how much it is invested, and by when. This test checks the "when". The strategy's own positions are rotated against the market by 1,000 offsets of at least 63 trading days. Each rotation keeps the exposure, the holding periods and the trading costs exactly; only the alignment with what the market did next is broken. Good timing should beat most rotations. This is a Monte Carlo permutation test (Masters 2006; Aronson, Evidence-Based Technical Analysis, 2007). When you declare a development period, it uses the years after it, which your tuning never saw. It is not run when exposure never changes (buy & hold has no timing to test).

When it raises a finding
  • High finding when the strategy beats fewer than 5% of rotations: its timing is worse than random.
  • Medium finding below 50%: no better than random.
  • Low finding below 95%: some evidence, not conclusive. At 95% or more it is listed as a strength.
  • With no skill, the percentile is equally likely to land anywhere from 0 to 100%, so these thresholds are significance levels. In our calibration the coin-flip strategies landed between 3% and 90%.
Test 10

Market exposure

How much of the return is simply the market's? Daily net returns are regressed on SPY's to give beta, annualized alpha (Jensen 1968) and alpha's t-statistic, with Newey-West standard errors because overlapping positions make daily errors correlated. The findings about the edge over buy & hold of the same assets, which caps the score, are reported under this test too.

When it raises a finding
  • High finding when buy & hold of the same assets beat the strategy by more than 0.2 Sharpe; medium when it beat it at all; low when the strategy's edge is under 0.1.
  • Medium finding when alpha is −1% a year or worse with a t-statistic of −2 or below.
  • Low finding when beta is at least 0.3 and alpha's t-statistic is between −1 and 1: the returns are mostly market exposure.
Test 11

Walk-forward

The parameter sets that were already run (your values and each ±10% and ±20% change) are re-ranked every year by their Sharpe over the previous five years. The best one is traded for the next year, and the test years are stitched together. Every choice uses only data available at the time, so the stitched record is what re-tuning once a year would have produced. It re-tunes within that small neighborhood only, so it can't see a wider search you ran before uploading; the research-selection test covers that. It needs about eight years of trading history.

When it raises a finding
  • High finding when the full backtest's Sharpe is above 0.3 and the walk-forward Sharpe is at or below zero.
  • Medium finding when the walk-forward Sharpe is below half the full backtest's, or when fewer than half the test years have a positive Sharpe.
Test 12

Research selection

If you backtest many versions of a strategy and keep the best, its Sharpe is inflated by the selection itself. You say roughly how many variants you tried (rules, parameter values, assets, date ranges). The deflated Sharpe ratio (Bailey and López de Prado, 2014) then estimates the chance that the true Sharpe is above zero, allowing for that many tries, the length of the record, skew and fat tails. Only you know the number, so the test runs only when you give it (under "Your setup"; random shards choose the setup for you, so it doesn't apply there), and it does not change the score. Without it, the report says the selection risk is unknown.

When it raises a finding
  • High finding when the chance is below 50%.
  • Medium finding when it is below 95%.

Random shards (default mode)

A single backtest depends on the setup you chose: the assets, the dates and the cost. In random-shard mode, the default, you choose nothing, and the score comes from many random slices of history instead. The result is the Quantgrounds score.

Other checks

Statuses and verdict

Each row of the stress-test panel takes the most severe finding attached to that test:

Most severe findingStatus
Critical or highFail
MediumWarning
LowNote
NonePass

A test that could not be applied (for example, no development period or no numeric parameters) is marked "Not run". When look-ahead is confirmed, every test except the look-ahead test and the code review is marked "Not valid".

The verdict is one sentence chosen by rule: it describes the test behind the most important critical or high finding. If there is none, it says no major weaknesses were found in these tests and how many tests have warnings.

Scores

There are two names for the same formula, so a report always says which one it is:

Both are a weighted mean of six sub-scores, each from 0 to 100, then two caps. Values between the listed points are interpolated linearly. Every sub-score that looks at returns is judged against buy & hold of the same assets over the same days, because holding is free: a strategy that is half in cash, or flips a coin about being invested, earns a share of the market's return without any skill.

score = min( Σ weight × sub-score ÷ Σ weight used, 50 + 100 × edge )

Sub-scores that cannot be computed (for example, no numeric parameters) are left out and the remaining weights are re-normalized. Scores are shown as whole numbers, with halves rounded up, and the band comes from the number shown.

ScoreBandWhat it means
90–100ExceptionalRare. A large edge over buy & hold that survives every test. We have not seen a public rule reach it.
80–89StrongA clear edge over buy & hold that holds up across the tests.
65–79PromisingSome edge that holds up in most tests.
45–64Mixed resultsLittle or no edge over buy & hold, or an edge with notable weaknesses. Buy & hold itself scores about 50.
25–44WeakDoes worse than buy & hold, or fails several tests.
0–24Serious issuesLoses to buy & hold by a wide margin, or the backtest is invalid (look-ahead).

The score summarizes how the strategy did in these tests. It is not a measure of trading skill or future profitability.

How we check the score

A score is only useful if higher scores go with better results on data the score never saw. We check that with 19 strategies: published rules (trend filters, time-series momentum, volatility targeting, breakouts, short-term mean reversion), buy & hold, and deliberate failures (coin flips, an always-half-invested portfolio, a rule picked from 972 backtests, an overfit strategy and one with look-ahead). Each is scored in random-shard mode on the Ken French universe, cut at the end of 2004 and, separately, the end of 2010. We then measure what it actually did afterwards on a different universe — 15 to 18 real stocks and SPY — over 2005–2010 (including the financial crisis) and 2011–2018.

Higher scores tracked better results on the stocks the score never saw. The rank correlation of score with the following years' Sharpe was +0.61 for 2005–2010 and +0.57 for 2011–2018; a strategy the market beat by more than 0.2 Sharpe scored below the rest in 88% and 82% of pairs. The controls land where they should, and the floor is where the first, absolute-performance formula failed most: it once ranked future losers above the rest more often than not and handed its top score to the always-invested control. Now:

StrategyScore 2004 / 2010What it is
Fast moving-average crossover59 / 59trend rule with a small edge over holding the whole market
200-day trend filter57 / 57trend rule
Buy & hold50 / 50the benchmark itself
Always 50% invested50 / 50exposure without skill
Look-ahead bug20 / 20capped: it uses the future
Best of 972 mined backtests10 / 10data-mined (the old formula missed it, scoring ~47)
Daily coin flip10 / 10random

The strongest published rules — trend-following across the whole market — clear 50 by a few points because timing a diversified universe genuinely beat holding it through 2008; none reaches the upper bands, which require a large, robust edge. The move to the survivorship-bias-free French universe is what lets the score catch data-mining and mean-reversion rules that flattered themselves on a handful of survivor stocks. Future returns over six to eight years are noisy, the 2011–2018 correlation is lower than 2005–2010, and 19 strategies are a small sample, so these checks show the direction of the evidence, not proof. The strategies, the harness and the full results are in the calibration/ folder of the repository.

We ran the same check on the random-timing and market-exposure tests before deciding whether they belong in the score. Both predicted the following years' edge only weakly and inconsistently (rank correlations between +0.13 and +0.35), so they are reported as tests and left out of the score: they explain how a strategy makes money, not whether it beats holding.

Limitations

Sandbox

Strategy code that passes the pre-check runs in a separate process with restricted built-ins, an import allowlist, CPU, memory and time limits, file writes blocked and network access blocked. Each report's code review section records the limits that applied to that run and whether the process ran in an isolated network namespace. Code is passed to the process in memory, never written to disk, and discarded when the run ends. Results are kept in memory for up to an hour so the PDFs can be downloaded.

Verifying a report

A PDF is easy to edit. Each report therefore carries two things that tie its score to the exact code it tested:

To check a report, paste the code on the verify page. The fingerprint is computed in your browser. The page then re-runs the strategy with the replay code's settings, like any other run, and compares the score. A match shows the report's score is what this exact code gets; no key, account or stored record is involved, so any report can be checked, including ones made with the command-line tool. It can't show who wrote the code, whether it was copied, or how it will do in future. A report from an older engine version may not reproduce exactly if the engine or data has changed since.