Pyrite Research

18 August 2026

447.5%

What several weeks of careful, validated, entirely wrong work looks like from the inside.

On the last day of March 2026 I committed a file saying my strategy compounded at 447.5% a year. The drawdown looked survivable. Buying and holding the same instrument did a small fraction of it.

I believed it for about a week.

Not carefully. I opened a compound interest calculator and started typing years into it, which is what everybody does, and at 447.5% you do not have to type many of them. I worked out, quite seriously, that I was going to be a billionaire.

In fairness to myself, I did stop short of the really silly numbers. A strategy trading leveraged ETFs cannot absorb hundreds of billions of dollars without moving the things it is buying, so somewhere up there was a ceiling. I was carefully applying capacity constraints to a figure that was entirely imaginary. That is more or less how the whole episode went.

Then the small voice at the back of my head spoke up. It said the obvious thing, which was that this was too good to be true. I have come to rely on that voice more than on any test I have written since, which is a slightly uncomfortable thing to admit in public.

It was not one mistake

That number was not the first thing the strategy produced, and I want to be precise about it, because the way it actually happened is the useful part.

It arrived at the end of several weeks of work. The rhythm went like this. I would have an idea. I would build it, run it against the previous version, and the number would go up. I would then run more validation on it, split periods, bootstraps, cross-checks against a different index, and the improvement would hold. So I would keep it and move on to the next idea. That happened over and over, and each time I came away more confident than I had gone in.

Every check was the broken instrument being asked to confirm itself.

And it always agreed.

Several of my ideas were not adding anything. They were compounding the same underlying error in slightly different ways, and because each one was measured against the version before it rather than against reality, the error was invisible at every individual step. The strategy did not get better over those weeks. It got better at leaking.

The evidence was already on the page

When I finally went looking, I did not need new information. It was sitting underneath the claim, in the same file, in a table I had written myself.

Rotation lookbackReturn, against no rotationSwitches per year
1 day3.6x~128
20 days1.3x~25
No rotation1.0x0

The top row is the 447.5%. The strategy rotated between two sets of instruments depending on which had better recent momentum, and the shorter the window it looked at, the better it did, all the way down.

I had written the justification too. Momentum autocorrelation came out at 0.94 on a one day lag, so obviously a one day lookback captured the most of it. That is a real statistic and it is even relevant. It was still a rationalisation, and I think a plausible mechanism is more dangerous than no mechanism at all, because it stops you looking.

A strategy that improves as you shorten its window is being handed the answer.

At 128 switches a year, that rotation was deciding what to hold using information about the day it was deciding. I also had Monte Carlo behind me: a 99.8% beat rate at sixty day blocks, 100% at a hundred and twenty. I read that as support. These days a bootstrap above 0.98 makes me stop, because resampling a broken backtest a thousand times gets you a thousand broken backtests, and they will all agree with each other.

It kept happening

I would like to say I learned this in March and moved on.

In June I ran an investigation into intraday signals and got +116 percentage points of CAGR out of it. Minimum bootstrap probability of 1.00. Out of sample better than in sample, which I now know is close to a confession, and which at the time I found encouraging.

It took a fortnight to find. My intraday code overlaid live prices for the seven tickers that had intraday bars, and left every other price column sitting at that day's close. So an eleven o'clock decision could see how the day ended. Not all of the day, just the parts I had not thought to overwrite.

Fixed it. Re-ran. +38pp, bootstrap 0.98.

Which is still good, and I was tired, and I wanted it to be over.

The second cause was narrower. One instrument I use for downside protection has no fifteen minute bars at all, so any intraday move into it was being marked close to close. On crisis mornings the strategy was collecting a decline it had not actually been positioned for. Same configuration, once that was fixed: -16pp, bootstrap somewhere between 0.02 and 0.05. The commit I wrote that afternoon says it flatly. The +38 was entirely the bug.

First result One bug out The truth +116pp +38pp -16pp
One investigation, measured three times, as each look-ahead came out

What I had not understood before that day is that each fix uncovers the next one. A backtest with a look-ahead bug in it is not a good measurement with one problem. It is an uncalibrated instrument, and until you calibrate it you do not know what any of its readings mean, including the ones that look sensible.

The one that cost money

All of that was measurement error, which is humiliating and free.

On 13 July 2026 I paid for the other kind. At one in the afternoon a stop signal flipped intraday and forced my live account out of a position at a 13.2% loss. $1,257, out of my own account, on a Monday.

The problem was not that the strategy made a bad call. It was that no backtest I had ever run had modelled that path at all. Every engine I owned measured the thing I believed I was running, and the thing I was actually running had quietly become something else. There was no test that could have caught it, because a test would have been written against the same wrong assumption.

The backtest was not where the problem was.

This is the inverse of look-ahead bias, and it is worse, because you cannot audit your way to it from the backtest at all.

A week later I switched intraday execution off altogether, which made the thing I was running and the thing I had validated the same object again. The reported numbers got worse. The numbers got correct.

What I do now instead of feeling confident

There is a written protocol in my repository that every number has to pass before I am allowed to quote it anywhere, including to myself. It is boring, which is rather the point.

Before I record anything, I check that every input to every decision was knowable at the time by its publication date and not its data date, which is a distinction that has cost me more than any other single thing. Then that turning the mechanism off reproduces the old baseline exactly, not approximately. Then that state advances once per period, at the moment production advances it. Then that every fill happens at a price somebody could have traded at.

After that there is a list of results I am simply not allowed to believe on sight. Any first measurement of anything new. Anything above ten points of alpha. Any bootstrap above 0.98. Out of sample beating in sample. Anything that improves after a change that was not meant to improve it. Tripping one of those does not mean a result is wrong. It means it is quarantined until I have pulled it apart, and I have quarantined plenty of things that turned out fine.

Pulling it apart means running old against new on identical data with only one thing changed, delaying every input by a day to see whether the edge survives being late, swapping the trigger for noise that fires at the same rate to see whether the plumbing pays by itself, checking the alpha shows up in the regime the mechanism was designed for, and printing the whole decision vector for two or three days and reading it line by line.

That last one cannot be automated, everyone skips it, and it is where two of my six worst errors turned up.

Where it landed

The honest number is roughly a fifth of what I believed in March. I am happy with it, which surprised me at the time. The gap between the two is not performance. It is what it cost to be wrong for a while and then find out.

I am writing this down because the conditions that produced my 447.5% are now available to everybody, and much faster than they were to me. A backtest used to take a week. It takes an afternoon now, and whoever is trading it has often not read all of it. The tools are genuinely good at producing code that works, which is the whole difficulty, because look-ahead bias produces code that works perfectly. Nothing throws. No test fails. The number just comes out too high, and it comes out too high with a plausible mechanism attached.

Nobody is short of strategies at this point. What is scarce is the unglamorous apparatus that tells you which ones are real, and the small voice that makes you go and look. Mine took four months and twelve hundred dollars to install, and I would not trade it back.

I do this for other people's backtests now. Here is what that involves.