Learn

Build an MT5 EA with AI: From Prompt to Backtest

At a glance

To build an MT5 Expert Advisor (EA) with AI, write the trading rule down, give it to the assistant as one bounded prompt and test what comes back. Our range-breakout EA came from a single prompt, compiled unchanged with zero errors and placed 646 trades in a Strategy Tester run on EURUSD M15 from January 2024 to September 2026. We recomputed every trade from exported bars, and the EA followed the rule. The backtest still lost 15.6% after commission: working code is not a profitable strategy.

On this page
The RoboXpert robot assembles a small blue device with gears at a workbench, holding a screwdriver. Headline: “Build an MT5 EA with AI”
AI-generated illustration with a headline added by RoboXpert. Not a platform screenshot or a trading result.

You can build an MT5 Expert Advisor with AI in one afternoon. This guide shows a complete run: one prompt, the unchanged answer, the compiler output, a Strategy Tester backtest and a check of every trade against the written rule.

The result has two parts. The code worked: it compiled without errors and followed the rule in the backtest. The strategy did not: it lost 15.6% after commission. Both parts are documented below, and the complete material is in the download.

A program like this is often called an AI trading bot or a trading robot. Here that means a bot whose code was written with AI. The EA is a deterministic MQL5 program. It compares prices with a time range and sends orders. It does not ask an AI service for trading decisions. The AI wrote the source code, and that is all it did here. Our MT5 AI Assistant guide explains the other case, an assistant with access to the platform. In our MT5 MCP server test an agent wrote, compiled and backtested an EA through the platform’s own tools.

Write the rule before the prompt

“Make a profitable trading robot” cannot be tested. A rule can. We chose a time-range breakout because every part of it is visible on a chart. The table holds the complete rule; everything the EA does later has to trace back to one of these lines.

Scroll horizontally if needed

PartRule for this example
RangeHighest high and lowest low of all bars that open from 00:00 to 08:00 broker server time
EntryA bar that opens between 08:00 and 16:00 closes above the range high: buy. Below the range low: sell
TimingDecide once per closed bar, never on the unfinished bar
TradesAt most one per server day
Stop lossThe opposite side of the range
Take profit1.5 times the stop distance, measured from the entry price
VolumeRisk 1% of equity if the stop is hit
FiltersNo entry above 30 points spread or with stops closer than the broker allows
Time exitClose the position at 21:00 if neither stop nor target was hit
OwnershipOnly positions with this EA’s magic number on this symbol

The hours and numbers are illustrative inputs. We fixed them in the prompt before the first test and did not optimise them afterwards.

The prompt: one bounded task for the AI

This is the prompt, word for word. It names the platform language, forbids what the program must not do and asks the assistant to state its assumptions before writing code.

Write a complete MT5 Expert Advisor in MQL5 (not MQL4) for a time-range
breakout. Name it "RX Range Breakout". Use the standard library class CTrade.
No DLLs, no file access, no network access.

Rules. All times are broker server time. Use the symbol and timeframe of the
chart the EA is attached to.

1. Range: the highest high and lowest low of all bars that open from
   RangeStartHour (default 0) up to, but not including, RangeEndHour
   (default 8) of the current server day.
2. Entry window: bars that open from RangeEndHour up to, but not including,
   LastEntryHour (default 16). Decide once per closed bar, never on the
   unfinished bar. Buy at market when a bar closes above the range high.
   Sell at market when a bar closes below the range low.
3. At most one trade per server day. After a restart, find out from the
   account history whether today's trade already happened and do not trade
   again.
4. Stop loss at the opposite side of the range. Take profit at RewardRisk
   (default 1.5) times the stop distance, measured from the entry price.
5. Volume: risk RiskPercent (default 1.0) of account equity if the stop is
   hit. Compute it from the symbol's tick value and tick size and round down
   to the volume step. Below the minimum volume: skip the trade and log why.
   Above the maximum volume: use the maximum.
6. Skip the entry when the spread exceeds MaxSpreadPoints (default 30), when
   no bar exists inside the range window, or when stop or target is closer
   than the symbol's minimum stop distance.
7. If neither stop nor target was hit, close the position at CloseHour
   (default 21).
8. Only touch positions and deals with this EA's magic number (an input) on
   this symbol. It must work on netting and on hedging accounts.
9. Check the result of every trade request and log the return code. Do not
   resend a failed request in a loop.
10. Draw each day's range as a rectangle on the chart.
11. Log one line per decision: the range values, the signal, a skipped entry
    with its reason, the order result and the time exit.

First restate the rules in your own words and list everything that is
ambiguous, with the assumption you chose. Then give the complete source in
one file. Do not claim that you compiled or tested the code.

We sent it once, on 2 October 2026, to Claude Opus 5.5 in a fresh session. The assistant was told to answer without files, a compiler or web search. The session ran inside our project workspace, so it could see the project’s general working instructions. They contain no EA code, but they explain the RoboXpert copyright line in the source.

Using ChatGPT, Gemini or another assistant

The prompt names no assistant and needs nothing that only one of them offers. You can paste it into ChatGPT, Gemini or a coding agent such as Claude Code. We ran it with Claude Opus 5.5 only and have not tested other models for this guide. Expect different code, different assumptions and possibly compiler errors. What you check stays the same: the list of assumptions, the compiler output, the tester journal and the trade list. Keep the prompt, the answer and every later change together, whichever assistant you use. In a separate test we gave Claude and GPT the same indicator prompt and checked both results tick by tick.

What the AI answered

The answer had three parts: the rules in the assistant’s own words, a list of 25 assumptions and one MQL5 file with 724 lines. It closed with the sentence “I have not compiled or run this code” and six points to check first.

The list of assumptions is the most useful part. Our prompt looked complete, and the assistant still found gaps. Five of them changed how the EA behaves:

Scroll horizontally if needed

Gap in our promptAssumption the AI chose
Which bar may trigger the entry?Any closed bar outside the range, as long as no trade happened that day. It need not be the first breakout bar
Does a skipped entry use up the day?No. The next closed bar outside the range is a new decision
When exactly is the decision made?On the first tick of the next bar, at the ask for a buy and at the bid for a sell
Where does a sell stop sit?Exactly on the range high, with no spread buffer. The ask triggers it
What if the close at 21:00 fails?Try again, at most once per 60 seconds. This is the one request that is repeated

Read this list before you read the code. Each line is a decision about your money that the prompt left open. The first two come back in the backtest below.

The volume calculation shows how the assistant turned rule 5 into code:

double riskMoney =equity*RiskPercent/100.0;
double lossPerLot=stopDistance/tickSize*tickValue;
// ...
double raw   =riskMoney/lossPerLot;
double vol   =NormalizeDouble(MathFloor(raw/step+1e-9)*step,digits);

The first trade of the backtest lets you check it by hand. Equity was 10,000 USD, so the risk was 100 USD. The stop was 282 points away, which costs 282 USD per lot on EURUSD in a USD account. 100 divided by 282 is 0.3546 lots, rounded down to 0.35. The tester journal shows Order SELL 0.35 lots.

Compile the unchanged answer

We saved the MQL5 block as RX_Range_Breakout.mq5 without editing a character and compiled it in MetaEditor build 6230:

Result: 0 errors, 0 warnings, 965 ms elapsed, cpu='X64 Regular'

That is a good start and proves little. A compiler checks that the code is valid MQL5. It cannot know whether stopDistance holds the right price difference or whether the EA trades twice on one day. For that, the program has to run.

If your answer does not compile, give the assistant the exact compiler message and the line it points to, and ask for a fix of that error only. Do not ask for a rewrite.

Run the MT5 Expert Advisor in the Strategy Tester

We ran the EA once with these settings:

Scroll horizontally if needed

SettingValue
PlatformMetaTrader 5 build 6230 on macOS (Wine 10.0), 2 October 2026
AccountDemo account, server CapitalPointTrading-Demo (Capital Point Trading Ltd), hedging, USD
Symbol and timeframeEURUSD, M15
Period1 January 2024 to 30 September 2026
ModelEvery tick based on real ticks, no execution delay
Deposit and leverage10,000 USD, 1:100
InputsDefaults from the prompt, not optimised
CommissionAs charged by the tester for this account: 7 USD per lot round turn
Server timeGMT+3 on the test day

The Strategy Tester simulates. It sent no orders to the demo account. The broker appears here as the source of the price history. It is not a recommendation, and this guide contains no broker link.

MT5 Strategy Tester chart of the range-breakout EA on EURUSD M15 with two blue range rectangles. On 24 September 2026 a buy above the range ends at the stop loss, on 25 September a buy ends at the take profit.
Original MT5 capture, 2 October 2026, cropped to the chart. Separate visual run over 21 to 26 September 2026 with a fresh 10,000 USD deposit, so the volumes differ from the full run. The blue rectangles are the 00:00 to 08:00 ranges drawn by the EA, the round markers are its fills. A function example, not a trading record.

The picture shows two days. On 24 September the bar that opened at 09:15 closed above the range high. The EA bought at 09:30, and the stop on the range low was hit at 13:15. On 25 September the same sequence ended at the target at 14:09. The journal of that run holds one line per decision, as rule 11 asked:

2026.09.25 08:00:00  Range 2026.09.25 00:00-08:00: high 1.13824, low 1.13684, height 140 points, 32 bars
2026.09.25 09:30:00  Signal BUY: bar 2026.09.25 09:15 closed at 1.13845, above the range high 1.13824
2026.09.25 09:30:00  Order BUY 0.62 lots at 1.13845, SL 1.13684, TP 1.14086: accepted, retcode 10009 (done at 1.13845), order #10, deal #10, filled 0.62 lots at 1.13845, last error 0

One limit of the data matters for everything that follows. The report states “History Quality: 18% real ticks”. The demo server supplied real ticks from 1 April 2026 only. For the 27 months before that, the tester generated ticks from minute bars. MetaQuotes documents this fallback and notes that the ask price is then the bid plus the spread stored in the minute bar. Source: real and generated ticks.

Check every trade against the rule

A backtest report tells you what the EA earned. It does not tell you whether the EA did what you asked. We checked that separately.

A small MQL5 script exported the EURUSD M15 bars of the test period from the chart. A Python script then rebuilt each day’s range and signals from those bars. It follows the written rule and never reads the EA source. Finally it compared its own result with the orders and deals in the tester report. The table shows how many of the 646 trades passed each comparison: all of them on direction, entry and exit, and all but one on stop, target and volume.

Scroll horizontally if needed

CheckResult
Days with a trade646, never more than one per server day
Direction equals the recomputed signal646 of 646
Entry at the open of the next bar, within the spread limit646 of 646
Stop on the opposite range boundary645 of 646
Target 1.5 times the stop distance from the entry645 of 646
Volume from 1% of the balance before the trade645 of 646
Exit by stop or target before 21:00, otherwise at 21:00646 of 646

The one deviating day is 1 April 2026, the first day with real ticks. Our exported chart history for that night starts at 01:45. The tester built two more bars from ticks and logged a lower range low. The EA’s stop, target and volume match the range in its own journal line. The difference lies in the two data sets.

The check found something the report hides. On 28 days the rule showed a signal and the EA placed no trade. On 12 more days it entered later than the first signal. The journal explains both with 497 lines like this one:

2025.03.18 09:30:00  Signal SELL: bar 2025.03.18 09:15 closed at 1.09040, below the range low 1.09063
2025.03.18 09:30:00  Entry skipped: spread 34 points exceeds MaxSpreadPoints 30

On that day the EA skipped a sell signal and then 16 buy signals in a row. It bought at 14:45, four hours after the first close above the range. That is exactly what the first two assumptions in the table above allow. It is probably not what you pictured when you read “buy when a bar closes above the range high”.

All but six of the 497 skipped entries fall into the period with generated ticks, where the spread comes from the stored minute bar. We cannot tell from here whether those spreads were real. The filter worked as written. The data it reacted to is the weak point.

The backtest result

The EA followed the rule, and the rule lost money. The table shows the Strategy Tester report for EURUSD M15 from 1 January 2024 to 30 September 2026 with a 10,000 USD deposit: a net loss of 1,562.18 USD, nearly all of it commission.

Scroll horizontally if needed

MeasureValue
Trades646 (286 with a profit, 44.27%)
Total net profit−1,562.18 USD (−15.6%)
Profit before commission−7.88 USD
Commission−1,554.30 USD
Profit factor0.94
Maximal equity drawdown3,202.08 USD (31.21%)
Exits154 by target, 262 by stop, 230 by time
Balance after each of the 646 trades from January 2024 to September 2026. The tester balance with commission falls from 10,000 to 8,438 USD. With commission added back the same trades end at 9,992 USD. Real ticks begin on 1 April 2026.
Original calculation from the tester report. The orange line adds the commission back to the same trades. It is not a second test without costs.

Before commission the 646 trades ended almost exactly at zero. The commission of 7 USD per lot turned that into a loss of 15.6%. Spread is already inside the first number, because the tester fills buys at the ask and sells at the bid.

The years differ widely. Split by calendar year, the same backtest lost money in 2024, ended flat in 2025 and gained in 2026:

Scroll horizontally if needed

PeriodTradesBefore commissionCommissionNet
2024244−1,768.36−721.88−2,490.24
2025218+332.75−386.84−54.09
2026 to 29 September184+1,427.73−445.58+982.15

The 129 trades on real ticks, from 1 April 2026, made 810.75 USD after commission. Do not read that as an edge. It is six months of one symbol with inputs nobody tested beforehand, and the 27 months before it lost 2,372.93 USD. A rule that is negative, flat and positive in three consecutive years has shown no stable behaviour.

This is a historical backtest. It is not an out-of-sample test, a demo-forward run or a live result. Our backtest versus live guide explains what each of those stages adds, and the cost-sensitivity study shows how quickly costs decide a result like this one.

What we did not test

The run above covers one path through the program. Several rules never executed:

  • Rule 3 after a restart. The tester does not restart an EA. The search in the account history ran once, at the start.
  • A netting account. The test account was a hedging account. MT5 hedging vs netting shows why that difference matters for an EA that closes its own position.
  • Rejected or partly filled orders. The tester filled every request at the requested price. A real server can reject, requote or fill a different volume. MetaQuotes requires checking the return code of every request; a sent order is not a completed fill. Source: OrderSend.
  • A closed market at 21:00, any symbol other than EURUSD and any timeframe other than M15.

The assistant’s own list adds more, among them stops that a broker does not accept together with a market order. If the EA stays silent on your chart, our EA-not-trading guide separates signal, permission, request and result.

Change one thing with a follow-up prompt

The backtest gives you a concrete case, and a concrete case is what a good follow-up prompt needs. To make the EA trade the first breakout only, do not ask for a “better strategy”. Describe one change and hand over the journal lines that show the old behaviour:

Change one behaviour in RX Range Breakout v1.00 and nothing else.

New rule: only the first closed bar outside the range may trigger an entry.
If that entry is skipped or fails, there is no trade on that day. Log one
line "first breakout not traded: <reason>".

Case that must change: on 2025.03.18 the first signal (SELL, bar 09:15) was
skipped for spread. v1.00 then bought at 14:45. The new version must not
trade on that day.

Return only the changed functions and name the lines you changed.

Then compile, repeat the same backtest and run the check again. The day you named must now show no trade, and all other days must still pass. We have not run this change. It alters the rule after we saw the result, so its backtest would belong to a new version with its own record.

Start smaller: test one function first

A trading EA is a large first step. Our first project for this guide was smaller: an EA that only logs a crossing of two moving averages and sends no orders. Its comparison sits in one pure function, which six fixed cases can test without market data:

int CrossDirection(double fast_old, double slow_old,
                   double fast_new, double slow_new)
{
   if(fast_old <= slow_old && fast_new > slow_new) return 1;
   if(fast_old >= slow_old && fast_new < slow_new) return -1;
   return 0;
}

On 26 September 2026 the six cases passed in an account-free MT5 build 6230 terminal. We also swapped the older and the newer values on purpose. The code still compiled, and the test returned −1 instead of 1. A compiler cannot know which point in time you meant, and a test case can.

The read that feeds this function is where generated code often goes wrong. In MQL5, iMA returns a handle, and the values come from CopyBuffer, which puts the older value first in a plain array. Source: CopyBuffer. The signal-logger project contains the source, the test harness, the compiler logs and a second, timer-driven run against native indicator buffers. That project was developed with a different assistant, which its README names.

Download and reproduce

Download the MQL5 project (ZIP). The prompt, the unchanged AI answer, MQL5 source, compile log, tester journal, trade list and the Python check. No executable, no account data.

The ZIP contains the prompt, the complete unchanged answer, the MQL5 source, the compile log, the tester report summary, all 3,230 journal lines of the EA, the trade list, the export script and the Python check. It contains no executable and no account data.

Use a demo account or a separate test installation. Copy the source into a subfolder of MQL5/Experts, compile it in MetaEditor and read the Errors tab. For the folder and compile route, see our MT5 EA installation guide, and for macOS the MetaTrader on Mac walkthrough.

Run the Strategy Tester with your own broker’s history. Your numbers will differ from ours, because prices, spreads, commission and server time differ. The useful comparison is your trade list against the rule. Read the “History Quality” line of your report before you read the profit. Our guide on how to read an MT5 Strategy Tester report goes through the report of this run line by line.

Friendly robot illustration representing the RoboXpert pen name.
AI-generated avatar

About the author

RoboXpert

Pen name

The person behind RoboXpert writes about expert advisors, trading evidence and programming, and develops their own trading software. They report 10 years of experience in these areas; this is self-reported, not an independently verified qualification or performance record.

Sources & further reading

Your next question

Continue reading

Build with AI

MT5 AI Assistant: Features, Permissions and Limits

Choose between code assistance and native platform actions.

Read the guide →
Setup & VPS

How to Install an Expert Advisor in MT5 on Windows

Install an EA in MetaTrader 5 on Windows: copy the EX5 into MQL5/Experts, compile MQ5 source with F7 or use Market. Then check that it started.

Read the guide →