MT5 e velocidade em ação - página 19

 
Roman:

C programadores.

O exemplo é muito simples neste caso. O cálculo davida útil total de todas as posições fechadas é uma tarefa muito mais difícil para um desempenho rápido.

 
fxsaber:

Um exemplo é muito simples neste caso. O cálculo davida útil total de todas as posições fechadas é uma tarefa muito mais difícil para um desempenho rápido.

Expliquei-lhe o motivo antes, mas você não o levou em conta.

 
Roman:

Expliquei-lhe o motivo antes, mas você não o levou em conta.

Aparentemente, preciso pesquisar no fórum para obter sua explicação.

 
fxsaber:

Aparentemente, preciso pesquisar no fórum para obter sua explicação.

Da última vez você teve um problema semelhante, onde o parâmetro passado não estava em cache, mas passou diretamente para o código.
E, depois de armazená-la em cache, a velocidade aumentou. Sempre alocar memória para uma variável e só usá-la mais tarde.
É o mesmo aqui, você declara uma variável, a memória já está alocada e o trabalho adicional com a variável será mais rápido, uma vez que não há custos de alocação de memória.

Isto também se aplica a valores de busca de funções mql.
Mesmo os desenvolvedores recomendados aqui no fórum, primeiro obtêm um valor de uma função em uma variável e depois usam essa variável em uma condição if()

 
fxsaber:

O cálculo davida útil acumulada de todas as posições fechadas é uma tarefa muito mais difícil para um desempenho rápido.

Fórum sobre comércio, sistemas automatizados de comércio e testes estratégicos

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

Pode haver uma opção mais rápida. Mas um passo para a esquerda na condição do que precisa ser calculado, e a lógica pode ter que mudar consideravelmente. Não é fácil, em geral.

 
fxsaber:

Pode haver uma opção mais rápida. Mas um passo para a esquerda na condição do que precisa ser contado, e a lógica pode ter que mudar consideravelmente. Não é fácil, em geral.

Não é a condição, é a escrita do código.
Embora você possa substituir a condição por um interruptor, ele funcionará mais rápido do que se fosse outro.
Tente este código, ele vai ficar mais rápido ou não? Caso contrário, tente substituir por um interruptor.
Espero que vocês entendam agora que todas as declarações variáveis devem ser colocadas fora do loop, e não reexecutá-las 100500 vezes.
Além disso, para cada valor retornado, alocar memória na forma de uma variável.

#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 é outra variante do código, para que não tenhamos que puxar a História para a segunda condição.
Você também pode pensar qual condição será satisfeita com mais freqüência, colocá-la em primeiro lugar no loop e continuar a iteração.

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

Esta é outra variante do código, a fim de não puxar o Histórico para a segunda condição.

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

A partir daqui, é com você.

 
Renat Fatkhullin:

No MT4 funciona da mesma maneira, apenas a criação do cache está escondida. Em cada OnTick/OnStart do MT4 o terminal cria automaticamente e com moderação um instantâneo do ambiente de mercado para cada EA.

Portanto, não se pode avaliar a verdadeira latência da preparação dos dados a partir do código MQL4. Felizmente, no MT4, os dados são pequenos e simples.

Caso você esteja se perguntando.

posições fechadas.

 
fxsaber:

Você pode assumir a partir daqui.

Se você mesmo o faz, você mesmo o faz.
Mas é estranho por que o resultado é tão estranho, essa é uma pergunta para Renate.
Minha suspeita é a verificação do hashmap DealsIn.TryGetValue
Veja sob o perfilador.

Razão: