Backtest architecture: why TradingView tests deceive you
What a backtest has to emulate before its output means anything — order queue position, partial fills, slippage, and the cost of disk I/O.
Most people treat a backtest as running indicators over candle history. Press a button in TradingView, get a pretty equity curve.
The problem is that retail platforms use a naive execution model: if price touched your limit, the system books you a profit. In reality, order-matching mechanics are what destroy you.
Here is how our simulation layer is built, and why.
Data and the I/O bottleneck
We parse history directly from the exchange. OHLCV candles are not enough — we need tick history and order book snapshots to measure how limit density shifts.
The main enemy of a backtest is disk I/O. Push arrays off a disk and your computation takes years. So the architecture runs through Redis, and during live runs and parameter optimisation the heavy maths stays in RAM. Memory access speed is what makes thousands of iterations finish in a workable time.
This is not optimisation for its own sake. While a run takes a day, you test one hypothesis per day. When it takes minutes, you test twenty.
Why the engine is written from scratch
We do not use public trading-simulation libraries. They do not model market microstructure.
The heavy maths, expected-value calculation and risk module are written in Python. The components that are latency- and concurrency-critical — exchange connectors and webhooks — are in Go.
The split follows the shape of the work, not taste: the computational side benefits from Python's ecosystem, the network side from cheap goroutines.
The real engineering problem: emulating reality
Making a backtest tell the truth is harder than writing the strategy. The engine simulates what retail platforms ignore:
- Order queue. Price touching your level does not mean your limit filled. You may have been thousandth in line.
- Partial fills. Available liquidity at a level can be smaller than your size.
- Slippage. Hitting the market eats the book.
If your backtest shows a 100% win rate, your code is lying to you.
Our system builds in operating losses and pessimises execution during simulation. We deliberately make conditions worse than the market's. A strategy that survives conditions known to be worse than real has a chance of surviving real ones. The reverse does not hold.
The zero-latency illusion
Retail is obsessed with renting a server near the exchange to get one-millisecond ping. For our infrastructure it does not matter: we work through webhooks, and ±50 ms does not concern us.
Why? Because we are not doing HFT arbitrage and not trying to outrun a market maker by microseconds. The algorithms read structural inefficiencies and trade expected value over a distance. At that horizon 50 ms is statistical noise, absorbed by the average size of a take.
The question is not how fast you send an order. It is how accurately your model describes the chaos of liquidity.
What to take from this
A backtest is not a test of your strategy. It is a test of how honestly you can model your own execution. A beautiful equity curve under a naive fill model tells you about the model, not the strategy.