MT5 y la velocidad en acción - página 19

 
Roman:

Programadores de C.

El ejemplo es muy sencillo en este caso. Calcular laduración total de todas las posiciones cerradas es una tarea mucho más difícil para un rendimiento rápido.

 
fxsaber:

Un ejemplo es muy sencillo en este caso. Calcular laduración total de todas las posiciones cerradas es una tarea mucho más difícil para un rendimiento rápido.

Ya te expliqué la razón antes, pero no la tuviste en cuenta.

 
Roman:

Ya te expliqué la razón antes, pero no la tuviste en cuenta.

Parece que tengo que buscar en el foro su explicación.

 
fxsaber:

Parece que tengo que buscar en el foro su explicación.

La última vez tuvo un problema similar, en el que el parámetro pasado no se almacenaba en la caché, sino que se pasaba directamente al código.
Y después de que la caché, la velocidad aumentó. Siempre hay que asignar memoria para una variable y sólo usarla después.
Es lo mismo: declaras una variable, la memoria ya está asignada y el trabajo posterior con la variable será más rápido ya que no hay costes de asignación de memoria.

Esto también se aplica a la obtención de valores de las funciones mql.
Incluso los desarrolladores aquí en el foro recomendaron obtener primero un valor de una función en una variable y luego usar esa variable en una condición if()

 
fxsaber:

Calcular laduración acumulada de todas las posiciones cerradas es una tarea mucho más difícil para un rendimiento rápido.

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

Bibliotecas: 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);
}

Puede haber una opción más rápida. Pero si se da un paso a la izquierda en la condición de lo que hay que calcular, la lógica puede tener que cambiar considerablemente. No es fácil, en general.

 
fxsaber:

Puede haber una opción más rápida. Pero un paso a la izquierda en la condición de lo que hay que contar, y la lógica puede tener que cambiar considerablemente. No es fácil, en general.

No es la condición, es la escritura del código.
Aunque se puede reemplazar la condición con el interruptor, funcionará más rápido que si no.
Pruebe este código, ¿se acelerará o no? Si no es así, pruebe a sustituir si no con el interruptor.
Espero que ahora entiendas el punto, que todas las declaraciones de variables deben ser puestas fuera del bucle, y no reejecutarlas 100500 veces.
Además, para cada valor devuelto, asigna memoria en forma 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);
}
 

Esta es otra variante del código, para que no tengamos que tirar de Historia para la segunda condición.
También puede pensar qué condición se cumplirá más a menudo, ponerla primero en el bucle y continuar la iteración.

#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:

Otra variante del código, para no sacudir la Historia innecesariamente para la segunda condición.

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

A partir de aquí, depende de ti.

 
Renat Fatkhullin:

En MT4 funciona igual, sólo que la creación de la caché está oculta. En cada OnTick/OnStart de MT4 el terminal crea automáticamente y con moderación una instantánea del entorno del mercado para cada Asesor Experto.

Por lo tanto, no se puede evaluar la verdadera latencia de la preparación de datos a partir del código MQL4. Afortunadamente, en MT4 los datos son pequeños y sencillos.

En caso de que te lo preguntes.

posiciones cerradas.

 
fxsaber:

Puedes tomarlo desde aquí.

Si lo haces tú, lo haces tú.
Pero el por qué del resultado es tan extraño, es una pregunta para Renate.
Mi sospecha es que la comprobación del hashmap DealsIn.TryGetValue
Mira bajo el perfilador.