AI backtesting
Describe a strategy in plain English. The built-in assistant writes it in FXScript, the engine replays it bar by bar over years of real market history, and the optimizer sweeps every input you declared to show which settings actually held up. You read the rules before anything runs — the model proposes, you approve.
One sentence to a tested strategy.
Four steps, none of which ask you to leave the browser or trust a number you cannot inspect.
Why AI-written strategy code usually breaks.
A chat column next to an editor is the easy half, and everyone has seen that demo. The hard part is that a language model asked for code in a small, specific language will confidently write a function that does not exist. It has read an enormous amount of Pine Script and MQL5 and almost none of FXScript, so it pattern-matches — and a plausible but imaginary indicator costs you a run, an error, and a piece of your belief that the feature works at all.
Two engineering decisions fix that, and both are worth knowing about because they are what separate a usable assistant from a demo.
The language reference is generated from the engine, never written by hand. The assistant's system prompt carries a complete, exhaustive list of every builtin, with a closed-world instruction stating plainly that no others exist. That reference is produced from the same source of truth the editor's "copy for AI" button hands out, and a test asserts the two agree in both directions — nothing documented that the interpreter lacks, nothing the interpreter offers left undocumented. A hand-copied reference drifts the day someone adds an indicator, and a drifted reference is worse than none at all, because the model then writes the missing function with total confidence.
Every script is parse-checked the moment it arrives, not when you press Run. A failure shows a red row with a FIX IT button that sends the error straight back for a correction. And the previous version of your work is stashed before every write, so one Undo restores it. An assistant that can silently replace forty lines of your own script is one people stop using.
FXScript, in practice.
Here is a complete strategy — trend filter on a higher timeframe, ATR stop, fixed reward-to-risk target, and a move to break-even once the trade is one R in profit — with three inputs declared for the optimizer to sweep.
strategy("EMA pullback", risk_pct = 1, fill_on = "next_open")
emaLen = input(50, "Trend EMA", minval = 5, maxval = 400)
atrMult = input(2.0, "Stop in ATR", minval = 0.5, maxval = 10)
target = input(2.0, "Reward:Risk", minval = 0.5, maxval = 10)
trend = ta.ema(close, emaLen)
atr = ta.atr(14)
bias = htf.close("H4") > htf.ema("H4", 50)
longSetup = bias and ta.crossover(close, trend)
shortSetup = not bias and ta.crossunder(close, trend)
if longSetup and not strategy.inPosition
strategy.entry("long", sl = close - atrMult * atr, rr = target)
else if shortSetup and not strategy.inPosition
strategy.entry("short", sl = close + atrMult * atr, rr = target)
// Once the trade is 1R up, protect it at break-even.
if strategy.inPosition and strategy.posMfe(0) > 1
strategy.setSl(strategy.entryPrice)
FXScript ships 40 technical builtins under ta., higher-timeframe access through htf., other-symbol series through sym., and the usual math. helpers. The language is interpreted rather than compiled — source is tokenised, parsed to a syntax tree and walked, so nothing reaches eval and a shared script cannot reach another trader's session.
Three things the engine guarantees.
No math drift. The engine contains no indicator math of its own and no cost math of its own. ta.ema delegates to the exact function the chart draws with; profit and loss delegates to the same routine the manual-trading path uses. Nothing is reimplemented "for the backtest". This sounds like tidiness and is actually correctness — it prevents the failure every tester eventually meets, where the chart shows one EMA, the backtest used another, and the discrepancy surfaces months later via a trader who now trusts no number on the page.
No look-ahead, proven rather than promised. Every tester claims it cannot see the future. This one is asserted by a test that is harder to fool than inspection: truncate two thousand bars off the end of the data, re-run, and no trade that closed before the cut is permitted to move. If any part of the engine could read forward, earlier trades would change. The grammar also refuses a forward subscript outright — close[-1] is a parse error, not a runtime surprise.
Same-bar ties resolved from data, not a rule of thumb. One candle contains both your stop and your target. Which came first? From that candle alone the question has no answer, and how a tester handles it is the single biggest lever on the numbers it prints. The engine walks finer timeframes finest-first — M1, then M5, then M15, then M30 — and takes whichever level was touched first in the finest series that actually covers the candle.
Sweep every input, with no combination cap.
Tick the inputs you want varied, give each a min, max and step, and every combination runs and is ranked. Only numeric and boolean inputs are offered — a string has no ordering, so there is no range to sweep, and a boolean is always exactly false and true.
There is no policy cap on combinations, and that is a measured decision rather than a boast. The backtest function is pure, and everything expensive around it — the higher-timeframe series, the other-symbol series, the finer series used for tie resolution — is already cached from the ordinary Run. A sweep is therefore one prepare and N replays over bars already in memory. It downloads nothing. Replay cost was measured on real EUR/USD H1 bars before any limit was chosen:
| Bars | Light script (1 indicator) | Medium (3) | Heavy (10 + loops) |
|---|---|---|---|
| 3,000 | 5 ms | 6 ms | 12 ms |
| 12,000 | 17 ms | 22 ms | 51 ms |
| 40,000 | 56 ms | 329 ms | 675 ms |
A typical 12,000-bar sweep costs about 22 ms per combination, so 500 combinations is roughly eleven seconds. Rather than impose a limit, the panel times two real runs of your own script on your own bars and builds a live estimate from that — taking the faster of the two, because the first run pays for the JIT warming up and a sweep pays that once rather than N times. Work is time-sliced rather than run per-combination, so the tab never freezes.
What this does not do.
It does not find you a profitable strategy. It removes the translation step between an idea and a tested result, which is a real cost and a real barrier — but a bad idea tested quickly is still a bad idea, and an optimizer run over enough combinations will always surface something that looks good on the sample it was fitted to. The ranking table is a starting point for out-of-sample work, not a verdict.
It does not trade for you, connect to a broker, or place a live order. Nothing here touches real money.
And the assistant is a language model, so it can misread an ambiguous instruction. That is precisely why the script lands in an editor you can read and edit rather than executing straight from the chat, and why the parse check runs before you ever press Run.
Versus writing it yourself.
An assistant that writes strategy code is not the only way to get a rule set tested, and it is not automatically the best one. Three approaches are worth putting side by side honestly.
| FXScript with the assistant | MQL5 or Pine by hand | A no-code rule builder | |
|---|---|---|---|
| How you express a strategy | Plain English, then edit the script it returns | You write every line | Dropdowns and preset conditions |
| Time to a first result | Seconds | An afternoon, longer if you are learning the language | Minutes |
| What you can express | Anything the language supports; you can edit any line | Effectively unlimited | Only what the builder exposes |
| Where it runs | Browser, no install | MetaTrader or TradingView | Vendor's platform |
| Ceiling | The language's builtins | None worth naming | Hit quickly, and invisible until you hit it |
The honest summary is that hand-written MQL5 has no ceiling and this does. If your strategy needs something the language does not expose, writing it yourself in MQL5 remains the right answer, and no assistant changes that.
Where a rule builder differs is subtler and matters more. A builder's ceiling is invisible until you hit it: you construct the strategy you can construct, not the one you meant, and you often do not notice the substitution. A script does not have that failure mode, because the rules are written down in front of you and anything the language cannot do fails loudly rather than quietly becoming a different strategy.
And one comparison deserves stating plainly rather than spun: for optimization specifically, MetaTrader's Strategy Tester is better equipped than this. It distributes passes across local agents and the MQL5 Cloud Network and offers a genetic algorithm for grids too large to enumerate. This runs a complete grid on a single thread in a browser tab. That is a real advantage and it belongs to them.
You have a ranking table. Now the real work.
An optimizer will always hand you a winner. Run five hundred combinations against any sample and the top row will look excellent, because you selected it for looking excellent on that sample. The ranking is a list of candidates, not a result. Four habits separate a finding from a coincidence.
Split the history before you sweep, not after. Set the range so the optimizer only ever sees part of your data, then take the winning inputs and re-run them on the span the sweep never touched. If the edge survives on data it was not fitted to, you have something worth more work. If it collapses, the sweep found a property of those particular bars. This is the single most useful thing you can do, and it costs one extra run.
Prefer a plateau to a spike. Look at the neighbours of the winning row, not only the row. A 50-period EMA that scores well while 45 and 55 also score well is describing something real about the market. A 50 that scores brilliantly while 45 and 55 are mediocre is describing noise, and it will not repeat. Robustness looks like a broad hill, not a needle.
Watch the trade count as hard as the returns. Every combination you test is another chance to get lucky, so the more of the grid you sweep the more evidence you need from each candidate. A row showing a superb profit factor over 22 trades is not a strategy, it is a small sample. Sort by trades alongside the ranking metric and be suspicious of anything thin.
Judge on the numbers that survive contact with reality. Win rate is the most quoted and the least informative — a strategy can win 70% of the time and lose money. Expectancy tells you what an average trade is worth, max drawdown tells you what you would have had to sit through, and the two together tell you whether you could actually have traded it. A run you could not psychologically have held is not an edge you have.
None of this is specific to AI-written scripts. It is what separates a backtest from a story, and it applies exactly as much to a strategy you coded by hand. The assistant removes the translation step between an idea and a tested result; it does not remove the burden of proving the result means something.
AI backtesting, answered.
Describe a strategy. See it tested.
Create an account and open the script editor. Write FXScript yourself, or tell the assistant what you trade and read what it hands back.
AI backtesting is a way of testing a trading strategy without writing the code for it yourself: you describe the rules in plain English, a language model turns them into a script a backtest engine can execute, and the engine replays those rules across historical price data one bar at a time. The value is not that the model is clever — it is that the distance between "I think this setup works" and a table of measured results stops being an afternoon of coding.
What separates a useful implementation from a demo is everything around the model. A closed-world language reference generated from the engine stops the assistant inventing indicators that do not exist. A parse check on arrival stops a broken script wasting a run. An engine that delegates its indicator and cost math to the same functions the chart and the manual-trading path use stops the backtest and the chart disagreeing. A look-ahead test that truncates the data and demands earlier trades stay identical catches a whole class of bug rather than the instances someone happened to think of. Tie resolution from finer timeframes replaces a coin-flip on every candle that contains both a stop and a target.
If you would rather test strategies by hand, the same engine powers manual bar-by-bar backtesting on the same data. If you are weighing the two approaches, manual versus automated backtesting covers where each one earns its keep, and how to backtest a trading strategy walks through the process itself.