KenKem Journal

Why Backtests Lie, and How a Tick Engine Fixes It

Β· #systematic-trading #backtesting #tick-data #research-method #trading-psychology

A dark screen showing dense price data and a terminal
A backtest is only as honest as the engine underneath it. Photo: Al Nahian / Pexels.

Early on, one of my backtests looked good. Too good, in a way I could not explain. The equity curve was smooth, the win rate was high, and nothing about the logic justified it. I am a software engineer before I am a trader, so my instinct was not to celebrate. It was to distrust my own code.

It took a while to find the problem, and when I did, it was not in the strategy at all. It was in the engine that tested it. This post is the plain-language version of what I found, because it is one of the most useful things I have learned, and almost nobody talks about it.

The thing most backtests quietly assume

Most retail backtests run on candles. One bar at a time: open, high, low, close. Your strategy sees a completed bar, makes a decision, and the engine fills your order somewhere inside the next bar.

That last part is the trap. A candle is a summary. It tells you four prices and the fact that price visited everything between the high and the low. What it does not tell you is the order those prices happened in.

Say a five-minute candle has a low of 100 and a high of 102. Your stop-loss sits at 100.5 and your take-profit sits at 101.5. Both are inside the bar's range. Both got touched. So which one filled first?

The candle cannot answer that. It has no time inside itself. And so the engine has to guess.

Why the guess flatters you

Here is where it gets uncomfortable. A lot of backtest engines resolve that ambiguity with an optimistic default, or with an assumption you never consciously chose. Some assume the take-profit fills first. Some assume the best-case path through the bar. Some let you set the rule, and most people never do.

Every one of those guesses, repeated across thousands of trades, nudges the result in your favor. Not by a huge amount on any single trade. By half a win here, a saved stop there. Stack that over a few thousand trades and you get a backtest that looks like an edge and is really an accounting artifact.

The worst part is how believable it looks. The curve is smooth precisely because the engine keeps quietly resolving coin-flips in your favor. You are not looking at a strategy. You are looking at your own optimism, compounded.

What a tick engine does instead

A tick is a single print: one trade, at one price, at one moment. Real tick data is the raw stream of every one of those prints, in the exact order they occurred.

A tick-level engine does not summarize the bar and guess. It walks the prints in sequence. When price reaches 100.5, your stop is evaluated right then, before price ever gets to 101.5, because that is the order it actually happened. There is no coin-flip to resolve, because there is no ambiguity left to resolve. The sequence is the data.

This sounds like a small distinction. In practice it changes everything downstream:

  • Fills happen where they actually could have happened, in the real order, not the convenient one.
  • The test stops flattering you. When the optimism is removed, a lot of "edges" quietly disappear. That is not the engine being pessimistic. That is the engine being correct.
  • Backtest and live start to agree. The gap between a paper result and a real one, what people call parity, gets smaller because both sides are now evaluating the same reality.

That last point is the one I care about most. A backtest is a promise you make to yourself about the future. If it is built on a flattering assumption, it is a promise you cannot keep.

Why I rebuilt mine

Moving off a bar-level engine onto a pure tick engine was one of the hardest problems in my research stack, dquants. It was slow, unglamorous work. Tick data is enormous, so it has to be stored and queried carefully. Every part of the pipeline that assumed "one bar at a time" had to be reconsidered.

But I did it for a simple reason: I would rather have a test that tells me the truth than one that feels good for a week. A strategy that only survives on a bar engine was never really surviving. It was being carried by the accounting.

When I run a setup through the tick engine now and it still holds up, after real costs, out of sample, in the exact market regime I claim it works in, that result means something. Not because it is impressive. Because it is honest. It has stopped being flattered.

What this means if you never touch code

You do not need to build an engine to use this. You need one question, and you should ask it of any backtest, including your own:

When my stop and my target are both inside the same bar, which one does this engine assume filled first?

If the answer is "I do not know," treat the whole result with care. It might be real. It might be the optimism talking. You cannot tell yet, and knowing that you cannot tell is itself progress. That single question separates a number you can trust from a number that is quietly cheating for you.

None of this is a claim about profit. It is a claim about honesty. A tick engine does not make a strategy good. It makes a bad strategy visible before it costs you real money, which is most of what a research process is for. In my own work, this is exactly why I keep the standard strict and the framing humble: I am still learning, and the fastest way to keep learning is to build tools that refuse to lie to me.

Educational purpose only. This is a description of a research method, not financial advice, and not a claim of results. Past performance does not guarantee future results.

← All journal articles

Chat