BLOG

How I test a MetaTrader 5 EA or indicator before delivery

By Nguyễn Hải Minh · Published · 3 min read

Before I deliver an MT5 Expert Advisor, indicator or utility, I check each behaviour it claims on a demo terminal or in the Strategy Tester, compare what happened with a result I worked out separately, and write down what I checked and what I didn't. A passed check means the code does what it says, for example refusing an entry or closing a position at a limit. It is not evidence that a strategy will make a profit, and I don't present it as one.

A library of blocks with a status on each

Most of what I build in MQL5 is assembled from reusable blocks: entries, exits, filters, risk limits, position sizing. Each block has a row in a registry with one of three statuses:

  • verified: the block's behaviour was checked in the Strategy Tester and the evidence is recorded with a date and a result.
  • unit_tested: its automated unit checks pass, but it doesn't yet have the full tester evidence.
  • rejected: I tried it and dropped it, with the reason written down.

In the registry export of 9 November 2026 there were 108 blocks: 80 verified, 25 unit_tested and 3 rejected. The split matters to me more than the total. If a client's EA depends on a block that is only unit_tested, I say so before we agree on anything.

A status only describes behaviour. A block that passes still tells you only that it filters, sizes or closes the way its description says.

What a block test looks like

Take one entry filter based on the daily range: it allows or refuses a new entry depending on how much of the average daily range has already been used. I ran it in the Strategy Tester with four different parameter sets. For each run I had an expected list of allow and refuse decisions, computed independently of the MQL5 code, and compared the two. In every run shown there were zero wrong allows and zero wrong refusals, and the block's 35 unit checks ran without a failure.

The independent expected result matters most. If the same code produces both the decisions and the answer key, a test can pass while both are wrong.

Utilities get a Checked and a Not checked list

For small tools such as a stop-loss audit panel, an exposure panel or an equity protector, every screenshot I publish carries a label. Checked means I saw that behaviour work on a demo terminal or a Strategy Tester virtual account. Not checked means the feature exists but I haven't confirmed it yet.

The equity protector is a good example. Checked on demo: it locks when the money limit is hit, closes a newly opened position within 3 seconds, and keeps the lock after a restart. Not checked: percent and drawdown limits, the daily target and the reset at a new day. The test also showed something a client should know before relying on it: the limit is a trigger level, so the loss at the moment of locking can be slightly larger than the limit.

The pending order expiry manager is similar. Listing orders, assigning a timer automatically and deleting expired orders were checked, in a test of about one minute (62 seconds). The panel buttons and what happens to the countdown after a restart were not.

Why I don't turn this into a profit claim

None of these checks ran on a live account, and none of them measure profit. A verified exit block closes trades when it should. Whether the strategy around it earns money is a separate question, and a block status can't answer it. When I deliver, the client gets the list of what was checked, where it was checked (demo or tester), and what was left out.

If you have an EA, indicator or MT5 tool you want built or fixed, send me what it should do and how you run it today, including the symbol, timeframe and account type. I'll tell you which parts I can check on a tester and which ones need a demo account.