MT5 EA Not Taking Trades: Checks, Causes, and Fixes
By FXNook Lab team

An MT5 EA that does not open trades is usually either not reaching its entry condition or is sending a request that the terminal or trade server rejects. First establish whether the EA tried to trade: inspect its decision path and the Experts and Journal tabs, then log the result of its MQL5 trade call with CTrade::ResultRetcode(). That tells you which part to investigate instead of changing entry rules at random.
Start by finding out whether the EA tried to trade
Make sure the EA is attached to the intended chart and that the chart has the symbol and timeframe you expect. In the terminal, the Algo Trading button must be enabled. In the EA’s properties, the option to allow algorithmic trading must also be enabled; the terminal’s Expert Advisors settings can restrict automated trading as well.
Open the Experts and Journal tabs at the bottom of MT5. The Experts tab commonly shows messages printed by the EA, while the Journal records terminal events such as initialization, permission problems and trade activity. Look at messages from the time the signal was expected, not only the most recent line.
These checks divide the problem into two cases:
- No trade attempt is logged: the EA may not have received a tick, may not have reached its entry code, or may have stopped at a signal condition or filter. A silent EA can still be running normally if its code prints nothing while it waits.
- A request is logged: inspect the result from the trade method and its server retcode. A rejected request points to execution constraints such as volume, stops, symbol permissions or filling mode.
A green compile result does not show that an EA reaches its trading code or that a broker will accept its request. For an MT5-specific contrast with the order-based checks used in MT4, see MT4 EA Not Opening Trades: Checks, Causes and Fixes.
Trace the entry decision path
Start at the code that should produce a signal and follow the conditions in the order the EA evaluates them. An entry can be blocked before any call to Buy(), Sell() or OrderSend(). Common gates include a spread ceiling, time window, trading-session rule, minimum history requirement, open-position limit, daily trade limit or a check that waits for a new bar.
Inspect the exact values each condition uses. A spread limit can be expressed in points, while a trader may be thinking in pips; on a fractional-pip quote, confusing the two can make a filter much stricter than intended. A session filter can also compare against broker server time when the developer expected local time.
Indicator logic needs the same scrutiny. In MQL5, many built-in indicators such as iMA return a handle. The EA then needs to retrieve indicator values with CopyBuffer() and handle the case where the requested data is not ready or the copy fails. If the logic reads the current, unfinished bar, a condition may appear briefly or change before the EA evaluates it as expected.
Log both the decision and the values behind it. For each entry gate, record a clear pass or fail and the relevant measurement, such as current spread, bars available, session status or position count. That makes the first blocking rule visible. Avoid logging only “no signal”: it does not tell you which condition failed or whether the signal data was available.
For example, the output could say that the signal passed but the spread filter failed because the observed spread exceeded the configured maximum. If every rule passes but no request follows, trace the code between the final gate and the trade call. A return, a failed position check or an error branch in that section can prevent execution without producing a broker retcode.
Log the MQL5 trade result and server retcode
With the standard MQL5 CTrade class, the boolean returned by Buy() or Sell() is not, by itself, proof that a deal was executed. It indicates whether the method’s basic request checks succeeded; inspect ResultRetcode() and ResultRetcodeDescription() to learn the server’s response. The following diagnostic helper is an MQL5 EA code fragment and can be called at the point where the entry conditions have passed.
#include <Trade/Trade.mqh>
CTrade trade;
void TryBuy(const double volume, const double sl, const double tp)
{
const bool method_ok = trade.Buy(volume, _Symbol, 0.0, sl, tp,
"diagnostic entry");
const uint retcode = trade.ResultRetcode();
PrintFormat("Buy method=%s; retcode=%u (%s); deal=%I64u; order=%I64u",
method_ok ? "true" : "false",
retcode,
trade.ResultRetcodeDescription(),
trade.ResultDeal(),
trade.ResultOrder());
}
int OnInit()
{
return INIT_SUCCEEDED;
}
void OnTick()
{
// Call TryBuy(volume, sl, tp) only after the EA's entry rules pass.
}
This example does not submit a trade on every tick: connect TryBuy() to the EA’s real entry branch and preserve its existing position and risk checks. When diagnosing a live rejection, log the symbol, requested volume, stop-loss and take-profit values, and the signal or decision that led to the call as well as the retcode.
Retcodes help narrow the cause. For example, TRADE_RETCODE_INVALID_VOLUME (10014) means the requested volume is invalid, TRADE_RETCODE_INVALID_STOPS (10016) means the stops are invalid, and TRADE_RETCODE_MARKET_CLOSED (10018) means the market is closed. TRADE_RETCODE_NO_MONEY (10019) indicates insufficient funds for the request, while TRADE_RETCODE_INVALID_FILL (10030) points to an unsupported filling mode.
Also distinguish an accepted request from a completed deal. Retcodes such as TRADE_RETCODE_DONE, TRADE_RETCODE_DONE_PARTIAL and TRADE_RETCODE_PLACED describe different outcomes; a placed order is not the same as a confirmed filled deal. Read the description alongside the numeric code and, where relevant, inspect the resulting order or deal in the terminal’s trade history.
Check volume, stops, filling mode and symbol rules
MT5 symbol properties are specific to the instrument and broker. In Market Watch, right-click the symbol and choose Specification to inspect trading hours, volume limits, stop distance and other contract details. An EA can also read properties in code with functions such as SymbolInfoDouble() and SymbolInfoInteger().
| Possible cause | What to inspect | Practical fix |
|---|---|---|
| Invalid volume | SYMBOL_VOLUME_MIN, SYMBOL_VOLUME_MAX and SYMBOL_VOLUME_STEP. | Normalize the requested lots to the symbol’s allowed minimum and step, and do not exceed its maximum. Do not assume a lot size valid for one symbol is valid for another. |
| Stops too close or invalid | SYMBOL_TRADE_STOPS_LEVEL and the symbol’s current Bid or Ask. Check that stop-loss and take-profit prices are on the correct side of the market. | Calculate stop prices using the symbol’s point size and allowed distance. If the EA uses a trailing or break-even rule, check the modified stops too. |
| Unsupported filling mode | The symbol’s permitted filling policy and the TRADE_RETCODE_INVALID_FILL response. | Set a filling mode supported by that symbol. The CTrade method SetTypeFillingBySymbol() can select the symbol’s supported mode. |
| Market closed or trading disabled | Trading hours in the symbol specification, the market’s current session and SYMBOL_TRADE_MODE. | Test during an allowed session and verify that the symbol and account permit the requested type of trade. |
| Insufficient margin | The requested volume, account funds and the TRADE_RETCODE_NO_MONEY response. | Use a valid volume for the intended request and inspect the account’s margin situation. Do not treat a smaller volume as a guaranteed solution; the server response and account conditions determine acceptance. |
For a quick code-side inspection, log the properties for the exact symbol passed to the trade method. Be careful when the EA trades a different symbol from the chart: using _Symbol for the chart while sending a request for another instrument can make a property check irrelevant to the actual order.
In MQL5, a symbol’s filling rules matter at request time. A trade method can be reached and still fail because the configured filling policy is not accepted for that instrument. If you use SetTypeFillingBySymbol(), log its result and the symbol name; do not assume a setting used for another broker or symbol will work unchanged.
Check account mode and existing-position logic
MT5 accounts can use netting or hedging position rules. In a netting account, there is generally one combined position per symbol, and a new deal can add to, reduce or reverse that position. In a hedging account, multiple positions on the same symbol can exist separately, so code that selects or closes positions by symbol may not behave like code that works with a single net position.
Inspect the account mode with AccountInfoInteger(ACCOUNT_MARGIN_MODE). The returned value distinguishes retail netting, exchange and retail hedging modes. Then read the EA’s position logic alongside that setting, especially checks using PositionSelect(symbol) and loops over positions with PositionGetTicket() or PositionSelectByTicket().
A common silent blocker is a rule like “if a position exists on this symbol, return.” It can be intentional when the EA allows only one position, but it also means every later signal is skipped until that position disappears. On a netting account, the position is combined by symbol; on a hedging account, selecting by symbol does not automatically mean the EA has inspected every separate position. Verify that the logic matches the intended account mode and magic-number handling.
Close and reverse code needs the same review. An EA written around position tickets or multiple same-symbol positions can fail to find the position it expects on a netting account, while an EA that closes by symbol on a hedging account may not target the particular ticket intended. Log what the EA finds, including symbol, ticket, direction and magic number, before it blocks an entry or attempts a close.
Reproduce the failure in Strategy Tester
The Strategy Tester is useful when the missing entry can be reproduced from historical data or the EA’s rules can be examined in a controlled run. Use the same symbol, timeframe, EA inputs and a date range that includes the expected signal. Keep the tester’s account and execution settings as close as possible to the situation being investigated; a different symbol specification or account mode can produce different behavior.
- Open Strategy Tester, select the EA and choose the symbol and timeframe used on the chart.
- Enter the same inputs and select a date range that covers the expected entry. Use the modeling option appropriate to the EA’s logic, particularly if it depends on intrabar price changes.
- Run the test, then read its Journal and Experts output for initialization messages, decision logs, trade requests and retcodes.
- Use Visual mode when timing or chart context matters. Compare the bar or tick where you expect a signal with the EA’s logged condition values and the point where it calls the trade method.
- Repeat the run after a single targeted change, such as correcting a symbol property check or adding a missing decision log. Keep the inputs and date range fixed so the comparison is meaningful.
A test that shows no order is not enough to identify the cause. Compare the EA’s expected signal points with its logged rule results: if the signal rule fails, investigate the data and signal calculation; if it passes but the entry is blocked, follow the filter or position logic; if the request is sent, use its retcode and request parameters to investigate execution.
Tester behavior can differ from live trading because broker conditions, trading sessions, account settings and execution may differ. A reproducible tester result is a debugging aid, not proof that live requests will be accepted or that future trading results will match the test.
Final checklist before changing the code
- Permissions: the EA is on the intended chart, terminal Algo Trading is enabled, and algorithmic trading is allowed in the EA and terminal settings.
- Activity: the Experts and Journal tabs show the EA running, and the expected symbol and timeframe are in use.
- Signal conditions: the EA has the required bars and indicator data, and the signal is evaluated on the intended bar or tick.
- Filters: spread, time, session, daily limits and open-position rules log their inputs and pass or fail results.
- Request outcome: every attempted trade logs the method result, server retcode and description, plus the symbol, volume and stops sent.
- Symbol constraints: volume, stop distance, trading permission, market hours and filling mode match the selected instrument.
- Account mode: netting or hedging behavior is consistent with the EA’s position, entry, close and reverse logic.
- Repeatability: the same symbol, timeframe, inputs and date range reproduce the result in Strategy Tester, with logs that show the first blocking condition or rejected request.
If the cause is still unclear, collect the relevant Experts and Journal messages, the exact symbol and account mode, the EA inputs, the retcode and the section of code that evaluates and sends the entry. Remove account credentials and other private information before sharing files. For code that compiles but stops before a trade, the FXNook EA debugger can trace entry paths and explain what blocks them; for a running EA that waits silently, FXNook Telemetry reports its rules, decisions, orders, trades and errors without placing or changing trades.
The practical next step is to add decision logs at the EA’s entry gates and retcode logging at the trade call, then run the same case in Strategy Tester. If those logs still do not identify the blocker, use the collected code and terminal messages to investigate that specific branch rather than making several changes at once.
Questions
Why does my MT5 EA show no errors but not open trades?
The EA may be running but never reaching its trade call because a signal condition, spread or time filter, bar-data check, or existing-position rule blocks the entry. It may also send a request without printing the response. Log each entry condition and print the CTrade result retcode at the request point to distinguish those cases.
Where can I see why an MT5 trade request was rejected?
Start with the terminal’s Experts and Journal tabs, then inspect the EA’s trade result. With CTrade, print ResultRetcode() and ResultRetcodeDescription() immediately after Buy() or Sell(); these show the server response, including reasons such as invalid volume, invalid stops or unsupported filling mode.
How do I check whether an MT5 EA's entry conditions are being met?
Add a log for each rule in the entry path, recording whether it passed and the values it used, such as spread, indicator data, session status and position count. If all rules pass, log whether the trade method is called and its retcode; if a rule fails, the first failed log identifies where to investigate.