MT5와 속도 - 페이지 20

 
fxsaber :

아마도 더 빠른 옵션이 있습니다. 그러나 왼쪽으로 한 단계 더 나아가 계산해야 하는 조건과 논리가 크게 달라져야 할 수도 있습니다. 일반적으로 쉽지 않습니다.

CHashMap< ulong , ulong > DealsIn;   // По PositionID возвращает DealIn.


캐싱이 아니라 인덱스입니다. 다음은 캐싱(코드의 일부)입니다.

 class DealInfo {
public :
   datetime Closed;
   ulong Ticket;
   ulong Position;
   string Symbol ;
   long Type;
   long Reason;
   double Volume;
   double Price;
   double Profit;
   double Swap;
   long Magic;
};

class DealsComparer : public IComparer<DealInfo*> {
   int Compare(DealInfo* x, DealInfo* y) {
     int res = ( int )(x.Closed - y.Closed);
     if (res == 0 ) {
      res = ( int )(x.Ticket - y.Ticket);
    }
    
     return res;
  }
};

CArrayList<DealInfo*> dealsHistory;

inline bool UpdateDeals(CArrayList<DealInfo*> &deals, datetime &lastUpdated) {
  DealInfo* dealsToAdd[];
  DealsComparer comparer;
   int toAdd = 0 ;
  DealInfo* deal;
  
   if (! HistorySelect (lastUpdated, TimeLocal () + 12 * 3600 )) {
     return false ;
  }

   for ( int i = 0 , total = HistoryDealsTotal (); i < total; i++) {
    DealInfo tmp;
     ulong ticket = HistoryDealGetTicket (i);
     if (ticket == 0 ) continue ;
    
     datetime dt = ( datetime ) HistoryDealGetInteger (ticket, DEAL_TIME );
     if (lastUpdated < dt) {
      lastUpdated = dt;
    }

     if ( HistoryDealGetInteger (ticket, DEAL_ENTRY ) != DEAL_ENTRY_OUT ) continue ;

     ulong reason = HistoryDealGetInteger (ticket, DEAL_REASON );

    tmp.Ticket = ticket;
    tmp.Closed = dt;
     int idx = deals.BinarySearch(&tmp, &comparer);
     if (idx >= 0 && deals.TryGetValue(idx, deal) && deal != nullptr && deal.Ticket == ticket)
       continue ;

    deal = new DealInfo;
    deal.Ticket = ticket;
    deal.Closed = dt;
    deal.Position = HistoryDealGetInteger (ticket, DEAL_POSITION_ID );
    deal. Symbol = HistoryDealGetString (ticket, DEAL_SYMBOL );
    deal.Type = HistoryDealGetInteger (ticket, DEAL_TYPE );
    deal.Reason = HistoryDealGetInteger (ticket, DEAL_REASON );
    deal.Volume = HistoryDealGetDouble (ticket, DEAL_VOLUME );
    deal.Price = HistoryDealGetDouble (ticket, DEAL_PRICE );
    deal.Swap = HistoryDealGetDouble (ticket, DEAL_SWAP );
    deal.Profit = HistoryDealGetDouble (ticket, DEAL_PROFIT );
    deal.Magic = HistoryDealGetInteger (ticket, DEAL_MAGIC );
    
     ArrayResize (dealsToAdd, toAdd + 1 , total);
    dealsToAdd[toAdd++] = deal;
  }
  
   if (toAdd > 0 ) {
    deals.AddRange(dealsToAdd);
    deals.Sort(&comparer);
  }
  
   return (toAdd > 0 );
}

코드는 급하게 작성되었으며 빈번한 ArrayResize 를 감안할 때 개선해야 할 점이 있지만 Closed 로 정렬된 캐시만 업데이트합니다. 나중에 검색하려면 색인을 사용하십시오. 그러나 매번 작은 부분만 업데이트하면 됩니다.
" 12 * 3600 "이 왜 거기에 있는지 기억이 나지 않습니다. 모든 거래가 저에게 주어진 것은 아닌 것 같습니다.

 
Andrey Pogoreltsev :

캐싱이 아니라 인덱스입니다.

주의 깊게 읽으십시오.

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

MT5와 속도

fxsaber , 2020.08.28 21:10

순수 MQL5는 부분(HistorySelectByPosition 전용) 캐싱 보다 100배 느립니다.

구조적 으로 전체 캐싱을 수행하려면 잘 생각해야 합니다. 많은 함정이 있습니다.

다음은 캐싱(코드의 일부)입니다.

코드가 급하게 작성되었고 ArrayResize가 자주 발생하므로 개선해야 할 점이 있지만 Closed로 정렬된 캐시만 업데이트합니다. 나중에 검색하려면 색인을 사용하십시오. 그러나 매번 작은 부분만 업데이트하면 됩니다.

이것은 진짜 농담 없이 역사를 정면으로 보존한 예일 뿐입니다. MT4Orders에서도 5초의 여유를 두고 부분 캐싱을 합니다...

" 12 * 3600 "이 왜 거기에 있는지 기억이 나지 않습니다. 모든 거래가 저에게 주어진 것은 아닌 것 같습니다.

항상 INT_MAX를 설정하십시오.

 
fxsaber :

구조적 으로 전체 캐싱을 수행하려면 잘 생각해야 합니다. 많은 함정이 있습니다.

사실 거기에는 복잡한 것이 없습니다. 예를 들어, 기록에 소급적으로 나타날 수 있는 모든 주문에 대해 시간을 예약하여 선택할 수 있습니다(그런데 매우 이상합니다).

이것은 진짜 농담 없이 역사를 정면으로 보존한 예일 뿐입니다. MT4Orders에서도 5초의 여유를 두고 부분 캐싱을 합니다...

항상 INT_MAX를 설정하십시오.

나는 전환의 요점을 이해하지 못한다. 마치 현재 타임스탬프가 있는 것처럼 그것에 상대적으로 가져오고 싶은데, 존재하지 않는 시간을 지정해야 하는 것이 이상합니다. 논리적인 설명을 원합니다.

그건 그렇고, 내 현금은 10,000건 이상의 거래가 있는 실제 계정에서 작동합니다.

그리고 지금까지 코드의 주요 브레이크는 네트워크 기능입니다.

 
우연히 지나가다 여기에서 이미 암시된 내용을 요약하기로 했습니다. 어떤 비용으로든 초고속 성능이 필요한 경우 메모리와 같은 다른 리소스를 사용하여 전통적으로 달성됩니다. 즉, 집계된 값(전체 기간뿐만 아니라)을 계산해야 할 때마다 전체 기록을 통해 루프를 실행할 필요가 없지만 "배열"(또는 기타 최적화된 데이터 구조 )에서 모든 것을 미리 계산해야 합니다. ) 그런 다음 추가하십시오. 그리고 위치 식별자(또는 분류가 이루어진 다른 매개변수)에 의한 값에 대한 요청은 메모리 셀 액세스로 변질됩니다. 가장 일반적인 형태로 이것은 OLAP와 비슷하지만(내 구현에서는 온라인 업데이트를 완료하지 않았지만) 특정 작업의 경우 더 간단한 방법으로 수행할 수 있습니다.
 

최신 베타 2588에서 HistorySelect 함수는 매우 잘 캐시 되며 거의 항상(처음을 제외하고) 무료입니다.

아마도 출시 전에 여러 가지 개선 사항을 만들 것입니다.



앞서 설명했듯이 MT5에서는 MT4에서와 같이 각 이벤트 전에 각 전문가에 대한 시장 스냅샷을 자동으로 생성하는 데 추가 비용이 들지 않습니다. 이를 통해 지연이 줄어들고 로봇이 더 빠르게 작업할 수 있습니다. 각 개발자는 자신에게 필요한 것을 정확히 요청합니다.

따라서 "전체 기록에 대해 HistorySelect를 호출한 다음 즉시 HistorySelectByPosition을 선택하는" 접근 방식이 이전에 생성된 기록 캐시를 종료한다는 점을 명확하게 이해해야 합니다. 발에 맞은 샷입니다.


출시 후에는 알고리즘 거래를 간소화하고 가속화할 수 있도록 보다 효율적인 새로운 MQL5 기능을 추가하고 기본 주문/거래 데이터 구조를 공개하기 위한 많은 작업을 시작할 것입니다.

 
Renat Fatkhullin :

최신 베타 2588에서 HistorySelect 함수는 매우 잘 캐시 되며 거의 항상(처음을 제외하고) 무료입니다.

 #include <fxsaber\Benchmark.mqh> // https://c.mql5.com/3/321/Benchmark.mqh

input int inAlertTime = 1 ; // Нижний порог в миллисекундах

#define _B2(A) _B(A, inAlertTime)
#define ALERT(A) Alert ( #A + " = " + ( string )(A))

void OnInit ()
{
   if ( HistorySelect ( 0 , INT_MAX ))
  {
    ALERT( HistoryDealsTotal ());
    ALERT( HistoryOrdersTotal ());
  }
}

void OnTick ()
{
   static int i = 0 ;
  
  ALERT(i++);
  
  _B2( HistorySelect ( TimeCurrent (), INT_MAX ));
  _B2( HistorySelect ( 0 , INT_MAX ));
}


결과.

 2020.09 . 01 22 : 56 : 46.089 Test6 (EURAUD,M1)       Alert : HistoryDealsTotal () = 9435
2020.09 . 01 22 : 56 : 46.089 Test6 (EURAUD,M1)       Alert : HistoryOrdersTotal () = 12529
2020.09 . 01 22 : 56 : 46.575 Test6 (EURAUD,M1)       Alert : i++ = 0
2020.09 . 01 22 : 56 : 46.579 Test6 (EURAUD,M1)       Alert : Time[Test6.mq5 25 : HistorySelect ( 0 , INT_MAX )] = 3 ms.
2020.09 . 01 22 : 56 : 47.424 Test6 (EURAUD,M1)       Alert : i++ = 1
2020.09 . 01 22 : 56 : 47.428 Test6 (EURAUD,M1)       Alert : Time[Test6.mq5 25 : HistorySelect ( 0 , INT_MAX )] = 3 ms.
2020.09 . 01 22 : 56 : 47.765 Test6 (EURAUD,M1)       Alert : i++ = 2
2020.09 . 01 22 : 56 : 47.768 Test6 (EURAUD,M1)       Alert : Time[Test6.mq5 25 : HistorySelect ( 0 , INT_MAX )] = 3 ms.
2020.09 . 01 22 : 56 : 47.902 Test6 (EURAUD,M1)       Alert : i++ = 3
2020.09 . 01 22 : 56 : 47.906 Test6 (EURAUD,M1)       Alert : Time[Test6.mq5 25 : HistorySelect ( 0 , INT_MAX )] = 3 ms.
2020.09 . 01 22 : 56 : 48.453 Test6 (EURAUD,M1)       Alert : i++ = 4
2020.09 . 01 22 : 56 : 48.456 Test6 (EURAUD,M1)       Alert : Time[Test6.mq5 25 : HistorySelect ( 0 , INT_MAX )] = 3 ms.
2020.09 . 01 22 : 56 : 48.516 Test6 (EURAUD,M1)       Alert : i++ = 5
2020.09 . 01 22 : 56 : 48.521 Test6 (EURAUD,M1)       Alert : Time[Test6.mq5 25 : HistorySelect ( 0 , INT_MAX )] = 4 ms.


모든 틱에는 문제가 있습니다.


ZY 설치된 Win10, LatencyMon은 모든 것이 정상임을 보여줍니다.

 
현재 99%의 경우 HistorySelect(0, INT_MAX )만 사용해야 한다는 것을 알았습니다. 다른 옵션을 사용하지 마십시오.
 
Renat Fatkhullin :

출시 후에는 알고리즘 거래를 간소화 하고 가속화할 수 있도록 보다 효율적인 새로운 MQL5 기능을 추가하고 기본 주문/거래 데이터 구조를 공개하기 위한 많은 작업을 시작할 것입니다.

MqlDeal, MqlOrder 및 MqlPosition이 좋습니다. 더 쉬워질 수도 있습니다.

 
fxsaber :
현재 99%의 경우 HistorySelect(0, INT_MAX )만 사용해야 한다는 것을 알았습니다. 다른 옵션을 사용하지 마십시오.

히스토리에 수십만 개의 주문이 있는 경우 마지막 몇 분 동안 히스토리를 가져오는 것보다 빠를까요?

글쎄, 그럼 내가 전체 이야기를 읽어야합니까 아니면 무엇을해야합니까? 말도 안되는 소리입니다.

 
Dmi3 :

히스토리에 수십만 개의 주문이 있는 경우 마지막 몇 분 동안 히스토리를 가져오는 것보다 빠를까요?

전투 로봇에서는 0 -INT_MAX 옵션만 남겼습니다. 브레이크가 눈치채지 못하게 멈췄습니다.

사유: