Genel sınıflar kütüphanesi - hatalar, açıklamalar, sorular, kullanım özellikleri ve öneriler - sayfa 12

 
Sergey Dzyublik :

T türü için GetHashCode işlevinin açık bir uygulaması yoksa kodun ne yaptığını anlıyor musunuz?
Cevap: Kirli bir numara, çünkü uygulama eksikliği sorunu örtbas ediliyor. Aynı sınıfın tüm nesneleri aynı karma değerini döndürür.

Ve uygulama (vücut) nerede?! İşte eklendi

 int GetHashCode(T & value)

vücut buldozerden sokuldu.

 
fxsaber :

Ve uygulama (vücut) nerede?! İşte eklendi

vücut buldozerden sokuldu.


Size sineklerden bahsediyorlar (bunu yapmamalısınız, kod ileride hastalanabilir) ve siz pirzolalardan bahsedersiniz.
Tamam, iyi iştah.

 

Önerilen çözümün hız özelliklerine bakmaya karar verdim. Test uzmanı danışmanı

 #include <MT4Orders.mqh>
#include <Generic\HashMap.mqh>

CHashMap< ulong , double > DealsProfit;

// Создаем историю из Amount сделок в тестере
void CreateHistory( const int Amount, const double Lots = 0.1 )
{
   MqlTick Tick;
  
   if ( SymbolInfoTick ( _Symbol , Tick) && Tick.ask && Tick.bid)
     for ( int i = (Amount >> 1 ) - 1 ; i >= 0 ; i--)
       OrderClose ( OrderSend ( _Symbol , OP_BUY , Lots, Tick.ask, 0 , 0 , 0 ), Lots, Tick.bid, 0 );
}

// Заполняем массив случайно выбранными сделками
void GetDeals( const int Amount, const int MaxDealTicket, ulong &Deals[] )
{
   for ( int i = ArrayResize (Deals, Amount) - 1 ; i >= 0 ; i--)  
    Deals[i] = MathRand () * MaxDealTicket / SHORT_MAX ;
}

// Заполнили HashMap
void SetHashMap()
{
   if ( HistorySelect ( 0 , INT_MAX ))
     for ( int i = HistoryDealsTotal () - 1 ; i >= 0 ; i--)
    {
       const ulong DealTicket = HistoryDealGetTicket (i);
      
      DealsProfit.Add(DealTicket, HistoryDealGetDouble (DealTicket, DEAL_PROFIT ));
    }
}

double GetDealProfitHashClear( const ulong Deal )
{
   static double Profit = 0 ;
  
   return (DealsProfit.TryGetValue(Deal, Profit) ? Profit : 0 );
}

double GetDealProfitFull( const ulong Deal )
{
   return ( HistoryDealSelect (Deal) ? HistoryDealGetDouble (Deal, DEAL_PROFIT ) : 0 );
}

double GetDealProfitClear( const ulong Deal )
{
   return ( HistoryDealGetDouble (Deal, DEAL_PROFIT ));
}

typedef double (*GetDealProfit)( const ulong );

// Находим суммарный профит сделок из массива
double SumProfit( const ulong &Deals[], GetDealProfit DealProfit )
{
   double Profit = 0 ;
  
   for ( int i = ArraySize (Deals) - 1 ; i >= 0 ; i--)
    Profit += DealProfit(Deals[i]);
    
   return (Profit);
}

#define BENCH(A)                                                              \
{                                                                             \
   const ulong StartTime = GetMicrosecondCount ();                              \
  A;                                                                          \
   Print ( "Time[" + #A + "] = " + ( string )( GetMicrosecondCount () - StartTime)); \
} 

int OnInit ()
{
   const int Amount = 100000 ;  
  CreateHistory(Amount); // Создаем историю из Amount сделок в тестере
  
   ulong Deals[];
  GetDeals(Amount, Amount, Deals); // Заполняем массив случайно выбранными сделками

   // Находим суммарный профит сделок из массива
  
  BENCH( Print (SumProfit(Deals, GetDealProfitFull))); // Полноценная классическая реализация
  
  BENCH(SetHashMap()); // Заполнили HashMap
  BENCH( Print (SumProfit(Deals, GetDealProfitHashClear))); // Реализация через HashMap
  
  BENCH( HistorySelect ( 0 , INT_MAX ));
  BENCH( Print (SumProfit(Deals, GetDealProfitClear))); // Реализация с предварительно загруженной историей
  
   return ( INIT_FAILED );
}

EA 100.000 işlem açar, ardından farklı yöntemler kullanarak rastgele işlemlerin toplam kârını arar (yorumlara bakın). Sonuç

 2017.12 . 05 00 : 00 : 00    - 13133.19999999244
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitFull))] = 38082
2017.12 . 05 00 : 00 : 00    Time [SetHashMap()] = 57849
2017.12 . 05 00 : 00 : 00    - 13133.19999999244
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitHashClear))] = 7437
2017.12 . 05 00 : 00 : 00    Time [ HistorySelect ( 0 , INT_MAX )] = 1
2017.12 . 05 00 : 00 : 00    - 13133.19999999244
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitClear))] = 31669

Peki, seçilen iki göstergeyi karşılaştıralım. HashMap erişiminin geliştiricilerin sahip olduğundan 4 kat daha hızlı olduğu ortaya çıktı. Ancak geliştiriciler için zaten tarih içeriyor ...

4 kez - bu durum için çok mu yoksa az mı? İşte burada 24 milisaniye. Tarihe birçok kez dönerseniz, muhtemelen çok tasarruf edebilirsiniz. Ama emin değilim.


Daha gerçekçi bir test durumu için (2000 işlem ve 1.000.000 tek geçmiş erişimi), sonuç şöyle görünür

 2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitFull))] = 122969
2017.12 . 05 00 : 00 : 00    Time [SetHashMap()] = 816
2017.12 . 05 00 : 00 : 00    4829800340.792288
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitHashClear))] = 23852
2017.12 . 05 00 : 00 : 00    Time [ HistorySelect ( 0 , INT_MAX )] = 1
2017.12 . 05 00 : 00 : 00    4829800340.792288
2017.12 . 05 00 : 00 : 00    Time [ Print (SumProfit(Deals,GetDealProfitClear))] = 114427

Geçiş başına yaklaşık 100 ms tasarruf! Örneğin, 10.000 tam geçiş için Optimizasyon yaparsak, Hash sürümü 15 dakika daha hızlı biter.

Geliştiricilerin Tarih ile çalışmanın uygulanması için sağlam bir beş vermeleri için henüz çok erken. MQL çözümü bile bunu yapabildiğinden, hızlanabilecekleri görülebilir.

 
fxsaber :

Önerilen çözümün hız özelliklerine bakmaya karar verdim. Test uzmanı danışmanı

EA 100.000 işlem açar, ardından farklı yöntemler kullanarak rastgele işlemlerin toplam kârını arar (yorumlara bakın). Sonuç

Peki, seçilen iki göstergeyi karşılaştıralım. HashMap erişiminin geliştiricilerin sahip olduğundan 4 kat daha hızlı olduğu ortaya çıktı. Ancak geliştiriciler için zaten tarih içeriyor ...

4 kez - bu durum için çok mu yoksa az mı? İşte burada 24 milisaniye. Tarihe birçok kez dönerseniz, muhtemelen çok tasarruf edebilirsiniz. Ama emin değilim.

Platform üzerinden yapılan çağrılarda, GetDealProfitFull'da iki kez ve GetDealProfitClear'da bir kez senkronizasyon nesneleri ve her yinelemede çok sayıda zorunlu kontrol üzerinden geçersiniz.

Bu nedenle, hız, önceden hazırlanmış bir yerel hashmap üzerinde bir dizi satır içi çalışma ile temiz ve optimize edilmiş bir hızdan açıkça daha düşüktür.

 
Renat Fatkhullin'in fotoğrafı.

Platform üzerinden yapılan çağrılarda, GetDealProfitFull'da iki kez ve GetDealProfitClear'da bir kez senkronizasyon nesneleri ve her yinelemede çok sayıda zorunlu kontrol üzerinden geçersiniz.

Bu nedenle, hız, önceden hazırlanmış bir yerel hashmap üzerinde bir dizi satır içi çalışma ile temiz ve optimize edilmiş bir hızdan açıkça daha düşüktür.

Önceki mesajımı düzelttim. Bu yüzden çift kontrole Tam denir.

Tester for HistoryDealGetDouble'da ne tür pahalı senkronizasyon nesnelerinden ve birçok kontrolden bahsettiğimizi tam olarak anlamıyorum?
 
fxsaber :

Önceki mesajımı düzelttim. Bu yüzden çift kontrole Tam denir.

Tester for HistoryDealGetDouble'da ne tür pahalı senkronizasyon nesnelerinden ve birçok kontrolden bahsettiğimizi tam olarak anlamıyorum?

Fark ne:

  1. hashmap testi için önce hızlı senkronize olmayan erişimle verileri yerel depoya aktardınız ve platform çağrılarında depoya düşmeniz gerekiyor
  2. platformda, hashmap değil, farklı türden bir depolama
  3. platformda, tek bir değer çıkarırken, tüm verilerin doğruluğunu ve kullanılabilirliğini iki kez kontrol ederek, isteği "ilk seferki gibi" ele almanız gerekir. aramalar arasında çok az şey değişti


Kodumuza baktım - alım satım işlemleri veritabanına yapılan çağrıları optimize etmek mümkün. Önümüzdeki hafta piyasaya sürülmek üzere uygulamaya çalışacağız.

 

Renat Fatkhullin'in fotoğrafı.

platformda, tek bir değer çıkarırken, tüm verilerin doğruluğunu ve kullanılabilirliğini yeniden kontrol ederek, isteği "ilk kez olduğu gibi" ele almanız gerekir.

TryGetValue çağrılırken doğrulama denetimi yapılmadı mı? Günlükler, HistorySelect'in test cihazında ücretsiz olduğunu gösteriyor.

Anlamadığım şey, neden bir anlaşmayla ilgili tüm verileri elde etmek için bir sürü pahalı HistoryDealGet * işlevini çağırmanız gerektiği? Sonuçta MqlDeal yapısını dolduran tek bir çağrı var.

Kullanıcının HashMap aracılığıyla geçmişle çalışmak istediğinde CHashMap<ulong, MqlDeal>'i dolduracağı açıktır.

Tüm tarihsel tablo zaten test cihazında olduğundan, pahalı birim çağrıları üretmemek için MqlDealInteger, MqlDealDouble, MqlDealString veya benzeri bir şey yapabilir misiniz? Ve sonra DealTicket'in doğruluğunu her seferinde değil, bir kez kontrol etmek yeterlidir.

 
fxsaber :

TryGetValue çağrılırken doğrulama denetimi yapılmadı mı? Günlükler, HistorySelect'in test cihazında ücretsiz olduğunu gösteriyor.

Nasıl ücretsiz? Hiç ücretsiz değil.


Anlamadığım şey, neden bir anlaşmayla ilgili tüm verileri elde etmek için bir sürü pahalı HistoryDealGet * işlevini çağırmanız gerektiği? Sonuçta MqlDeal yapısını dolduran tek bir çağrı var.

Kullanıcının HashMap aracılığıyla geçmişle çalışmak istediğinde CHashMap<ulong, MqlDeal>'i dolduracağı açıktır.

Bir MqlDeal yapımız yok, çünkü ticari kayıt biçimleri dalgalanıyor ve periyodik olarak genişliyor. Bu olmadan, platformun işlevselliğini genişletmek imkansızdır.

Bu nedenle, tek seçenek bunlara Get işlevi aracılığıyla erişmektir. Ayrıca, daha önce etkilenen kaydın kalan alanlarına erişim, kayıt önbelleğe girdiğinden, ilk erişimden birçok kat daha hızlıdır.

Ve sonra DealTicket'in doğruluğunu her seferinde değil, bir kez kontrol etmek yeterlidir.

Yukarıdaki testte, anlaşma numaraları her seferinde yenidir ve bu, önceden seçilen anlaşmanın önbelleğini sürekli olarak düşürür. Ayrıca aramalar arasında bir şeylerin değişmediğinin garantisi de yoktur. Sonuçta yine de geçmişe yönelik istekler arasında ticaret yapabilirsiniz.

 
Renat Fatkhullin'in fotoğrafı.
Nasıl ücretsiz? Hiç ücretsiz değil.

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Genel sınıf kitaplığı - hatalar, açıklama, sorular, kullanım ve öneriler

fxsaber , 2017.12.08 22:46

EA 100.000 işlem açar, ardından farklı yöntemler kullanarak rastgele işlemlerin toplam kârını arar (yorumlara bakın). Sonuç

 2017.12 . 05 00 : 00 : 00    Time [ HistorySelect ( 0 , INT_MAX )] = 1

100.000 işlem (ve aynı sayıda emir) için 1 mikrosaniye ücretsizdir. Her şey test cihazıyla ilgili.

Yukarıdaki testte, anlaşma numaraları her seferinde yenidir ve bu, önceden seçilen anlaşmanın önbelleğini sürekli olarak düşürür. Ayrıca aramalar arasında bir şeylerin değişmediğinin garantisi de yoktur. Sonuçta, geçmişe yönelik istekler arasında hala ticaret yapabilirsiniz.

Böylece tarih (özellikle test cihazında) sadece tamamlanır, eski kayıtlar değişmez. Temizle seçeneğiyle ilgili.


Gerçek hayatta, bir emir kısmen yürütüldüğünde ve birkaç işlem oluşturduğunda bile, tamamen dolana veya iptal edilene kadar geçmişe girmeyecek gibi görünüyor. Onlar. donmuş tarih kuralı korunur.

 
fxsaber :

100.000 işlem (ve aynı sayıda emir) için 1 mikrosaniye ücretsizdir. Her şey test cihazıyla ilgili.

Test cihazındaki HistorySelect, özellikle 0, INT_MAX parametreleriyle kesinlikle sanal/sahtedir. Bu, uzun süredir optimize edilmiştir.

Gerçekte belirli bir bileti arayan ve önbelleğe alan HistorySelect (test cihazında erişim aralığını ayarlar) ve HistoryDealSelect(bilet) arasında karşılaştırma yapamazsınız.

Neden: