AI Assistant · FXScript · Optimizer

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.

Plain English in Readable script out Bar-by-bar replay Full grid optimizer Runs in the browser
How it works

One sentence to a tested strategy.

Four steps, none of which ask you to leave the browser or trust a number you cannot inspect.

1
Describe it in English
Type the strategy the way you would explain it to another trader. "Buy when the 20 EMA crosses above the 50, stop 20 pips, target 2R." The assistant returns a working FXScript with the entry, the stop, the target and the sizing already wired up.
2
Read it before it runs
The script lands in the editor, not in a black box. You see the exact rules that will execute — every condition, every level, every input — and can change any of them. The previous version is stashed before every write and one Undo restores it.
3
Replay it bar by bar
The engine walks your script across years of real market history one candle at a time, opening and closing positions exactly where the rules say. No indicator math is reimplemented for the backtest: ta.ema calls the same function the chart draws with, and profit and loss goes through the same routine as a manual trade.
4
Sweep every input
Declare inputs with a min, a max and a step, tick the ones you want varied, and the optimizer runs the full grid and ranks the results. Only numeric and boolean inputs are offered — a string has no ordering, so there is no range to sweep.
The hard part

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.

What it writes

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.

Trust the numbers

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.

The optimizer

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:

BarsLight script (1 indicator)Medium (3)Heavy (10 + loops)
3,0005 ms6 ms12 ms
12,00017 ms22 ms51 ms
40,00056 ms329 ms675 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.

Being straight with you

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.

Compared with the alternatives

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 assistantMQL5 or Pine by handA no-code rule builder
How you express a strategyPlain English, then edit the script it returnsYou write every lineDropdowns and preset conditions
Time to a first resultSecondsAn afternoon, longer if you are learning the languageMinutes
What you can expressAnything the language supports; you can edit any lineEffectively unlimitedOnly what the builder exposes
Where it runsBrowser, no installMetaTrader or TradingViewVendor's platform
CeilingThe language's builtinsNone worth namingHit 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.

After the sweep

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.

Questions

AI backtesting, answered.

What is AI backtesting?
AI backtesting means describing a trading strategy in plain English and having a language model turn it into runnable code that a backtest engine can execute over historical price data. On FxBacktest the assistant writes FXScript, the platform's own strategy language, and the engine replays that script bar by bar over real market history. You read the rules it produced before anything runs, so the model proposes and you approve.
Do I need to know how to code?
No. You can describe the strategy in a sentence and run the script the assistant returns. FXScript is readable enough that most traders end up editing it directly after a few sessions — changing a number, flipping a condition — but nothing forces you to write it from scratch.
Is the AI assistant included in the plan?
The assistant runs on AI credits. Credits can be bought as a one-off pack or bundled with a Pro or Ultra plan. Writing FXScript yourself, running the backtest and using the optimizer do not consume credits — only asking the assistant to generate or fix a script does.
Can the AI invent an indicator that does not exist?
It is specifically engineered not to. The language reference in the assistant's system prompt is generated from the engine itself rather than written by hand, and it states a closed world: these are the builtins, there are no others. A test asserts the reference and the interpreter agree in both directions, so nothing documented is missing from the engine and nothing in the engine is left undocumented. On top of that, every script the assistant returns is parse-checked the moment it arrives, not when you press Run.
How do I know the backtest is not looking ahead?
Two ways. The grammar refuses a forward subscript outright — close[-1] is a parse error, not a runtime surprise. And the engine is checked by a test that truncates two thousand bars off the end of the data and re-runs: no trade that closed before the cut is allowed to move. If any part of the engine could read forward, earlier trades would change.
What happens when a candle contains both my stop and my target?
The engine resolves it from finer timeframes rather than guessing. It walks 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. How a tester handles this tie is the single biggest lever on the numbers it prints, so it is resolved from data rather than by a rule of thumb.
How many input combinations can the optimizer run?
There is no policy cap. The backtest function is pure and everything expensive around it is already cached from the ordinary Run, so a sweep is one prepare and N replays over bars already in memory — it downloads nothing. On real EUR/USD H1 bars a typical 12,000-bar replay costs about 22 ms per combination, so 500 combinations is roughly eleven seconds. Before a sweep the panel times two real runs of your own script on your own bars and builds the estimate from that.

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.