MT5 et la vitesse en action - page 19

 
Roman:

Les programmeurs C.

L'exemple est très simple dans ce cas. Le calcul de ladurée de vie totale de toutes les positions fermées est une tâche beaucoup plus difficile pour les performances rapides.

 
fxsaber:

L'exemple est très simple dans ce cas. Le calcul de ladurée de vie totale de toutes les positions fermées est une tâche beaucoup plus difficile pour une performance rapide.

Je vous ai expliqué la raison plus tôt, mais vous ne l'avez pas prise en compte.

 
Roman:

Je vous ai expliqué la raison plus tôt mais vous n'en avez pas tenu compte.

Apparemment, je dois chercher votre explication sur le forum.

 
fxsaber:

Apparemment, je dois chercher votre explication sur le forum.

La dernière fois, vous avez rencontré un problème similaire, où le paramètre passé n'était pas mis en cache, mais transmis directement dans le code.
Et après l'avoir mis en cache, la vitesse a augmenté. Toujours allouer de la mémoire pour une variable et ne l'utiliser que plus tard.
C'est la même chose ici, vous déclarez une variable, la mémoire est déjà allouée et le travail ultérieur avec la variable sera plus rapide puisqu'il n'y a pas de coûts d'allocation de mémoire.

Cela s'applique également à la récupération de valeurs à partir de fonctions mql.
Même les développeurs recommandés ici sur le forum, récupèrent d'abord une valeur d'une fonction dans une variable, puis utilisent cette variable dans une condition if().

 
fxsaber:

Le calcul de ladurée de vie cumulée de toutes les positions fermées est une tâche beaucoup plus difficile pour les performances rapides.

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

Bibliothèques : MT4Orders

fxsaber, 2020.08.29 04:17

#include <Generic\HashMap.mqh>

// Возвращает общую длительность всех закрытых позиций.
int SumPositionsLengthMQL5( void )
{
  int Res = 0;
  
  if (HistorySelect(0, INT_MAX))
  {
    CHashMap<ulong, ulong> DealsIn;  // По PositionID возвращает DealIn.
    const int TotalDeals = HistoryDealsTotal();
    
    for (int i = 0; i < TotalDeals; i++)
    {
      const ulong TicketDeal = HistoryDealGetTicket(i);
      
      if (HistoryDealGetInteger(TicketDeal, DEAL_ENTRY) == DEAL_ENTRY_IN)
        DealsIn.Add(HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID), TicketDeal);
      else if (HistoryDealGetInteger(TicketDeal, DEAL_TYPE) <= DEAL_TYPE_SELL)
      {
        ulong TicketDealIn;
        
        if (DealsIn.TryGetValue(HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID), TicketDealIn))
          Res += (int)(HistoryDealGetInteger(TicketDeal, DEAL_TIME) - HistoryDealGetInteger(TicketDealIn, DEAL_TIME));        
      }        
    }
  }
      
  return(Res);
}

Il y a peut-être une option plus rapide. Mais un pas vers la gauche dans l'état de ce qui doit être calculé, et la logique peut devoir changer considérablement. Pas facile, en général.

 
fxsaber:

Il y a peut-être une option plus rapide. Mais un pas vers la gauche dans la condition de ce qui doit être compté, et la logique peut devoir changer considérablement. Pas facile, en général.

Ce n'est pas la condition, c'est l'écriture du code.
Bien que vous puissiez remplacer la condition par un interrupteur, il fonctionnera plus rapidement que n'importe quel autre.
Essayez ce code, est-ce que ça ira plus vite ou pas ? Si ce n'est pas le cas, essayez de remplacer l'interrupteur.
J'espère que vous comprenez maintenant le point, à savoir que toutes les déclarations de variables doivent être mises hors de la boucle, et ne pas les ré-exécuter 100500 fois.
De plus, pour chaque valeur retournée, allouez de la mémoire sous forme de variable.

#include <Generic\HashMap.mqh>

// Возвращает общую длительность всех закрытых позиций.
int SumPositionsLengthMQL5( void )
{
   int  Res     = 0;
   bool HSelect = false;
  
   HSelect = HistorySelect(0, INT_MAX);
  
   if(HSelect)
   {
      CHashMap<ulong, ulong> DealsIn;  // По PositionID возвращает DealIn.
    
      int   TotalDeals   = 0;
      ulong TicketDeal   = 0;
      bool  condition1   = false;
      bool  condition2   = false; 
      bool  condition3   = false;       
      long  PositionID   = 0;
      ulong TicketDealIn = 0;
      int   DealTime     = 0;
    
      TotalDeals = HistoryDealsTotal();
    
      for(int i=0; i < TotalDeals; i++)
      {
         TicketDeal =  HistoryDealGetTicket(i);      
         condition1 = (HistoryDealGetInteger(TicketDeal, DEAL_ENTRY) == DEAL_ENTRY_IN);
         condition2 = (HistoryDealGetInteger(TicketDeal, DEAL_TYPE) <= DEAL_TYPE_SELL);
      
         if(condition1)
         {
            PositionID = HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID);
            DealsIn.Add(PositionID, TicketDeal);          
         }
         else if(condition2)
         {       
            PositionID = HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID);
            condition3 = DealsIn.TryGetValue(PositionID, TicketDealIn);
         
            if(condition3) 
            {
               DealTime = (int)(HistoryDealGetInteger(TicketDeal, DEAL_TIME) - HistoryDealGetInteger(TicketDealIn, DEAL_TIME));
               Res += DealTime; 
            }   
         }        
      }
   }
     
   return(Res);
}
 

Il s'agit d'une autre variante du code, de sorte que nous n'avons pas à arracher l'histoire pour la deuxième condition.
Vous pouvez également penser à la condition qui sera remplie le plus souvent, la placer en premier dans la boucle, et continuer l'itération.

#include <Generic\HashMap.mqh>

// Возвращает общую длительность всех закрытых позиций.
int SumPositionsLengthMQL5( void )
{
   int  Res     = 0;
   bool HSelect = false;
  
   HSelect = HistorySelect(0, INT_MAX);
  
   if(HSelect)
   {
      CHashMap<ulong, ulong> DealsIn;  // По PositionID возвращает DealIn.
    
      int   TotalDeals   = 0;
      ulong TicketDeal   = 0;
      bool  condition1   = false;
      bool  condition2   = false; 
      bool  condition3   = false;       
      long  PositionID   = 0;
      ulong TicketDealIn = 0;
      int   DealTime     = 0;
    
      TotalDeals = HistoryDealsTotal();
    
      for(int i=0; i < TotalDeals; i++)
      {
         TicketDeal =  HistoryDealGetTicket(i);      
         condition1 = (HistoryDealGetInteger(TicketDeal, DEAL_ENTRY) == DEAL_ENTRY_IN);         
      
         if(condition1)
         {
            PositionID = HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID);
            DealsIn.Add(PositionID, TicketDeal);
            continue;                      
         }                  
         
         condition2 = (HistoryDealGetInteger(TicketDeal, DEAL_TYPE) <= DEAL_TYPE_SELL);
         
         if(condition2)
         {       
            PositionID = HistoryDealGetInteger(TicketDeal, DEAL_POSITION_ID);
            condition3 = DealsIn.TryGetValue(PositionID, TicketDealIn);
         
            if(condition3) 
            {
               DealTime = (int)(HistoryDealGetInteger(TicketDeal, DEAL_TIME) - HistoryDealGetInteger(TicketDealIn, DEAL_TIME));
               Res += DealTime; 
            }   
         }        
      }
   }
     
   return(Res);
}
 
Roman:

Une autre variante du code, afin de ne pas saccader inutilement l'histoire pour la deuxième condition.

        3132754100
        Time[Bench(SumPositionsLengthMQL5)] = 105779
        3132754100
        Time[Bench(SumPositionsLengthMQL5_Roman)] = 106270

A partir de là, c'est vous qui décidez.

 
Renat Fatkhullin:

Dans MT4, cela fonctionne de la même manière, la création du cache est simplement cachée. À chaque OnTick/OnStart de MT4, le terminal crée automatiquement et avec parcimonie un instantané de l'environnement du marché pour chaque EA.

Par conséquent, vous ne pouvez pas évaluer la véritable latence de la préparation des données à partir du code MQL4. Heureusement, dans MT4, les données sont petites et simples.

Au cas où vous vous poseriez la question.

positions fermées.

 
fxsaber:

Vous pouvez le prendre à partir d'ici.

Si vous le faites vous-même, vous le faites vous-même.
Mais pourquoi le résultat est si étrange, c'est une question pour Renate.
Ma suspicion est le contrôle hashmap DealsIn.TryGetValue
Regardez sous le profileur.

Raison: