🚀 AI One-Click Generation of mql4 Strategy Code

How to Make Your Mql4 EA Safer with Environment & Trade Context Checks

mql4 | Published on: 2025/12/5
The following content is generated by EasyQuant .

Problem Description

How can I check if my trading robot is allowed to trade, if it's connected to the server, and if the trade context is busy before placing an order?

Solution

To ensure robust execution in MQL4, you should perform these checks sequentially. Since the trading context can be temporarily busy (e.g., another Expert Advisor is currently trading), it is best practice to implement a retry mechanism rather than immediately failing.

Here is the complete MQL4 code implementing a robust check function.

MQL4 Implementation

//+------------------------------------------------------------------+
//|                                            CheckTradeStatus.mq4  |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Example logic: Place a Buy order if conditions are met
   // This is just a trigger example
   if(OrdersTotal() == 0) 
   {
      // 1. Perform the safety checks before attempting to trade
      if(CheckTradingEnvironment())
      {
         // 2. If checks pass, refresh rates to ensure Ask/Bid are current
         RefreshRates(); 
         
         // 3. Place the order
         int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "My Order", 0, 0, clrGreen);
         
         if(ticket < 0)
         {
            Print("OrderSend failed with error #", GetLastError());
         }
         else
         {
            Print("Order placed successfully. Ticket: ", ticket);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Function to check connection, permissions, and trade context     |
//+------------------------------------------------------------------+
bool CheckTradingEnvironment()
{
   // 1. Check connection to the server
   if(!IsConnected())
   {
      Print("Error: Terminal is not connected to the server.");
      return(false);
   }

   // 2. Check if trading is allowed (AutoTrading button + EA Permission)
   // Note: IsTradeAllowed() checks both the global terminal setting and the specific EA setting.
   if(!IsTradeAllowed())
   {
      Print("Error: Trading is not allowed. Check 'AutoTrading' button and EA properties.");
      return(false);
   }

   // 3. Check if Trade Context is busy (with retry mechanism)
   // The trade context might be busy if another EA is trading at the exact same moment.
   int retryCount = 0;
   int maxRetries = 10;
   int sleepTime  = 100; // Milliseconds

   while(IsTradeContextBusy())
   {
      // If context is busy, wait and try again
      Sleep(sleepTime);
      retryCount++;

      // If we exceeded max retries, abort
      if(retryCount >= maxRetries)
      {
         Print("Error: Trade context is busy. Timeout after ", (maxRetries * sleepTime), "ms.");
         return(false);
      }
   }

   // If we waited for the context to clear, we must refresh market info
   // because prices might have moved during the Sleep()
   if(retryCount > 0)
   {
      RefreshRates();
   }

   // All checks passed
   return(true);
}

Explanation of Functions Used

  1. IsConnected():

    • Returns true if the client terminal is connected to the broker's server. If this returns false, OrderSend will inevitably fail.
  2. IsTradeAllowed():

    • This function performs a dual check:
      1. Is the "AutoTrading" button in the terminal toolbar enabled?
      2. Is the "Allow live trading" checkbox enabled in the specific Expert Advisor's properties (Common tab)?
    • If either is disabled, it returns false.
  3. IsTradeContextBusy():

    • In MetaTrader 4, only one thread is available for trading operations across the entire terminal. If you have multiple charts with different EAs, they cannot trade simultaneously.
    • If EA #1 is sending an order, the context becomes "Busy". If EA #2 tries to trade at that exact millisecond, OrderSend would fail with error 146 (ERR_TRADE_CONTEXT_BUSY).
    • The Solution: The while loop in the code above waits (using Sleep) for the context to free up before proceeding.
  4. RefreshRates():

    • If the code enters the Sleep() loop because the context was busy, time passes. During that time, the Ask and Bid variables stored in the cache might become outdated. RefreshRates() updates these variables to the absolute latest market prices.

Q&A

Q: Why do I need RefreshRates() after checking IsTradeContextBusy()?
A: MQL4 stores Ask and Bid prices when OnTick starts. If your code pauses (using Sleep) to wait for the trade context to clear, the market prices may change. RefreshRates() forces the EA to fetch the newest prices, preventing "Invalid Price" or "Requote" errors.

Q: Can IsTradeAllowed() return false even if AutoTrading is on?
A: Yes. It can return false if the specific EA does not have the "Allow live trading" permission checked in its properties, or if the terminal is logged in with an Investor (read-only) password.

Q: Does IsTradeContextBusy() exist in MQL5?
A: No. MQL5 is multi-threaded regarding trading operations, so multiple EAs can trade simultaneously without blocking each other. This check is specific to the architecture of MQL4.