Can't manage to individually count the number of trade for multiple bot (running at the same time)

 

Hi everyone, 

am currently facing an issue that I can't seem to overcome. I am running multiple bots on a single VPS. The problem is that, in my trading system, the expert advisor can only have one open position at a time.

At first, I used PositionsTotal , but I noticed that it counts the number of active positions across the entire account. As a result, when one bot opened a trade, all the other bots were unable to trade because one of the conditions for entering a position is that PositionsTotal must be equal to 0.

For now, here is the solution I have found:


int myposition = 0;
bool firstSlChange = false; // Utilisation d'une fonction bool comme stockage spécifique pour suivre le premier changement (ATR First Stoploss), dont affect my problem here)
void OnTick(){ // Initialisation de la fonction Ontick(), effectuée à chaque changement de prix
   if(myposition == 0){ // Si aucune le nombre de trades en cours est égal à 0
      firstSlChange = false; // La valeur de firstSlChange est mis à 'false'
      }
 myposition = 0; // Réinitialiser le compteur de positions
   for(int i = 0; i < PositionsTotal(); i++){
      ulong posTicket = PositionGetTicket(i); // Récupère le ticket de la position à l'index i
      if(posTicket > 0){ // Vérifie que le ticket est valide
         if (PositionSelectByTicket(posTicket)){ // Sélectionne la position par son ticket
            // Vérifie si le symbole et le Magic Number correspondent
            if(PositionGetSymbol(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == Magic){
               myposition++; // Incrémente si la position correspond
               }
            } 
            else{
 Print("Erreur : impossible de sélectionner la position avec le ticket ", posTicket);
               }
         }
      }
   Print("Nombre de positions spécifiques au bot : ", myposition);
 // Cette boucle permet de parcourir toutes les positions ouvertes sur le compte de trading
   for(int i = 0; i < PositionsTotal(); i++){ // 'int i = 0' initialise la variable à 1 ce qui veut indique que la boucle commence à la 1ère position. 'i = i + 1' à chaque itération, la variable i est incrémentée de 1, ce qui permet de passer à la position suivante
      ulong posTicket = PositionGetTicket(i); // 'ulong posTicket' cette variable stock cet identifiant pour la position spécifiée par 'i. 'PositionGetTicket(i)'est la variable qui renvoie le ticket de la position de l'index 'i' passé en argument.
      if(posTicket > 0){
         if(PositionSelectByTicket(posTicket)){
            if(PositionGetSymbol(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == Magic){
void executeBuy(){ // Fonction d'achat   
   if(myposition == 0){

This seemed to solve the problem, but I occasionally noticed that the bot could take two positions at the same time. After some thought, I realized that this might be due to the fact that MyPosition resets to 0 on every tick. With market stress or latency, it sometimes happened that the loop didn't have enough time to verify itself, and MyPosition remained at 0 long enough to allow the bot to open another position.

That’s why I considered a second solution:

bool isTradeActive = false; // Indique si une position pour ce bot est active
bool isCheckingPositions = false; // Verrou pour éviter les vérifications concourrantes
void OnTrade(){
   // Réinitialiser `isTradeActive` et vérifier les positions
   Print("OnTrade déclenché - Mise à jour des positions");
   isTradeActive = false;
   
   for (int i = 0; i < PositionsTotal(); i++){
      ulong posTicket = PositionGetTicket(i);
      if (posTicket > 0 && PositionSelectByTicket(posTicket)){
         // Vérifie si le symbole et le Magic Number correspondent
         if (PositionGetSymbol(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == Magic){
            isTradeActive = true;
            break;
            }
         }
      }      
      // Debugging : afficher l'état des positions
      Print("Trade en cours (OnTrade) : ", isTradeActive);
   }
//+------------------------------------------------------------------+
//| Fonctions appelées à chaque tick                                 |
//+------------------------------------------------------------------+
void OnTick(){ // Initialisation de la fonction Ontick(), effectuée à chaque changement de prix
   if(isCheckingPositions){
      Print("vérification en cours en attente...");
      return;
      }
      
   // Activer le verrou pour éviter les exécutions concourrantes
   isCheckingPositions = true;
   
   // Vérifier les positions ouvertes
   bool tradeActive = false;
   for(int i = 0; i < PositionsTotal(); i++){
      ulong posTicket = PositionGetTicket(i);
      if (posTicket > 0 && PositionSelectByTicket(posTicket)){
         // Vérifie si le symbole et le Magic Number correspondent
         if (PositionGetSymbol(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == Magic){
            tradeActive = true; // Une position correspondant à ce bot est trouvée
            break;
            }
         }
      }
   // Mettre à jour "isTradeActive" après la vérification
   isTradeActive = tradeActive;
   
   // Libérer le verrou
   isCheckingPositions = false;
   
   // Debugging : afficher l'état des positions
   Print("trade en cours (OnTick) : ", isTradeActive);
   if(isTradeActive){ // Si le nombre de trades en cours est égal à 0
      firstSlChange = false; // La valeur de firstSlChange est mis à 'false'
      }
      
//+---------------------Boucle positions ouvertes----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   // Cette boucle permet de parcourir toutes les positions ouvertes sur le compte de trading
   for(int i = 0; i < PositionsTotal(); i++){ // 'int i = 0' initialise la variable à 1 ce qui veut indique que la boucle commence à la 1ère position. 'i = i + 1' à chaque itération, la variable i est incrémentée de 1, ce qui permet de passer à la position suivante
      ulong posTicket = PositionGetTicket(i); // 'ulong posTicket' cette variable stock cet identifiant pour la position spécifiée par 'i. 'PositionGetTicket(i)'est la variable qui renvoie le ticket de la position de l'index 'i' passé en argument.
      if(posTicket > 0){
         if(PositionSelectByTicket(posTicket)){
            if(PositionGetSymbol(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == Magic){
void executeBuy(){ // Fonction d'achat   
   if(isTradeActive == false){

However, after testing, I noticed that the bot takes multiple positions each time the conditions allow it.

I really don’t understand how I can run multiple bots simultaneously on different symbols while integrating a system that calculates the number of positions specific to each bot, without encountering issues related to stress or delays.

Thank you very much in advance for your help.

Schmitt Alexis 

 
Your topic has been moved to the section: Expert Advisors and Automated Trading
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
 
Fernando Carreiro #:
Your topic has been moved to the section: Expert Advisors and Automated Trading
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
Sorry for that, thank you 
 

It sounds like a situation where you're not establishing a unique magic number in the different expert advisors. I think you're also just overcomplicating the code

if(PositionsTotal() == 0 && magicNumber == Magic){

  // open one position if no positions are active in *this* EA
}
 
Conor Mcnamara #:

It sounds like a situation where you're not establishing a unique magic number in the different expert advisors. I think you're also just overcomplicating the code

Hello,

I have read your response carefully, and first of all, I thank you. However, no matter how I analyze the problem, it still doesn’t work. I believe there are several reasons for this, and that we may have misunderstood each other.

As I mentioned in my previous message, I have several bots running on the same VPS, but each of them has a different “magic number.”

I also think that using “PositionsTotal” is not a viable solution because, in MQL5, this function returns the total number of open positions for any bot, regardless of the “magic number.” Therefore, even if we specify a certain “magic number” in the “if” function, it will not work.

Regarding the solution you provided, first of all, I am not sure what you mean by “magicNumber” in the “if” function. Is this a variable that needs to be created, or is it an existing variable in MQL5? Additionally, the “if” condition can never be true and allow positions to be opened because we have “&&,” which means both conditions must be met. Since “PositionsTotal” checks whether positions are open across all bots, this does not solve the problem, as the conditions will always be false unless no positions are open on any bot in the VPS.

However, I want each bot to take positions and trade independently. Am I mistaken?

I appreciate the time you are taking to read this.

Best regards,
Schmitt Alexis
 
Alexis Schmitt #:
Hello …

struct MqlTradeRequest
  {
   ENUM_TRADE_REQUEST_ACTIONS    action;           // Trade operation type
   ulong                         magic;            // Expert Advisor ID (magic number)
   ulong                         order;            // Order ticket
   string                        symbol;           // Trade symbol
   double                        volume;           // Requested volume for a deal in lots
   double                        price;            // Price
   double                        stoplimit;        // StopLimit level of the order
   double                        sl;               // Stop Loss level of the order
   double                        tp;               // Take Profit level of the order
   ulong                         deviation;        // Maximal possible deviation from the requested price
   ENUM_ORDER_TYPE               type;             // Order type
   ENUM_ORDER_TYPE_FILLING       type_filling;     // Order execution type
   ENUM_ORDER_TYPE_TIME          type_time;        // Order expiration type
   datetime                      expiration;       // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type)
   string                        comment;          // Order comment
   ulong                         position;         // Position ticket
   ulong                         position_by;      // The ticket of an opposite position
  };

magic

Expert Advisor ID. It allows organizing analytical processing of trade orders. Each Expert Advisor can set its own unique ID when sending a trade request.


Before executing the order placement operation, check if there are any open positions. Loop through their magic numbers, and if one matches the EA's input magic number, you'll know that the EA already has a position open and you should skip the process.

 

I agree with you that this doesn't seem to work and I'm also at a loss here

I'm using the trade library, I set the magic number in OnInit: 

trade.SetExpertMagicNumber(expert_magic);    

then before I execute the trade, I try to request the magic number using RequestMagic() function

https://www.mql5.com/en/docs/standardlibrary/tradeclasses/ctrade/ctraderequestmagic

if(allow_buy && bearTrend[0] == 0 && trade.RequestMagic() == expert_magic){ 

}

but then it won't execute any position

Sorry, I don't know

Documentation on MQL5: Standard Library / Trade Classes / CTrade / RequestMagic
Documentation on MQL5: Standard Library / Trade Classes / CTrade / RequestMagic
  • www.mql5.com
Gets the magic number of the Expert Advisor. Return Value The magic number (ID) of the Expert Advisor, used in the last request...
 

I just saw now that the magic number doesn't become active until the first position is opened, which is because magic number is sent with the order I guess, but ideally it should work different in the framework (in my opinion).

So you will have to make a function like this:

int GetOpenPositionCount( int cnt)
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      if(PositionGetSymbol(i) == _Symbol && PositionSelect(_Symbol) && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
        {
         cnt++;
         magicNumberActive = true;
         break;
     
        }
     }
   return cnt;
  }

with a global bool variable "magicNumberActive" initialized as false


then execute your positions in such a way:

if(magicNumberActive && trade.RequestMagic == magicNumber){

 // execute trades

}
else{

 // execute the first position without magic number
}