Loslegen

Vectorized vs Event-Driven Backtesting Engines

The two backtest architectures fail in opposite ways. One is fast and lies about order state, the other is slow and honest. Here is which one to reach for at each stage of research.

I keep coming back to the same argument with people who are new to building strategies, and it usually starts when they show me a backtest with a Sharpe that looks too clean. Nine times out of ten the culprit is not the strategy. It is the engine. They built the whole thing in a vectorized backtest because that is what every tutorial hands you, and vectorized engines are wonderful right up until the moment your logic depends on the order in which things happened. Then they quietly start telling you a story that is not true.

So it is worth being precise about what these two architectures actually are, because the choice is not about which one is better. It is about which lie you can afford at which stage.

What each engine is actually doing

A vectorized engine treats your entire price history as one big array and applies your logic across all of it at once. You compute an indicator, you compute a signal, you shift the signal forward by one bar so you are not trading on information you did not have yet, and you multiply that signal by forward returns. The whole backtest is a handful of array operations. It runs in milliseconds because there is no loop stepping through time. Time is collapsed into columns.

An event-driven engine does the opposite. It steps through the data one event at a time, a bar or a tick or an order book update, and at each step it asks what your strategy wants to do given only what it knew at that instant. It maintains explicit state. There is a portfolio object, there are open orders, there is cash, there are positions with a cost basis. An order gets submitted, sits in a queue, and fills on a later event according to whatever fill model you gave it. It is slower by a large factor because you are paying for a Python loop, or a slightly less painful compiled loop, over every timestamp.

The speed gap is real and it matters. When I am sweeping a parameter grid or checking whether an idea has any pulse at all, I want the answer in seconds, not overnight. Vectorized wins that contest by a mile, and that is the whole reason it exists.

Where vectorized quietly gets it wrong

The trouble is that a vectorized backtest assumes every position is a clean, fully filled, instantly executed bet that you hold until the signal flips. That assumption is invisible until your strategy has any of the following, at which point the number on the screen becomes fiction.

  • Trailing stops. A trailing stop is path-dependent by definition. Where it sits today depends on the highest price reached since entry, which depends on the exact sequence of bars, which is exactly the thing a vectorized engine flattens away. People fake it with a rolling maximum, but a rolling max over a fixed window is not the same object as a stop that ratchets from entry and never loosens. The fake version will often show you an exit that could not have happened, usually a better one.
  • Partial fills. Vectorized assumes you got the whole size at the printed price. In anything less than deep liquidity, you did not. Your large order walks the book, or it only partially fills and the rest hangs, and now your real position is smaller and your average price is worse. The vectorized version never sees this, so it happily compounds size you never actually held.
  • Portfolio margin and cross-position constraints. The moment your available buying power for position B depends on the unrealized PnL of position A, you have a state problem. Vectorized engines treat each column as independent. They will let you put on trades that, in reality, you had no margin to open, or they will miss a liquidation that would have wiped you.
  • Stop and limit interaction inside the same bar. If both your stop and your target sit inside one bar's range, which one filled? A vectorized engine has no ordering inside the bar, so it picks one by convention, and the convention is usually the optimistic one.

None of these are exotic. Trailing stops and partial fills show up in the first real strategy most people build. The failure mode is not a crash. It is a backtest that looks a little too good and fails silently, which is the worst kind, because you will fund it before you find out.

A rule of thumb for which to reach for

I think about it in terms of what my logic depends on. If every decision can be written as a function of data available at that bar, and nothing depends on the sequence of what happened since entry, vectorized is not just acceptable, it is the correct tool and using a heavy event-driven engine would be a waste. Moving-average crossovers, threshold entries on an indicator, simple rebalancing, most factor screens. All fine vectorized.

The moment any of these appear, I move to event-driven:

  1. The exit depends on the path since entry. Trailing stops, breakeven stops, time-based exits that interact with price, scaling out in tranches.
  2. Fills are not guaranteed. Anything where size relative to liquidity matters, or where you are modeling slippage as a function of order size rather than a flat haircut.
  3. Positions interact. Portfolio margin, shared risk budgets, correlation-based sizing, anything where one trade's state changes what another trade is allowed to do.
  4. Order state itself is the strategy. Working orders, queue position, cancel-and-replace logic, maker rebates that depend on whether you were passive.

The workflow that has saved me the most grief is to use both in sequence rather than picking one. I hunt with the vectorized engine, wide and fast, to find candidates that are at least not obviously dead. Then before I trust anything, I re-run the survivors through the event-driven engine with a realistic fill model, and I look hard at the gap between the two results. That gap is the diagnostic. If a vectorized backtest and a careful event-driven one land in roughly the same place, the strategy is probably robust to execution reality. If the event-driven version falls apart, the edge was living inside the vectorized engine's optimistic assumptions, and it was never really there.

When the fast approximate answer is fine

I do not want to leave the impression that event-driven is always the grown-up choice and vectorized is a toy. Fidelity is not free. A high-fidelity engine has more moving parts, more places for your own fill model to be quietly wrong, and it tempts you into overfitting the microstructure of your assumptions. Precisely modeling slippage on a daily-rebalanced, liquid-large-cap strategy is effort spent buying a decimal place you did not need.

So the honest answer is that a fast approximate result is acceptable whenever the approximation error is small relative to the thing you are trying to learn. Early exploration, relative ranking of many ideas, sanity checks, sizing studies on liquid instruments where your order is a rounding error against volume. In all of those, the vectorized number is close enough to steer by, and the speed lets you ask ten times as many questions. You just have to know you are steering by an estimate and refuse to fund anything on it alone. When we build strategy tooling at Blockcircle, the backtester runs both modes for exactly this reason, so you can see the cheap answer and the honest answer side by side and treat the distance between them as information.

The mistake is not using vectorized. The mistake is using it, seeing a clean equity curve, and forgetting which questions it was never able to answer. Keep the fast engine for finding things and the slow one for believing them, and check that trailing stop by hand at least once before you trust any backtest that contains one.

GESCHRIEBEN VON
Blockcircle Team

Finanzmarkt-Intelligenz für Krypto, Aktien, Rohstoffe, Edelmetalle und Prognosemärkte.