MT5和速度在行动 - 页 19

 
Roman:

C语言程序员。

在这种情况下,这个例子非常简单。计算所有封闭位置的总寿命 是一个更难的任务,以实现快速性能。

 
fxsaber:

在这种情况下,这个例子非常简单。计算所有封闭位置的总寿命 是一个更难的任务,因为要快速表现。

我早些时候向你解释了原因,但你没有考虑到这一点。

 
Roman:

我早些时候向你解释了原因,但你没有考虑到这一点。

显然,我需要在论坛上搜索你的解释。

 
fxsaber:

显然,我需要在论坛上搜索你的解释。

上次你有一个类似的问题,传递的参数没有被缓存,而是直接传递到代码中。
而在你缓存了之后,速度就提高了。
这里也是一样:你声明了一个变量,内存已经被分配了,并且由于没有内存分配 成本,进一步使用该变量的工作会更快。

这也适用于从mql函数中获取数值。
即使是论坛上的开发人员也建议,首先从一个函数中获得一个值,并将其放入一个变量中,然后在if()条件中使用该变量。

 
fxsaber:

计算所有闭合位置的累积寿命 是一项更难的任务,因为要实现快速性能。

关于交易、自动交易系统和策略测试的论坛

图书馆: 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);
}

可能有一个更快的选择。但在需要计算的条件下向左走一步,逻辑就可能要发生很大的变化。不容易,一般来说。

 
fxsaber:

可能有一个更快的选择。但是,在需要计算的条件中,向左走一步,逻辑可能就要发生很大的变化。不容易,一般来说。

这不是条件问题,而是代码的编写问题。
虽然你可以用开关 代替条件,但它的工作速度会比其他地方快。
试试这段代码,到底会不会变快?如果不是,请试着用开关替换如果其他。
我希望你现在明白了一点,所有的变量声明 都应该放在循环之外,而不是重新执行100500次。
同时,为每个返回值,以变量的形式分配内存。

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

这是代码的另一个变体,这样我们就不必为第二个条件而扬弃历史。
你也可以考虑哪个条件会更频繁地得到满足,把它放在循环的第一位,然后继续迭代。

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

代码的另一个变体,以便不为第二个条件不必要地撸动历史。

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

从这里开始,就取决于你了。

 
Renat Fatkhullin:

在MT4中,它的工作方式是一样的,只是隐藏了缓存的创建。在MT4的每一个OnTick/OnStart,终端会自动为每个EA创建一个市场环境的快照。

因此,你无法从MQL4代码中评估数据准备的真正延迟。幸运的是,在MT4中,数据是小而简单的。

如果你想知道的话。

关闭头寸 数量相同的情况下,MT4x32比MT5x64快四倍以上。

 
fxsaber:

你可以从这里拿走它。

如果你自己做,你就自己做。
但奇怪的是,为什么结果会如此奇怪,这是给雷纳特的问题。
我的怀疑是Hashhmap检查DealsIn.TryGetValue
看下剖析器