Ways to capture signals from an EX5 (when MQ5 not available)

31 October 2025, 07:53
Rajesh Kumar Nait
0
93
Here are some ways :
  1. Monitor trades / positions (most reliable)

    • Watch for new deals/orders/position changes using OnTradeTransaction() or by snapshotting PositionsTotal() and PositionGet... properties.

    • You can detect: symbol, volume, magic number, comment, price, direction — then trigger your action.

    • Works even if the other EA is EX5 because all trade operations go through the terminal.

  2. Detect chart objects the EA draws (arrows, labels)

    • Some EAs draw arrows/text when they signal. You can scan chart objects ( ObjectsTotal , ObjectName , ObjectGet ) and react to a new object.

    • Less reliable (object naming conventions vary).

  3. Read Terminal Global Variables

    • If the EX5 EA uses GlobalVariableSet() to publish signals, your EA can GlobalVariableGet() them. Requires that EA to actually use global variables.

  4. Read files / shared memory / DLL / windows messages

    • Only possible if the EX5 writes files or uses a DLL / shared mechanism. Rare and often unsafe (DLLs require terminal settings and are platform dependent).

  5. Use iCustom / indicators

    • If the EX5 uses a visible indicator with accessible buffers you can call iCustom() to read buffers. Only works if that indicator is present and you know buffer indices.

Recommended approach
  • Use trade/position monitoring. It's simple, reliable and requires no cooperation from the other EA.

  • If you cannot distinguish which EA placed a trade, let the user pick a trade from history to “follow”, or auto-detect the first trade after attaching your EA and store its magic/comment to follow subsequent trades.


Example MQL5 EA — listens for other EAs' trade activity and reacts

This EA:

  • builds a set of currently known position tickets on init,

  • uses OnTradeTransaction() to detect trade changes,

  • when it sees a new position open or position closed, it calls OnExternalSignalDetected(...) where you place your custom action (open hedge, notify, etc.),

  • shows how to auto-detect the other EA's magic/comment or let user specify it.

Paste the code into MetaEditor as a new EA and compile.

//+------------------------------------------------------------------+
//|  FollowExternalTrades.mq5                                        |
//|  Example: detect other EA's opens/closes and react               |
//+------------------------------------------------------------------+
#property copyright "Example"
#property version   "1.00"
#property strict

input long   FollowMagic = -1;    // if >=0 follow this magic; -1 = auto-detect first external trade
input string FollowComment = "";  // optionally follow by comment (non-empty to match)
input bool   AutoDetect = true;   // when FollowMagic==-1 try to auto-detect

// internal storage of known position tickets
ulong knownTickets[];

//+------------------------------------------------------------------+
//| Utility: add ticket if not present                                |
//+------------------------------------------------------------------+
void AddKnownTicket(ulong ticket)
{
   for(int i=0;i<ArraySize(knownTickets);i++)
      if(knownTickets[i]==ticket) return;
   ArrayResize(knownTickets, ArraySize(knownTickets)+1);
   knownTickets[ArraySize(knownTickets)-1] = ticket;
}

//+------------------------------------------------------------------+
//| Utility: remove ticket                                            |
//+------------------------------------------------------------------+
void RemoveKnownTicket(ulong ticket)
{
   int idx=-1;
   for(int i=0;i<ArraySize(knownTickets);i++)
      if(knownTickets[i]==ticket) { idx=i; break; }
   if(idx==-1) return;
   for(int j=idx;j<ArraySize(knownTickets)-1;j++) knownTickets[j]=knownTickets[j+1];
   ArrayResize(knownTickets, ArraySize(knownTickets)-1);
}

//+------------------------------------------------------------------+
//| Utility: is known                                                 |
//+------------------------------------------------------------------+
bool IsKnownTicket(ulong ticket)
{
   for(int i=0;i<ArraySize(knownTickets);i++)
      if(knownTickets[i]==ticket) return true;
   return false;
}

//+------------------------------------------------------------------+
//| Called on initialization                                          |
//+------------------------------------------------------------------+
int OnInit()
{
   ArrayResize(knownTickets,0);
   // populate knownTickets with current positions so only new ones are detected
   int total = PositionsTotal();
   for(int i=0;i<total;i++)
   {
      if(PositionSelectByIndex(i))
      {
         ulong ticket = (ulong)PositionGetInteger(POSITION_TICKET);
         AddKnownTicket(ticket);
      }
   }
   Print("FollowExternalTrades initialized. Known positions: ", ArraySize(knownTickets));
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Called on deinitialization                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // cleanup if needed
}

//+------------------------------------------------------------------+
//| Called for every trade transaction in terminal                    |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   // Keep it simple: when any transaction occurs, re-scan positions and detect differences
   // This is robust and avoids deep parsing of MqlTradeTransaction fields.
   DetectPositionChanges();
}

//+------------------------------------------------------------------+
//| Helper: scan positions and detect new opens / closes              |
//+------------------------------------------------------------------+
void DetectPositionChanges()
{
   // Build a set of current position tickets
   ulong currentTickets[];
   ArrayResize(currentTickets, 0);
   int total = PositionsTotal();
   for(int i=0;i<total;i++)
   {
      if(PositionSelectByIndex(i))
      {
         ulong ticket = (ulong)PositionGetInteger(POSITION_TICKET);
         ArrayResize(currentTickets, ArraySize(currentTickets)+1);
         currentTickets[ArraySize(currentTickets)-1] = ticket;
      }
   }

   // detect newly opened positions (present in current but not in known)
   for(int i=0;i<ArraySize(currentTickets);i++)
   {
      ulong t = currentTickets[i];
      if(!IsKnownTicket(t))
      {
         // New position detected
         if(PositionSelectByTicket(t))
         {
            long magic = (long)PositionGetInteger(POSITION_MAGIC);
            string comment = PositionGetString(POSITION_COMMENT);
            string sym = PositionGetString(POSITION_SYMBOL);
            double vol = PositionGetDouble(POSITION_VOLUME);
            int ptype = (int)PositionGetInteger(POSITION_TYPE); // 0 = long, 1 = short
            datetime time = (datetime)PositionGetInteger(POSITION_TIME);

            // If user requested filtering by magic/comment, respect it
            bool match = true;
            if(FollowMagic>=0 && magic!=FollowMagic) match = false;
            if(StringLen(FollowComment)>0 && comment!=FollowComment) match = false;

            // If auto-detect is enabled and FollowMagic==-1, set FollowMagic to magic of first detected
            if(AutoDetect && FollowMagic==-1 && match)
            {
               FollowMagic = magic;
               PrintFormat("Auto-detected FollowMagic = %d (comment='%s')", FollowMagic, comment);
            }

            // If following by magic/comment and this matches, call handler
            if((FollowMagic==-1 || magic==FollowMagic) && (StringLen(FollowComment)==0 || comment==FollowComment))
            {
               PrintFormat("Detected NEW position: ticket=%I64u sym=%s type=%d vol=%.2f magic=%d comment=%s time=%s",
                           t, sym, ptype, vol, magic, comment, TimeToString(time, TIME_DATE|TIME_SECONDS));
               OnExternalSignalDetected(true, t, sym, ptype, vol, magic, comment, time);
            }

            // Add to known set regardless to avoid repeated processing
            AddKnownTicket(t);
         }
      }
   }

   // detect closed positions (present in known but not in current)
   // copy knownTickets to iterate to avoid mutation issues
   int knownCount = ArraySize(knownTickets);
   for(int i=knownCount-1;i>=0;i--)
   {
      ulong t = knownTickets[i];
      bool stillExists = false;
      for(int j=0;j<ArraySize(currentTickets);j++) if(currentTickets[j]==t) { stillExists=true; break; }
      if(!stillExists)
      {
         // position closed
         PrintFormat("Detected CLOSED position ticket=%I64u", t);
         OnExternalSignalDetected(false, t, "", -1, 0.0, 0, "", 0);
         RemoveKnownTicket(t);
      }
   }
}

//+------------------------------------------------------------------+
//| User hook: called when an external position open/close detected  |
//| is_open = true => open detected; false => closed detected        |
//+------------------------------------------------------------------+
void OnExternalSignalDetected(bool is_open, ulong ticket, string symbol, int pos_type, double volume, long magic, string comment, datetime open_time)
{
   // --> PUT YOUR ACTIONS HERE <--
   // Examples:
   //  - Place a hedging order
   //  - Send notification / email
   //  - Copy the trade
   //  - Update internal state

   if(is_open)
   {
      // Example: print and (example) open a small opposite position as reaction:
      PrintFormat("*** ACTION: external OPEN detected. Ticket=%I64u symbol=%s type=%d vol=%.2f magic=%d comment=%s",
                  ticket, symbol, pos_type, volume, magic, comment);

      // Example placeholder: open 0.01 lot opposite (CAUTION: real trading)
      // double lots = 0.01;
      // int opposite_type = (pos_type==POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
      // (You would use trade.Request/OrderSend here - omitted to avoid accidental trading)

   }
   else
   {
      PrintFormat("*** ACTION: external CLOSE detected. Ticket=%I64u", ticket);
      // handle close: maybe close your mirror order or log
   }
}

//+------------------------------------------------------------------+
//| Helper: select position by ticket                                 |
//+------------------------------------------------------------------+
bool PositionSelectByTicket(ulong ticket)
{
   // iterate positions and match ticket
   for(int i=0;i<PositionsTotal();i++)
   {
      if(PositionSelectByIndex(i))
      {
         if((ulong)PositionGetInteger(POSITION_TICKET) == ticket) return true;
      }
   }
   return false;
}

//+------------------------------------------------------------------+
//| OnTick - nothing heavy here                                       |
//+------------------------------------------------------------------+
void OnTick()
{
   // EA idle; logic is event driven by OnTradeTransaction
}