FIELD NOTES · 2026-07-29

The bug that makes your backtest look good — and why you can't see it

We found it in our own code while auditing a result we'd already decided was a failure. It had been quietly inflating our numbers for weeks. It throws no error, it corrupts only some of your rows, and in cheap stocks it always makes you look better. Here is exactly how it works.

The thing nobody tells you about historical prices

A stock's price history is not a fixed fact. It is a function of when you asked.

When a company splits its stock, data providers go back and restate the entire prior price series. They have to. A 1-for-10 reverse split takes a $0.50 stock to $5.00 overnight, and if the history weren't restated, every chart would show a 900% one-day gain and every moving average would break.

So the vendor multiplies all the earlier prices by an adjustment factor. Reverse split of 1-for-10: multiply history by 10. Forward split of 2-for-1: halve it. The line stays smooth, the indicators keep working, and everybody is happy.

The consequence is easy to miss: download Apple's 2019 prices in 2019, and again today, and you get different numbers — because of the 2020 split. The past changed. It will change again.

How that turns into invented profit

Any calculation that mixes a price captured at the time with a price downloaded later is comparing two different unit systems. It's a dollars-versus-cents error wearing a plausible disguise.

Here is precisely what happened in our code:

ValueWhere it came fromNumber
Entry priceRecorded at grading time, as actually traded$0.50
Same session's closeRe-downloaded months later, after a 1-for-10 reverse split$5.00
Computed return(5.00 − 0.50) / 0.50+900%

The stock did nothing. The trade never happened. But the arithmetic is impeccable, and across a few hundred trades a single row like that is enough to drag an average up by ten percentage points — which is roughly what it did to us.

The part almost nobody knows: the error flips sign by universe

This is what makes it genuinely dangerous rather than merely annoying.

Microcaps do reverse splits. Constantly — usually to claw back above the $1 minimum an exchange requires for continued listing. Reverse splits adjust history upward, so every contaminated row shows a spurious gain.

Large caps do forward splits, when the share price has climbed high enough to be inconvenient. Those adjust history downward, producing spurious losses.

So in exactly the universe where retail traders run backtests — cheap, volatile, heavily promoted stocks — this bug systematically makes results look better. It flatters you precisely where you are least equipped to notice.

If you have ever backtested penny stocks and been pleasantly surprised, this is the first thing to rule out.

Why it survives review

  1. It is completely silent. No exception, no warning. Just numbers that are slightly too kind.
  2. It only touches a minority of rows — the ones with a corporate action in the window. So your aggregates look plausible-but-encouraging rather than obviously broken. Nobody investigates a good result as hard as a bad one.
  3. It corrupts selectively, in a pattern that looks like a finding. In our case it only inflated rules whose exit was an actual market price — sell at the close, trailing stops, time exits. Rules with a capped exit (take profit at +10%) compute their exit as entry × 1.10, so a corrupted bar could change whether the target was hit but never the size of the payoff. Those stayed clean. The result was a table where most rules looked mediocre and three looked like winners. That reads as "some strategies work" — which is exactly the shape of answer you were hoping for.
  4. The corrupted row is usually your best trade, and nobody deletes their best trade to see if the conclusion holds.

And the reason most people simply cannot catch this

The bug is invisible unless you kept a forward-only record of prices as they were at the time.

We only found it because there was a stored, append-only price to disagree with. We recomputed the same-day return from the grade-time record for all 379 picks that had one: mean −2.86% against a stored −2.86%, maximum difference 0.0, zero mismatches. Perfect agreement. That isolated the corruption instantly to the 65 picks that had no stored path and therefore went through a re-download.

A backtest that re-downloads everything on every run has nothing to reconcile against. The error is undetectable — and the results are unreproducible — for the same underlying reason. If your backtest can't reproduce its own numbers from a stored record, it also can't tell you when the data moved under it.

What it cost us

Our exit study reported the baseline — simply selling at the end of the first day — as +8.0% average net per trade. The true figure is −2.9%.

Three exit rules carried a marker meaning "beats the baseline by at least 2 points." All three were artifacts. After the fix:

Exit ruleReportedActual
Sell at the first day's close (baseline)+8.0%−2.9%
Trailing 15% stop+10.9%−4.6%
Trail 15% after a +10% touch+11.8%−6.2%
Exit at day 1's close+6.1%−4.4%
Hold to day 5's close−2.4%−10.5%

With correct data, not one of the 23 exit rules we tested beats simply selling at the first day's close. Before the fix, three appeared to. We had been looking at a table that said "your instinct was right" when the data said the opposite.

How to check your own work

In rough order of how much they buy you:

  1. Store prices forward-only, at decision time, and never re-pull them. Write down what you saw when you saw it. This is the only defence that works by construction rather than by vigilance.
  2. If you must re-pull, reconcile. Recompute something you already stored and require exact agreement before the row is allowed into the study. We now demand that every trade reproduce its recorded same-day return to within 0.05 percentage points, or it is dropped and counted in the report.
  3. Never mix adjusted and unadjusted prices in one calculation. Pick one and be consistent — including for the entry price, which is where people usually break it.
  4. Store returns, not prices, where you can. A return computed at the time is adjustment-invariant. A price is not.
  5. Flag implausible magnitudes instead of averaging them in. A +900% day in a backtest is a data question, not a trade.
  6. Delete your single best trade and re-run. If the conclusion flips, you never had a result — you had one row. This is the cheapest check on this page and it catches a much wider family of problems than just this one.

A thirty-second version of the check

For any trade in your log, take the entry price you recorded at the time and the entry price you'd get by downloading that same date now. If they differ, everything you computed from that row is suspect:

stored_entry   = 0.50   # what you wrote down on the day
refetched_entry = 5.00   # same date, downloaded today

if abs(refetched_entry - stored_entry) / stored_entry > 0.001:
    print("prices were restated — do not mix these two series")

If you have no stored entry price to compare against, that is itself the finding.

The wider family this belongs to

Split adjustment is one member of a class: your data provider quietly knows things today that nobody knew at the time. The others worth auditing are survivorship bias (delisted companies silently absent from your universe), restated fundamentals (earnings as revised, not as originally reported), point-in-time index membership (testing "the S&P 500" using today's constituents), and dividend back-adjustment mixing total-return and price-return series. All of them share the same signature: they make the past look more knowable than it was, and they almost always flatter the backtester.

Why we're publishing this

We found this bug in our own code, and it had been making our own results look better for weeks. We caught it while auditing a result we had already concluded was a failure — which is worth sitting with, because it means the only reason we looked hard enough was that we were trying to establish a negative rigorously.

A track record that has never published a correction is not a careful record. It's an unaudited one.

The full technical write-up, including the reconciliation guard we added, is in our public audit log under 2026-07-29. The experiment this surfaced during is Experiment 01, where we tested our own stock screener and it lost money.

The other one

This wasn't the only error in our favour. In August 2026 we found that our scanner had logged 128 picks after the market had already opened, on seven separate sessions — breaking the one guarantee the whole record depends on. That correction is here, and the pattern is the same: an error that flatters you can sit there for weeks, because nothing forces you to look.

Get every verdict by email

A verdict lands every few weeks. We'll email you each one, free, the day it publishes — and nothing else. No signals, no picks, no offers. Verdicts stay free and public for everyone either way; this just means you don't have to remember to check back.

One confirmation email first — you're not on the list until you click it. Privacy

Educational and informational only — not investment advice, and not a broker-dealer. ThePickLog is operated by AMD Ventures, LLC (Florida). The diagnosis above is the explanation consistent with our evidence: picks with a stored grade-time price reconciled exactly, and only the re-downloaded subset disagreed. Vendor adjustment behaviour varies, so check your own provider's documentation rather than assuming ours applies.
All experiments · The 7 checks every service should pass · Disclaimer