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

これも変形版で、2つ目の条件のためにHistoryをヤケクソにする必要がないようにしたものです。
また、どの条件がより多く満たされるかを考え、それを最初にループに入れ、反復を続けることもできる。

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

これは、2つ目の条件でHistoryを引かないようにするための、別の変形コードです。

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

ここからは、あなた次第です。

 
Renat Fatkhullin:

MT4では、キャッシュの作成が非表示になるだけで、同じように動作します。MT4のOnTick/OnStartごとに、ターミナルは各EAのために市場環境のスナップショットを自動的かつ惜しみなく作成します。

そのため、MQL4コードからデータ準備の真のレイテンシーを評価することはできません。幸いなことに、MT4ではデータは小さくシンプルです。

一応、言っておきますが。

クローズドポジション 数で、MT5x64の4倍以上の速度があります。

 
fxsaber:

ここから先は、あなたが受け持つことになります。

自分でやるなら、自分でやる。
でも、なぜそのような結果になるのか不思議で、それはレナーテへの質問です。
私の疑惑は、ハッシュマップチェック DealsIn.TryGetValue
プロファイラの 下で見てください。