Standart özelliklerin/yaklaşımların alternatif uygulamaları

 

NormalizeÇift

 #define EPSILON ( 1.0 e- 7 + 1.0 e- 13 )
#define HALF_PLUS  ( 0.5 + EPSILON)

double MyNormalizeDouble( const double Value, const int digits )
{
   // Добавление static ускоряет код в три раза (Optimize=0)!
   static const double Points[] = { 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };

   return (( int )((Value > 0 ) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);
}

ulong Bench( const int Amount = 1.0 e8 )
{
   double Price = 1.23456 ;
   const double point = 0.00001 ;
  
   const ulong StartTime = GetMicrosecondCount ();
  
   int Tmp = 0 ;
  
   for ( int i = 0 ; i < Amount; i++)
  {
    Price = NormalizeDouble (Price + point, 5 ); // замените на MyNormalizeDouble и почувствуйте разницу
    
     // Если убрать, то общее время выполнения будет нулевым при любом Amount (Optimize=1) - круто! В варианте NormalizeDouble оптимизации такой не будет.  
     if (i + i > Amount + Amount)
       return ( 0 );
  }
  
   return ( GetMicrosecondCount () - StartTime);
}

void OnStart ( void )
{
   Print (Bench());
    
   return ;
};

Sonuç, MyNormalizeDouble lehine 1123275 ve 1666643'tür (Optimize=1). Optimizasyon olmadan - dört kat daha hızlı (bellek için).


 

eğer değiştirin

 static const double Points[] = { 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };

anahtar varyantında, anahtar uygulamasının kalitesini sayılarla görebileceksiniz.

 

NormalizeDouble ile betiğin temizlenmiş bir sürümünü düşünün:

 #define EPSILON ( 1.0 e- 7 + 1.0 e- 13 )
#define HALF_PLUS  ( 0.5 + EPSILON)
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double MyNormalizeDouble( const double Value, const int digits)
  {
   static const double Points[]={ 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };

   return (( int )((Value > 0 ) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ulong BenchStandard( const int Amount= 1.0 e8)
  {
   double        Price= 1.23456 ;
   const double point= 0.00001 ;
   const ulong   StartTime= GetMicrosecondCount ();
//---
   for ( int i= 0 ; i<Amount;i++)
     {
      Price= NormalizeDouble (Price+point, 5 );
     }
   
   Print ( "Result: " ,Price);   // специально выводим результат, чтобы цикл не оптимизировался в ноль
//---
   return ( GetMicrosecondCount () - StartTime);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ulong BenchCustom( const int Amount= 1.0 e8)
  {
   double        Price= 1.23456 ;
   const double point= 0.00001 ;
   const ulong   StartTime= GetMicrosecondCount ();
//---
   for ( int i= 0 ; i<Amount;i++)
     {
      Price=MyNormalizeDouble(Price+point, 5 );
     }
   
   Print ( "Result: " ,Price);   // специально выводим результат, чтобы цикл не оптимизировался в ноль
//---
   return ( GetMicrosecondCount () - StartTime);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart ( void )
  {
   Print ( "Standard: " ,BenchStandard(), " msc" );
   Print ( "Custom:   " ,BenchCustom(),   " msc" );
  }

Sonuçlar:

Custom:   1110255 msc
Result:   1001.23456

Standard: 1684165 msc
Result:   1001.23456

Hemen yorumlar ve açıklamalar:

  1. static burada gereklidir, böylece derleyici bu diziyi işlevden çıkarır ve işlev her çağrıldığında yığın üzerinde oluşturmaz . C++ derleyicisi de aynı şeyi yapar.
     static const double Points
  2. Derleyicinin işe yaramaz olduğu için döngüyü dışarı atmaması için hesaplamaların sonuçlarını kullanmanız gerekir. Örneğin, Print değişkenini Fiyat yapın.

  3. İşlevinizde bir hata var - rakamların sınırları kontrol edilmiyor, bu da kolayca bir dizinin sınırların dışına çıkmasına neden olabilir.

    Örneğin, MyNormalizeDouble(Price+point, 10 ) gibi bir çağrı yapın ve hatayı yakalayın:
    array out of range in 'BenchNormalizeDouble.mq5' (19,45)
    
    Kontrolleri atlayarak hızlandırma yöntemi kabul edilebilir, ancak bizim durumumuzda değil. Herhangi bir hatalı veri girişini işlemekle yükümlüyüz.

  4. 8'den büyük bir dizin için basit bir koşul ekleyelim ve kodu basitleştirmek için <0 ek koşulu yerine >8 için bir karşılaştırma yapmak için digit değişkeninin türünü uint ile değiştireceğiz.
     //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    double MyNormalizeDouble( const double Value, uint digits)
      {
       static const double Points[]={ 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };
    //---
       if (digits> 8 )
          digits= 8 ;
    //---
       return (( int )((Value > 0 ) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);
      }
    

  5. Kodu çalıştırıyoruz ve ... şaşırıyoruz!
    Custom:   1099705 msc
    Result:   1001.23456
    
    Standard: 1695662 msc
    Result:   1001.23456
    
    Kodunuz, standart NormalizeDouble işlevinden daha da önde!

    Ayrıca, koşulun eklenmesi süreyi bile azalttı (aslında buradaki azalma hata payı içinde). Neden bu kadar hız farkı var?

  6. Her şey performans testçilerinin standart hatasıyla ilgili.

    Testler yazarken, derleyici tarafından uygulanabilecek optimizasyonların tam listesini aklınızda bulundurmanız gerekir. Basitleştirilmiş bir örnek test yazarken hangi girdileri kullandığınız ve bunların nasıl yok edileceği konusunda çok net olmanız gerekir.

    Derleyicimizin yaptığı tüm optimizasyonları adım adım değerlendirip uygulayalım.

  7. Sürekli yayılma ile başlayalım - bu, bu testte yaptığınız önemli hatalardan biridir.

    Girilen verilerin yarısı sabittir. Dağılımlarını dikkate alarak örneği yeniden yazalım.

     ulong BenchStandard( void )
      {
       double       Price= 1.23456 ;
       const ulong StartTime= GetMicrosecondCount ();
    //---
       for ( int i= 0 ; i< 1.0 e8;i++)
         {
          Price= NormalizeDouble (Price + 0.00001 , 5 );
         }
    
       Print ( "Result: " ,Price);
    //---
       return ( GetMicrosecondCount () - StartTime);
      }
    
    ulong BenchCustom( void )
      {
       double       Price= 1.23456 ;
       const ulong StartTime= GetMicrosecondCount ();
    //---
       for ( int i= 0 ; i< 1.0 e8;i++)
         {
          Price=MyNormalizeDouble(Price + 0.00001 , 5 );
         }
    
       Print ( "Result: " ,Price, " " , 1.0 e8);
    //---
       return ( GetMicrosecondCount () - StartTime);
      }
    
    Lansmandan sonra hiçbir şey değişmedi - olması gerektiği gibi.

  8. Devam edin - kodunuzu satır içine alın (NormalizeDouble'ımız satır içine alınamaz)

    Kaçınılmaz satır içi işleminden sonra işlevinizin gerçekte dönüştüğü şey budur. Çağrılardaki tasarruflar, dizi çıkarımlarındaki tasarruflar, sabitler ayrıştırılarak kontroller kaldırılır:
     ulong BenchCustom( void )
      {
       double               Price= 1.23456 ;
       const ulong          StartTime= GetMicrosecondCount ();
    //---
       for ( int i= 0 ; i< 1.0 e8;i++)
         {
           //--- этот код полностью вырезается, так как у нас заведомо константа 5
           //if(digits>8)
           //   digits=8;
           //--- распространяем переменные и активно заменяем константы
           if ((Price+ 0.00001 )> 0 )
             Price= int ((Price+ 0.00001 )/ 1.0 e- 5 +( 0.5 + 1.0 e- 7 + 1.0 e- 13 ))* 1.0 e- 5 ;
           else
             Price= int ((Price+ 0.00001 )/ 1.0 e- 5 -( 0.5 + 1.0 e- 7 + 1.0 e- 13 ))* 1.0 e- 5 ;
         }
    
       Print ( "Result: " ,Price);
    //---
       return ( GetMicrosecondCount () - StartTime);
      }
    
    Zaman kaybetmemek için saf sabitleri toplamadım. hepsinin derleme zamanında katlanması garanti edilir.

    kodu çalıştırın ve orijinal sürümdekiyle aynı zamanı alın:
    Custom:   1149536 msc
    Standard: 1767592 msc
    
    sayıların titremesine dikkat etmeyin - mikrosaniye düzeyinde, zamanlayıcı hatası ve bilgisayardaki kayan yük normal aralıktadır. oran tamamen korunur.

  9. Sabit girdiler nedeniyle test etmeye başladığınız koda bakın.

    Derleyici çok güçlü optimizasyonlara sahip olduğundan, göreviniz etkili bir şekilde basitleştirildi.


  10. Peki performansı nasıl test edersiniz?

    Derleyicinin nasıl çalıştığını anlayarak, ön optimizasyon ve basitleştirmeler uygulamasını engellemeniz gerekir.

    Örneğin, digits parametresini değişken yapalım:

     #define EPSILON ( 1.0 e- 7 + 1.0 e- 13 )
    #define HALF_PLUS  ( 0.5 + EPSILON)
    //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    double MyNormalizeDouble( const double Value, uint digits)
      {
       static const double Points[]={ 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };
    //---
       if (digits> 8 )
          digits= 8 ;
    //---   
       return (( int )((Value > 0 ) ? Value / Points[digits] + HALF_PLUS : Value / Points[digits] - HALF_PLUS) * Points[digits]);
      }
    //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    ulong BenchStandard( const int Amount= 1.0 e8)
      {
       double        Price= 1.23456 ;
       const double point= 0.00001 ;
       const ulong   StartTime= GetMicrosecondCount ();
    //---
       for ( int i= 0 ; i<Amount;i++)
         {
          Price= NormalizeDouble (Price+point, 2 +(i& 15 ) );
         }
    
       Print ( "Result: " ,Price);   // специально выводим результат, чтобы цикл не оптимизировался в ноль
    //---
       return ( GetMicrosecondCount () - StartTime);
      }
    //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    ulong BenchCustom( const int Amount= 1.0 e8)
      {
       double        Price= 1.23456 ;
       const double point= 0.00001 ;
       const ulong   StartTime= GetMicrosecondCount ();
    //---
       for ( int i= 0 ; i<Amount;i++)
         {
          Price=MyNormalizeDouble(Price+point, 2 +(i& 15 ) );
         }
    
       Print ( "Result: " ,Price);   // специально выводим результат, чтобы цикл не оптимизировался в ноль
    //---
       return ( GetMicrosecondCount () - StartTime);
      }
    //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    void OnStart ( void )
      {
       Print ( "Standard: " ,BenchStandard(), " msc" );
       Print ( "Custom:   " ,BenchCustom(), " msc" );
      }
    
    Çalıştırırız ve... öncekiyle aynı hız sonucunu alırız.

    Kodunuz daha önce olduğu gibi yaklaşık %35 kazanır.

  11. Neden öyle?

    Satır içi oluşturma nedeniyle kendimizi hala optimizasyondan kurtaramadık. 100.000.000 çağrıyı yığından veri geçirerek aynı uygulamanın NormalizeDouble işlevimize kaydederek kolayca böyle bir ivme verebilir.

    Bir MQL5 programında fonksiyon yer değiştirme tablosunu yüklerken NormalizeDouble'ımızı direct_call mekanizmasına koymadığımıza dair bir şüphemiz daha var.

    Sabah kontrol edeceğiz ve eğer durum buysa, onu direct_call'a aktaracağız ve hızı tekrar kontrol edeceğiz.

İşte NormalizeDouble'ın bir çalışması.

MQL5 derleyicimiz, C++ kodunun hızıyla karşılaştırıldığında yeterliliğini gösteren sistem işlevimizi yendi.

 
fxsaber :

eğer değiştirin

anahtar varyantında, anahtar uygulamasının kalitesini sayılarla görebileceksiniz.

Statik bir diziye doğrudan indekslenmiş erişimi sabit bir indeks (bir alandan bir sabite dönüşen) ve anahtar ile karıştırıyorsunuz.

anahtarı bu durumda çok rekabetçi değil. switch'in yaygın olarak kullanılan birkaç form optimizasyonu vardır:

  • "Açıkça sıralı ve kısa değerler statik bir diziye ve indeks geçişine konur" - en basit ve en hızlı, statik bir diziyle rekabet edebilir, ancak her zaman değil.
  • "bölge sınırlarını kontrol eden sıralı ve yakın değer parçalarında birkaç dizi" - burada zaten frenlerle
  • "çok az kontrol edilen değer aptalca kontrol edilirse" - hız yok, ancak programcı suçlanacak, yerinde olmayan anahtarı kullanıyor
  • "ikili arama ile tamamen seyrek sıralı tablo" - korkunç durumlar için çok yavaş

Aslında, bir anahtar için en iyi strateji, geliştiricinin kasıtlı olarak daha düşük sayılar kümesindeki değerler kümesini kapsamda kompakt hale getirmeye çalışmasıdır.

 
Renat Fatkhullin :

NormalizeDouble ile betiğin temizlenmiş bir sürümünü düşünün:

Sonuçlar:


Hemen yorumlar ve açıklamalar:

  1. static burada gereklidir, böylece derleyici bu diziyi işlevden çıkarır ve işlev her çağrıldığında yığın üzerinde oluşturmaz . C++ derleyicisi de aynı şeyi yapar.
"Optimize=0" ile öyle. "Optimize=1" ile onu çöpe bile atabilirsiniz - ortaya çıktığı gibi derleyici optimize edici akıllıdır.
  1. Derleyicinin işe yaramaz olduğu için döngüyü dışarı atmaması için hesaplamaların sonuçlarını kullanmanız gerekir. Örneğin, Print değişkenini Fiyat yapın.
Harika özellik!
  1. İşlevinizde bir hata var - rakamların sınırları kontrol edilmiyor, bu da kolayca bir dizinin sınırların dışına çıkmasına neden olabilir.

    Örneğin, MyNormalizeDouble(Price+point, 10 ) gibi bir çağrı yapın ve hatayı yakalayın:
    Kontrolleri atlayarak hızlandırma yöntemi kabul edilebilir, ancak bizim durumumuzda değil. Herhangi bir hatalı veri girişini işlemekle yükümlüyüz.

  2. 8'den büyük bir dizin için basit bir koşul ekleyelim ve kodu basitleştirmek için <0 ek koşulu yerine >8 için bir karşılaştırma yapmak için digit değişkeninin türünü uint ile değiştireceğiz.
evet en iyisi bu gibi
 double MyNormalizeDouble( const double Value, const uint digits )
{
   static const double Points[] = { 1.0 e- 0 , 1.0 e- 1 , 1.0 e- 2 , 1.0 e- 3 , 1.0 e- 4 , 1.0 e- 5 , 1.0 e- 6 , 1.0 e- 7 , 1.0 e- 8 };
   const double point = digits > 8 ? 1.0 e- 8 : Points[digits];

   return (( int )((Value > 0 ) ? Value / point + HALF_PLUS : Value / point - HALF_PLUS) * point);
}
  1. Her şey performans testçilerinin standart hatasıyla ilgili.

    Testler yazarken, derleyici tarafından uygulanabilecek optimizasyonların tam listesini aklınızda bulundurmanız gerekir. Basitleştirilmiş bir örnek test yazarken hangi girdileri kullandığınız ve bunların nasıl yok edileceği konusunda çok net olmanız gerekir.
  2. Peki performansı nasıl test etmelisiniz?

    Derleyicinin nasıl çalıştığını anlayarak, ön optimizasyon ve basitleştirmeler uygulamasını engellemeniz gerekir.

    Örneğin, digits parametresini değişken yapalım:
Derleyici performans ölçümlerinin nasıl düzgün bir şekilde hazırlanacağına dair ayrıntılı açıklama için çok teşekkür ederiz! Gerçekten de, sabiti optimize etme olasılığını hesaba katmadı.

İşte NormalizeDouble'ın bir çalışması.

MQL5 derleyicimiz, C++ kodunun hızıyla karşılaştırıldığında yeterliliğini gösteren sistem işlevimizi yendi.

Evet, böyle bir sonuç gurur meselesidir.
 
Renat Fatkhullin :

Statik bir diziye doğrudan indekslenmiş erişimi sabit bir indeks (bir alandan bir sabite dönüşen) ve anahtar ile karıştırıyorsunuz.

anahtarı bu durumda çok rekabetçi değil. switch'in yaygın olarak kullanılan birkaç form optimizasyonu vardır:

  • "Açıkça sıralı ve kısa değerler statik bir diziye ve indeks geçişine konur" - en basit ve en hızlı, statik bir diziyle rekabet edebilir, ancak her zaman değil.

İşte tam da böyle bir düzen durumu.

Aslında, bir anahtar için en iyi strateji, geliştiricinin kasıtlı olarak daha düşük sayılar kümesindeki değerler kümesini kapsamda kompakt hale getirmeye çalışmasıdır.

32 bit sistemde denendi. Orada, yukarıdaki örnekte anahtarla değiştirme ciddi frenlere yol açtı. Yeni bir arabada test etmedim.
 
fxsaber :

İşte tam da böyle bir düzen durumu.

Ayrı ayrı kontrol etmek gerekir, ancak daha sonra.


32 bit sistemde denendi. Orada, yukarıdaki örnekte anahtarla değiştirme ciddi frenlere yol açtı. Yeni bir arabada test etmedim.

Her MQL5 aslında iki derlenmiş programa sahiptir: 32 bit için basitleştirilmiş program ve 64 bit için maksimum optimize edilmiş program. 32 bit MT5'te yeni optimize edici hiç uygulanmaz ve 32 bit işletim sistemleri için kod, MT4'teki MQL4 kadar basittir.

Yalnızca MT5'in 64 bit sürümünde çalıştırıldığında on kat daha hızlı kod üretebilen bir derleyicinin tüm verimliliği: https://www.mql5.com/en/forum/58241

Tamamen platformun 64 bit sürümlerine odaklandık.

 

NormalizeDouble konusunda böyle bir saçmalık var

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

Sıralı olarak bir enum üzerinde yineleme nasıl yapılır?

fxsaber , 2016.08.26 16:08

İşlev açıklamasında bir not var

Bu yalnızca minimum fiyat adımı 10^N olan ve N'nin bir tam sayı olduğu ve pozitif olmadığı semboller için geçerlidir. Minimum fiyat adımı farklı bir değere sahipse, o zaman OrderSend'den önce fiyat seviyelerini normalleştirmek anlamsız bir işlemdir ve çoğu durumda OrderSend'in false döndürmesine neden olur.


Yardımdaki eski görüşleri düzeltmek güzel olurdu.

NormalizeDouble tamamen gözden düştü. Sadece yavaş bir uygulama olmakla kalmaz, aynı zamanda çeşitli stok sembollerinde (örneğin, RTS, MIX, vb.) anlamsızdır .

NormalizeDouble, başlangıçta sizin tarafınızdan Order* işlemleri için oluşturulmuştur. Temel olarak, fiyatlar ve lotlar için. Ancak standart olmayan TickSize ve VolumeStep çıktı. Ve işlev sadece kullanımdan kaldırıldı. Bu nedenle bir fren kodu yazarlar. Standart kitaplıktan örnek
 double CTrade::CheckVolume( const string symbol, double volume, double price, ENUM_ORDER_TYPE order_type)
  {
//--- check
   if (order_type!= ORDER_TYPE_BUY && order_type!= ORDER_TYPE_SELL )
       return ( 0.0 );
   double free_margin= AccountInfoDouble ( ACCOUNT_FREEMARGIN );
   if (free_margin<= 0.0 )
       return ( 0.0 );
//--- clean
   ClearStructures();
//--- setting request
   m_request.action= TRADE_ACTION_DEAL ;
   m_request.symbol=symbol;
   m_request.volume=volume;
   m_request.type  =order_type;
   m_request.price =price;
//--- action and return the result
   if (!:: OrderCheck (m_request,m_check_result) && m_check_result.margin_free< 0.0 )
     {
       double coeff=free_margin/(free_margin-m_check_result.margin_free);
       double lots= NormalizeDouble (volume*coeff, 2 );
       if (lots<volume)
        {
         //--- normalize and check limits
         double stepvol= SymbolInfoDouble (symbol, SYMBOL_VOLUME_STEP );
         if (stepvol> 0.0 )
            volume=stepvol*( MathFloor (lots/stepvol)- 1 );
         //---
         double minvol= SymbolInfoDouble (symbol, SYMBOL_VOLUME_MIN );
         if (volume<minvol)
            volume= 0.0 ;
        }
     }
   return (volume);
  }

Pekala, bunu yapamazsın! NormalizeDouble'ı unutarak birçok kez daha hızlı olabilir

 double NormalizePrice( const double dPrice, double dPoint = 0 )
{
   if (dPoint == 0 ) 
    dPoint = :: SymbolInfoDouble (:: Symbol (), SYMBOL_TRADE_TICK_SIZE );

   return (( int )((dPrice > 0 ) ? dPrice / dPoint + HALF_PLUS : dPrice / dPoint - HALF_PLUS) * dPoint);
}

Ve aynı hacim için o zaman

volume = NormalizePrice(volume, stepvol);

Fiyatlar için

NormalizePrice(Price, TickSize)

Standart NormalizeDouble'ın aşırı yüklenmesi olarak böyle bir şey eklemek doğru görünüyor. İkinci parametre olan "rakamlar" int değil, iki katı olacaktır.

 

2016 itibariyle, çoğu C++ derleyicisi aynı optimizasyon seviyelerine ulaşmıştı.

MSVC, her güncellemedeki iyileştirmeleri merak etmenizi sağlar ve bir derleyici olarak Intel C++ birleştirilmiştir - ve büyük projelerdeki "iç hatalarından" kurtarılmamıştır.

Derleyicideki 1400 derlemesindeki iyileştirmelerimizden bir diğeri, karmaşık projeleri derlemenin daha hızlı hale gelmesidir.

 

Bu konuda. Standart işlevlere alternatifler yaratmalısınız, çünkü bazen ihtiyacınız olanı vermezler. İşte SymbolInfoTick'e örnek bir alternatif

 // Получение тика, который на самом деле вызвал крайнее событие NewTick
bool MySymbolInfoTick( const string Symb, MqlTick &Tick, const uint Type = COPY_TICKS_ALL )
{
   MqlTick Ticks[];
   const int Amount = :: CopyTicks (Symb, Ticks, Type, 0 , 1 );
   const bool Res = (Amount > 0 );
  
   if (Res)
    Tick = Ticks[Amount - 1 ];
  
   return (Res);
}

// Возвращает в точности то, что SymbolInfoTick
bool CloneSymbolInfoTick( const string Symb, MqlTick &Tick )
{
   MqlTick TickAll, TickTrade, TickInfo;
   const bool Res = (MySymbolInfoTick(Symb, TickAll) &&
                    MySymbolInfoTick(Symb, TickTrade, COPY_TICKS_TRADE ) &&
                    MySymbolInfoTick(Symb, TickInfo, COPY_TICKS_INFO ));
  
   if (Res)
  {
    Tick = TickInfo;

    Tick.time = TickAll.time;
    Tick.time_msc = TickAll.time_msc;
    Tick.flags = TickAll.flags;
    
    Tick.last = TickTrade.last;
    Tick.volume = TickTrade.volume;    
  }
  
   return (Res);
}

Test cihazında, her olayda NewTick SymbolInfoTick'i arayın ve değişim cirosunu bulmak için hacim alanını ekleyin. Ama hayır, yapamazsın! MySymbolInfoDouble anlamında çok daha mantıklı yapmanız gerekiyor.

 
fxsaber :

NormalizeDouble konusunda böyle bir saçmalık var

NormalizeDouble, başlangıçta sizin tarafınızdan Order* işlemleri için oluşturulmuştur. Temel olarak, fiyatlar ve lotlar için. Ancak standart olmayan TickSize ve VolumeStep çıktı. Ve işlev sadece kullanımdan kaldırıldı. Bu nedenle bir fren kodu yazarlar. Standart kitaplıktan örnek

Pekala, bunu yapamazsın! NormalizeDouble'ı unutarak birçok kez daha hızlı olabilir

Ve aynı hacim için o zaman

Fiyatlar için

Standart NormalizeDouble'ın aşırı yüklenmesi olarak böyle bir şey eklemek doğru görünüyor. İkinci parametre "rakamlar" int değil, iki katı olacaktır.

Etrafınızdaki her şeyi optimize edebilirsiniz.

Bu sonsuz bir süreç. Ancak vakaların %99'unda ekonomik olarak uygun değildir.