MT5 e la velocità in azione - pagina 19

 
Roman:

Programmatori C.

L'esempio è molto semplice in questo caso. Calcolare ladurata totale di tutte le posizioni chiuse è un compito molto più difficile per le prestazioni veloci.

 
fxsaber:

Un esempio è molto semplice in questo caso. Calcolare ladurata totale di tutte le posizioni chiuse è un compito molto più difficile per una performance rapida.

Ti ho spiegato il motivo prima, ma non ne hai tenuto conto.

 
Roman:

Ti ho spiegato il motivo prima, ma non ne hai tenuto conto.

A quanto pare devo cercare nel forum la tua spiegazione.

 
fxsaber:

A quanto pare devo cercare nel forum la tua spiegazione.

L'ultima volta hai avuto un problema simile, in cui il parametro passato non veniva memorizzato nella cache, ma passato direttamente nel codice.
E dopo aver fatto la cache, la velocità è aumentata. Alloca sempre la memoria per una variabile e usala solo dopo.
È la stessa cosa qui, dichiari una variabile, la memoria è già allocata e l'ulteriore lavoro con la variabile sarà più veloce poiché non ci sono costi di allocazione della memoria.

Questo vale anche per il recupero di valori da funzioni mql.
Anche gli sviluppatori raccomandati qui sul forum, prima ottengono un valore da una funzione in una variabile e poi usano quella variabile in una condizione if()

 
fxsaber:

Calcolare ladurata cumulativa di tutte le posizioni chiuse è un compito molto più difficile per le prestazioni veloci.

Forum sul trading, sistemi di trading automatico e test di strategia

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

Potrebbe esserci un'opzione più veloce. Ma un passo a sinistra nella condizione di ciò che deve essere calcolato, e la logica potrebbe dover cambiare notevolmente. Non è facile, in generale.

 
fxsaber:

Potrebbe esserci un'opzione più veloce. Ma un passo a sinistra nella condizione di ciò che deve essere contato, e la logica potrebbe dover cambiare notevolmente. Non è facile, in generale.

Non è la condizione, è la scrittura del codice.
Anche se è possibile sostituire la condizione con l'interruttore, funzionerà più velocemente che se altro.
Prova questo codice, sarà più veloce o no? In caso contrario, provate a sostituire se altro con l'interruttore.
Spero che tu capisca il punto ora, che tutte le dichiarazioni di variabili dovrebbero essere messe fuori dal ciclo, e non rieseguirle 100500 volte.
Inoltre, per ogni valore restituito, alloca la memoria sotto forma di variabile.

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

Questa è un'altra variante del codice, in modo da non dover tirare la Storia per la seconda condizione.
Potete anche pensare quale condizione sarà soddisfatta più spesso, metterla per prima nel ciclo e continuare l'iterazione.

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

Un'altra variante del codice, per non far sobbalzare inutilmente la Storia per la seconda condizione.

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

Da qui in poi, dipende da voi.

 
Renat Fatkhullin:

In MT4 funziona allo stesso modo, solo che la creazione della cache è nascosta. Ad ogni OnTick/OnStart di MT4 il terminale crea automaticamente e con parsimonia un'istantanea dell'ambiente di mercato per ogni EA.

Pertanto, non è possibile valutare la vera latenza della preparazione dei dati dal codice MQL4. Fortunatamente, in MT4 i dati sono piccoli e semplici.

Nel caso ve lo stiate chiedendo.

posizioni chiuse.

 
fxsaber:

Potete prenderlo da qui.

Se lo fai da solo, lo fai da solo.
Ma è strano perché il risultato è così strano, questa è una domanda per Renate.
Il mio sospetto è il controllo hashmap DealsIn.TryGetValue
Guarda sotto il profiler.

Motivazione: