What the engine is for
AlfaTactix describes each strategy once, in one strategy document, and turns it into MQL5 code for MetaTrader 5 or Pine Script v6 code for TradingView. Backtest engine v2 runs the same document on past bars. It has two jobs:
- A backtest for you. The backtest is open to every signed-in user. A strategy you build in the 7-step builder runs in the engine with the bar rules, costs and rounding this page describes. What each plan allows and how to start: No-code backtest.
- A reference for the code. The engine is the yardstick the generated code is checked against. We run the same strategy in the engine and in the MetaTrader 5 tester or on TradingView, then compare the signals and the trades. Every difference must have a named cause, or it counts as a bug.
This page explains the engine's rules in plain words, then shows how closely MetaTrader 5 and TradingView follow it, with the limits. How we test the rest of the product is on How we test; the generated code has its own page, MQL5 and Pine generators.
The bar model in plain words
A bar gives four prices: open, high, low and close. It does not say in which order the prices came inside the bar. Every tester needs a rule for that. These are the engine's rules, written in the strategy specification:
- A gap fills at the open. If a bar opens beyond your stop loss or take profit, the order fills at the open, not at the level you set.
- The stop first. When the stop loss and the take profit are both inside one bar, the engine assumes the stop was hit first.
- Levels in price order. When one bar crosses several levels, such as partial closes and the take profit, they fill in the order the price reaches them.
- Moves from the next bar. A trailing stop or a breakeven move takes effect from the next bar, not inside the bar that triggered it.
- Signals at the close, fills at the next open. Exit signals and time exits are decided at the close of a bar and filled at the open of the next one.
- Partial closes round down to the symbol's volume step.
Why the stop first
A single bar cannot tell which of two levels came first, so a tester has to guess. Taking the stop is the cautious guess. On ordinary bars this rule is stricter than TradingView, MetaTrader 5 and NinjaTrader, and the gap fill at the open is the same as TradingView's. That comparison is a reading of the platforms' own documentation: we did not run their testers for it.
The rules have their own test library: 25 cases, 25 of 25 passing.
Four more rules
Also set:
- bars are Bid prices, and a short position exits on the Ask;
- slippage applies only to stop, gap and market fills;
- a limit order can get a fill offset in ticks (0 by default);
- when partial closes add up to the whole position, the last level closes what is left.
The fine-data mode
Inside a bar the engine can read finer prices instead of guessing. Each run uses one of three modes:
| Mode | What the engine reads inside each bar |
|---|---|
| Bars | the bar only, with the rules above |
| 1-minute OHLC | the open, high, low and close of each minute inside the bar |
| Real ticks | every price change inside the bar |
A bar without finer prices falls back to the bar rules, and the run counts how many bars did. Every result names its mode, so you always know which reading you are looking at.
The comparisons with MetaTrader 5 further down used the 1-minute OHLC mode. The real-tick mode has not been compared with MetaTrader 5 or TradingView yet.
Costs and the test profile
Costs are not hidden in the bar model. Each one is set in the run's test profile, where you can see it:
| Cost | How it is set |
|---|---|
| Spread | from the price data, or a fixed value |
| Commission | per lot, per order, or a percentage of the trade's value |
| Swap | from the price data, or fixed values for long and short |
| Slippage | backtest only, on stop, gap and market fills |
| Limit-order fill offset | an optional offset in ticks for limit fills, 0 by default |
Test profile 1.1 adds three things:
- the symbol's quote and base currency;
- a fixed currency conversion;
- the triple-swap day: Wednesday for forex and metals, Friday for index and stock CFDs.
A run with a 1.0 profile still gives byte-identical results.
The tick grid and money rounding
Prices on the tick grid
Prices move in steps: the symbol's tick size. A level that falls between two steps can never be filled. The engine puts every stop loss, take profit, trailing stop and breakeven level on the symbol's tick grid, rounded away from the entry: below the entry the level moves down to the next step, above it up to the next step. A level within a millionth of a tick of a step counts as on it. Position size and 1R still use the exact distance you set.
In the minute and tick modes, a trailing stop and breakeven move once per bar, at its close, and prices within a millionth of a tick of the grid are snapped onto it when the engine reads them. The reason is a platform fact: MetaTrader stores 6.2% of EURUSD minute prices one ulp (the smallest step a computer number can take) off the grid.
Money on the cent
Commission, swap and the result of each fill are booked in the account currency's smallest unit, the cent for a USD account, rounded half away from zero, as the MetaTrader 5 tester books them. The evidence is 42 charges that fell exactly on a half cent and 841 of 841 deals. For swap and fill results this was observed; for commission it is an assumption. TradingView keeps exact money, without rounding.
How we compare: values, signals, trades
We compare the engine with each platform at three levels:
| Level | What is compared | How exact |
|---|---|---|
| P1 | indicator values | bit for bit on MetaTrader 5, zero tolerance on TradingView |
| P2 | signals: on every bar, each entry and exit flag and every rule of the strategy | equal or not, bar by bar |
| P3 | trades: the whole list, with entries, exits, prices and volumes | equal, or every difference has a named cause |
P1 is the generators' part and has its own page: MQL5 and Pine generators. This page is about P2 and P3.
Named causes and bugs
A difference in a trade list is either one of twelve named causes, each checked row by row, or a bug. A run is within budget when every difference has a named cause and the net results of the two sides reconcile with a remainder of 0.00. Four causes explain most differences:
- End of data. The engine closes an open trade at the last bar's close; the MetaTrader 5 tester closes it at its own end of test; TradingView leaves it open.
- Tester mode. In "1 minute OHLC" the MetaTrader 5 tester fills a stop loss or take profit at the level itself, even when the minute opened beyond it. The engine fills it at that minute's open, the realistic price.
- The path inside a bar. When one bar touches both the stop loss and the take profit, the path the tester or TradingView follows inside the bar may reach the take profit first; the engine takes the stop first.
- Equity cascade. After a named difference the two balances differ a little, so a later trade sized on risk can differ by one volume step.
Results against the MetaTrader 5 tester
Golden strategies
Our golden set has 31 valid test strategies. The golden comparisons run on test bars put into a MetaTrader 5 custom symbol, so the engine and the Expert Advisor read identical bars:
| Level | Equal | Within budget | Not comparable |
|---|---|---|---|
| Signals (P2) | 29 | does not apply | 2 |
| Trades (P3, "1 minute OHLC") | 7 | 22 | 2 |
So 29 of 31 strategies give the same signals, and 29 of 31 give equal trades or trades within budget, with 0 bugs. The 2 not comparable are strategies MetaTrader 5 cannot run: one uses every filter at once, and one uses a fundamental filter that only TradingView offers. The generator refuses them for MetaTrader 5 by design.
Six common strategies on real prices
We ran six common strategies on about ten months of real EURUSD H1 prices in the MetaTrader 5 tester ("1 minute OHLC" mode):
| Run | Strategy | Trades: engine / MetaTrader 5 | Verdict |
|---|---|---|---|
| R1 | EMA 20/50 cross with a 2 × ATR stop | 89 / 89 | within budget |
| R2 | RSI(14) mean reversion with an SMA 200 | 16 / 16 | equal |
| R3 | Bollinger (20, 2) breakout with a volume filter | 127 / 127 | within budget |
| R4 | MACD on H4 with a daily EMA 200 filter | 17 / 17 | within budget |
| R5 | London range breakout with FTMO limits | 71 / 71 | within budget |
| R6 | Donchian 20 breakout, trailing stop, 50% closed at 1R | 170 / 170 | within budget |
The signals had 0 differences on every bar in every run, for example 4,832 rows for R4 and 12,110 for R6. In the five runs within budget, the differences come mainly from the tester's mode and the end of data, and the net results reconcile with a remainder of 0.00.
Most of the six lost money over this period. That is not what the test measures: it shows that the engine and MetaTrader 5 agree, not how a strategy will do.
Results on TradingView
TradingView has no command-line tester, so every run there is a manual run, and the coverage is small. On the 31 golden strategies:
| Level | On TradingView itself | Not run |
|---|---|---|
| Signals (P2) | 7 equal | 24 |
| Trades (P3) | 4 equal, 1 within budget | 26 |
We also check our own simulator of the Pine code against the engine on every golden strategy. That is a check of our simulator, not of TradingView: signals 20 equal, trades 18 equal and 2 within budget, 11 not comparable. After generator version 1.0.0 the verdicts are unchanged.
On TradingView's own bars
We ran the six common strategies on TradingView's own EURUSD H1 bars (5,012 bars, no costs):
- R1 87, R2 11, R3 125 and R5 75 trades, each equal to the engine run on the same bars;
- R6 181 trades, with one named cause (the path inside a bar) that later trades follow from;
- R4 no trades: its warm-up needs more bars than the TradingView account loaded.
Why MetaTrader 5 and TradingView never match exactly
An obvious test is to run the same strategy in MetaTrader 5 and on TradingView and compare the two. They will not match exactly, and we do not claim they do: the two platforms read different price feeds. A cross happens on one feed and misses by a point or two on the other; a volume filter counts different ticks; one exit an hour apart changes the next position.
For five of the six common strategies, this was the share of entries at the same hour and on the same side:
| Run | Same hour and side |
|---|---|
| R1 | 94% |
| R2 | 82% |
| R3 | 88% |
| R5 | 94% |
| R6 | 95% |
That is why we compare each platform with the engine on that platform's own bars, as in the two sections above, and not the two platforms with each other.
The limits
These are the limits of what this page shows:
- Commission and slippage on MetaTrader 5 are not proven. On a custom symbol the MetaTrader 5 tester never charges commission, slippage or the limit-order fill offset. We leave them out of both sides and name them in each case.
- TradingView models fewer costs. It models no spread, swap or currency conversion, and its log reports no commission. These are left out of both sides too.
- Small TradingView coverage. Signals for 7 and trades for 5 of the 31 golden strategies.
- One symbol, one feed, about ten months. The real-price runs used EURUSD only, one broker's price feed and the "1 minute OHLC" mode. Not run: the real-tick mode and a 12-month TradingView run.
- No live trading. Nothing here was tested with real money, on a live account, or forward in time.
- Not verified yet. TradingView's List of trades export, the limits of Pine logs, the MetaTrader 5 tester's shared file folder (
FILE_COMMON) and the tester's own close at the end of a test. - Four metrics rest on our assumptions. The annualisation of the Sharpe ratio, the recovery factor on equity drawdown, the Sortino target of 0 and exposure.
- Whole backtests are not bit-exact. Bit for bit applies to indicator values. Signals are equal on the cases above; trades are equal or differ for a named cause.
Questions and answers
Will a backtest here match my run in the MetaTrader 5 tester?
In our tests, on the same bars and with the costs both sides charge, the signals were the same and the trades were equal or differed for a named cause. A run of your own in the tester can differ when it reads other bars, uses another tester mode, or charges costs the engine run leaves out.
Why does the engine take the stop first?
A bar does not say which of two levels came first, so a tester has to guess, and the stop is the cautious guess. In the 1-minute OHLC and real-tick modes the engine reads the prices inside the bar, so it has to guess less.
What does "within budget" mean?
Every difference between the engine and the platform has a named cause from a fixed list, and the net results of the two sides reconcile with a remainder of 0.00. A difference with no named cause is a bug.
Does a good backtest mean a strategy will do well?
No. A backtest shows what the rules would have done on past prices, with the stated costs and limits. It says nothing about the future. The tests on this page check that the engine and the platforms agree, not that a strategy is good.
Was the engine tested with real money?
No. Only the MetaTrader 5 tester and TradingView backtests were run. Live trading was not tested.
Who can run a backtest?
Every signed-in user. To try the builder without signing up, open the public demo.
Sources
The figures on this page come from our engineering record, cited by document id.
149Evidence dossier: the engine facts (§2) and the claims we may make (§6.1).115Engine brief update: the bar model (§2) and the test profile (§9).125Bar model check against TradingView, MetaTrader 5 and NinjaTrader.100Decisions DD-66, DD-101, DD-103 and DD-105.137Parity harness: the three levels and the named causes.137aParity report: the counts.143Reference runs of the six common strategies.

