Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 130

 
// ArrayResize с освобождением памяти
template <typename T>
int ArrayResize2( T &Array[], const int NewSize, const int Reserve = 0 )
{
  T ArrayTmp[];
  
  ArraySwap(Array, ArrayTmp);
  const int Res = ArrayResize(Array, NewSize, Reserve);
  
  if (Res > 0)
    ArrayCopy(Array, ArrayTmp, 0, 0, MathMin(Res, ArraySize(ArrayTmp)));
    
  return(Res);
}
 
fxsaber :

Teşekkür ederim. ArraySwap işlevini kullanmak aklıma gelmezdi.

Anladığım kadarıyla, işleviniz boyutta hem artış hem de azalma ile çalışacak, yani. tam bir ArrayResize analogu olarak.

Bir diziyi arttırırken, ArraySwap, ArrayResize, ArrayCopy üç işlevini çağırmaktansa, yalnızca standart ArrayResize'ı çağırmak daha iyi değil mi?


ps Sürümünüzü kontrol ettim ve MqlTick dizisini 1.000.000'dan 500.0000'e düşürürken iki kopya ile benim sürümünüzü kontrol ettim. Sürümünüz 22 milisaniyede başa çıkıyor. Benimki 37-38.
 
pivomoe :

Bir diziyi arttırırken, ArraySwap, ArrayResize, ArrayCopy üç işlevini çağırmaktansa, yalnızca standart ArrayResize'ı çağırmak daha iyi değil mi?

Düşündüm ama yapmadım çünkü. aslında daha fazla nüans var. Bu yüzden daha basit versiyona bağlı kalmaya karar verdim.

Nüanslardan biri şudur. Yapıcılar/yıkıcılar içeren bir yapı dizisi alırsanız, ArrayResize bunları her iki yönde de değerler arasındaki farka eşit bir miktarda çağırır.

Ancak ArrayCopy kullanımı, tüm yapıcılara yapılan bir çağrıdır. ArrayTmp kaldırılıyor - tüm yıkıcıları çağırıyor. Yani ArrayResize2 tam olarak ArrayResize değil.

 
Görünüşe göre ArrayResize ( arr, new_size, -1) bu şekilde yazabilirsiniz. Doğru, sürümünüz 37 milisaniyeye karşılık 22 milisaniye civarında hala daha hızlı.
 
Danışmanın çerçeve modunu bıraktınız, ancak ona geri dönmeniz gerekiyor. Aşağıdaki danışman bunun nasıl yapılacağını gösterir.
 // Создание mqd-Файла из Тестера, чтение mqd-файла из Терминала во фрейм/ стандартном режиме работы советника.

input int Range = 0 ; // 0..10

void OnTesterInit ( void ) {}
void OnTesterDeinit ( void ) {}

#define TOSTRING(A) #A + " = " + ( string )(A) + " "

void OnTesterPass ( void )
{
   ulong Pass;
   string Name;
   long ID;
   double Value;

   while ( FrameNext (Pass, Name, ID, Value)) // Прочли очередной проход из mqd-файла.
     Print (TOSTRING(Pass) + TOSTRING(Name) + TOSTRING(Value)); // Вывели данные mqd-файла
}

double OnTester ( void )
{
   if ( MQLInfoInteger ( MQL_OPTIMIZATION ))
  {
     uchar Data[];

     FrameAdd ( TerminalInfoString ( TERMINAL_DATA_PATH ), 0 , MathRand (), Data); // Отправили данные в mqd-файл Терминала.
  }

   return ( 0 );
}

void OnInit ()
{
   if ( MQLInfoInteger ( MQL_TESTER ))
  {
     // OnInit для Тестера
  }
   else if ( FrameFirst ()) // Удалось инициализировать mqd-файл.
  {
     OnTesterInit ();
     OnTesterPass ();
  }
}

void OnDeinit ( const int )
{
   if ( MQLInfoInteger ( MQL_TESTER ))
  {
     // OnDeinit для Тестера
  }
   else
     OnTesterDeinit ();
}

void OnTick ()
{
   static const bool IsTester = MQLInfoInteger ( MQL_TESTER );
  
   if (!IsTester)
     return ;
    
   // OnTick для Тестера.
}


Optimizasyondan sonra bunu göreceksiniz

Pass = 0 Value = 25534.0 
Pass = 1 Value = 12915.0 
Pass = 7 Value = 25534.0 
Pass = 8 Value = 12915.0 
Pass = 6 Value = 6528.0 
Pass = 5 Value = 2523.0 
Pass = 3 Value = 22229.0 
Pass = 2 Value = 9767.0 
Pass = 4 Value = 7748.0 
Pass = 9 Value = 25534.0 
Pass = 10 Value = 12915.0 


Expert Advisor'ı çerçeve modunda kapatır ve standart modda çalıştırırsanız, Optimizasyon sırasında aldığı verilerin aynısını gösterecektir.

Bu yaklaşım, tekrar tekrar Optimizasyon sonuçlarına geri dönmenizi sağlar.


PS Danışmanın çerçeve modu için Terminalde açılan çizelgede birden fazla danışman çalıştıramazsınız. Bu nedenle standart modda çalıştırmanız gerekiyorsa, çerçeveler için açılmamış grafikler üzerinde çalıştırmanız gerekir.

 
extern artık kodlanmış bir makro
 #undef extern
#define extern // macro redefinition
Buna göre, mq4 kodunun MT5'te değişiklik yapmadan çalışmasını sağlamak her zaman mümkün olmayacaktır.
 

fxsaber :
extern теперь является жестко заданным макросом

Buna göre, mq4 kodunun MT5'te değişiklik yapmadan çalışmasını sağlamak her zaman mümkün olmayacaktır.

Belgelerde herhangi bir değişiklik yok. Bunu daha detaylı açıklayabilir misiniz?

 
Alexey Viktorov :

Belgelerde herhangi bir değişiklik yok. Bunu daha detaylı açıklayabilir misiniz?

Bu tür kod

 #property script_show_inputs

#define extern input // macro redefinition

extern int i = 0 ;

void OnStart () {}

her zaman bir uyarı verecektir. "İmkansızlık" ile ilgili olarak - heyecanlandım. Geçersiz kılmak mümkündür, bu nedenle bu tür durumlarda sadece uyarılar her zaman askıda kalır.

 
fxsaber :

Nüanslardan biri şudur. Yapıcılar/yıkıcılar içeren bir yapı dizisi alırsanız, ArrayResize bunları her iki yönde de değerler arasındaki farka eşit bir miktarda çağırır.

Ancak ArrayCopy kullanımı, tüm yapıcılara yapılan bir çağrıdır. ArrayTmp kaldırılıyor - tüm yıkıcıları çağırıyor. Yani ArrayResize2 tam olarak ArrayResize değil.

O zaman ona ArrayReallocate demek muhtemelen daha doğru olur. Her ne kadar böyle bir zorla yeniden kopyalamada bir anlam görmüyorum. Ekstra frenler. Tek şey, muhtemelen yalnızca bir dizi sınıf nesnesinin işaretçileri sıfırlaması gerekiyorsa (önceki değerlerini geçersiz kılar), bu bir yerde dikkate alınırsa (ancak bu daha çok bir koltuk değneğidir)
 
Alexey Navoykov :
O zaman ona ArrayReallocate demek muhtemelen daha doğru olur. Her ne kadar böyle bir zorla yeniden kopyalamada bir anlam görmüyorum. Ekstra frenler.

Belleği boşaltmak tek nedendir.