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

 
Nikolay Semko :

  1. önceki mesajıma bakın
  2. Mikrosaniyelerin pratik kullanımıyla ilgili birçok örneğim var.

Şimdiye kadar, GetTickCount'un bahsettiğim tek dezavantajını görüyorum - sistem zamanlayıcısının çözünürlüğü ile sınırlı, evet, bu ciddi bir sorun. Gerisi çok az pratik kullanım içindir. 15 milisaniyelik ultra kısa testler yapıyor olmanız gerçeği - kimse yapmaz. Bu tür sonuçlar kararsızdır. Testin en az yarım saniye sürmesi gerekir, o zaman zaten bir şey hakkında konuşabilirsiniz.

 
Alexey Navoykov :

15 milisaniyelik ultra kısa testler yapıyor olmanız gerçeği - kimse yapmaz. Bu tür sonuçlar kararsızdır. Testin en az yarım saniye sürmesi gerekir, o zaman zaten bir şey hakkında konuşabilirsiniz.

Hatalısınız. Bu 15 milisaniye boyunca GetTickCount() işlevi 6.000.000'den fazla kez çağrılır.

Hesabım doğru. GetTickCount() değerini her 1/(2^6)=1/64 saniyede bir (15625 mikrosaniye) değiştirin.
Geliştiriciler, lütfen onaylayın.

 
ikolai Semko :

Hatalısınız. Bu 15 milisaniye boyunca GetTickCount() işlevi 6.000.000'den fazla kez çağrılır.

Çalışma kodunun performansı (vakumdaki küresel bir at değil) ölçüldüğünde, yeterli bir süre boyunca (yüzlerce milisaniye ve daha fazla) yarışır. Bunun nedeni, sistemin performansının ve iş yükünün sürekli değişmesidir. Bir an o bir ve bir sonraki o farklı. Ve kısa aralıklarla, sonuçlar testten teste büyük ölçüde değişecektir. Bu nedenle, daha uzun bir aralığa ihtiyaç vardır ve orada mikrosaniyeler artık bir rol oynamaz.

Daha ileri. Tekliflerimiz milisaniye cinsindendir. Pingler de milisaniye cinsinden sayılır. Bu nedenle, burada mikrosaniye nereye ekleyeceğimi göremiyorum. Ancak, mesele bu değil.

Şimdi her iki işlevin de eksikliklerini gidermek için durumdan nasıl çıkılacağına dair bir çözüm bulmamız gerekiyor. Geliştiriciler için çok az umut var.

 
Alexey Navoykov :

Şimdi her iki işlevin de eksikliklerini gidermek için durumdan nasıl çıkılacağına dair bir çözüm bulmamız gerekiyor. Geliştiriciler için çok az umut var.

Bunun gibi bir formülle ilk yaklaşıma ulaşmanın mümkün olduğunu düşünüyorum:

 ulong RealGetMicrosecondCount=( GetTickCount ()-StartGetTickCount)*1000+x+ GetMicrosecondCount ()% 15625 ;

Şimdilik, bu sadece bir düşünce.

 

Mikrosaniye kullandığım bazı yerler

  • ms'ye kadar yaklaşık doğrulukla özel TimeCurrent.
  • Bir ticaret emrinin yürütme süresinin hesaplanması.
  • Terminalde işlem geçmişi senkronizasyon süresinin hesaplanması.
  • Terminal gecikmesi (~ 5 ms) - OnTick/OnCalculate zamanına kadar bir onay işaretinin ne kadar eski olduğuna göre.
  • OnTimer'ı, (sadece komşu değil) herhangi bir Zaman olayı arasındaki mesafenin belirtilen zamanın katı olacak şekilde ayarlama.
 
fxsaber :

Mikrosaniye kullandığım bazı yerler

  • OnTimer'ı, (sadece komşu değil) herhangi bir Zaman olayı arasındaki mesafenin belirtilen zamanın katı olacak şekilde ayarlama.

Yani zamanlayıcı öncelikle milisaniyedir. İkincisi, hatası GetTickCount() ile aynıdır, yani. 15 milisaniye. Dolayısıyla burada mikrosaniyenin ne anlamı var çok net değil. Aralığı mikro doğrulukla hesapladığınızı varsayalım, ancak aslında birkaç MILLIsaniye sonra veya daha önce gelecektir.

 
Alexey Navoykov :

Yani zamanlayıcı öncelikle milisaniyedir. İkincisi, hatası GetTickCount() ile aynıdır, yani. 15 milisaniye. Dolayısıyla burada mikrosaniyenin ne anlamı var çok net değil. Aralığı mikro doğrulukla hesapladığınızı varsayalım, ancak aslında birkaç MILLIsaniye sonra veya daha önce gelecektir.


ve komutlar kuyruğa alınır ve sırayla yürütme 5 saniye içinde olabilir ..

 
Alexey Navoykov :

Şimdi her iki işlevin de eksikliklerini gidermek için durumdan nasıl çıkılacağına dair bir çözüm bulmamız gerekiyor. Geliştiriciler için çok az umut var.


Ne yazık ki.
Sadece bu seçeneği önerebilirim:

 ulong RealMicrosecondCount()
  {
   static bool first= true ;
   static ulong sum= 0 ;
   static long delta;
   static long shift= 0 ;
   static ulong   lasttickcount;
   ulong i= GetTickCount ()+sum;
   ulong t= GetMicrosecondCount ();
   if (first) // если первый вход, то вычисляем разницу GetMicrosecondCount и GetTickCount
     {
      lasttickcount=i;
      delta=(( long )i* 1000 - long (t));
      first= false ;
     }
   long curdelta=(( long )i* 1000 - long (t));
   long d=curdelta-delta;
   if ( fabs (d-shift)> 20000 ) shift=d;
   if (i<lasttickcount) sum+= 0x100000000 ;
   lasttickcount=i;
   return (t+shift);
  }

Neden Eyvah?
Çünkü yerel saatin değişmesi veya sadece bir yazılımın donması durumunda RealMicrosecondCount işlevine 16 milisaniyeye kadar hata eklenebilmektedir. Ve bunun bir yolu yok.
Ancak öte yandan, kış (yaz) saatine geçerken, kayış değiştirirken, internet üzerinden saat güncellenirken ölümcül sonuçlar olmayacaktır.

Dosyalar:
 
Nikolay Semko :


Ne yazık ki.
Sadece bu seçeneği önerebilirim:

Neden Eyvah?
Çünkü yerel saatin değişmesi veya sadece bir yazılımın donması durumunda RealMicrosecondCount işlevine 16 milisaniyeye kadar hata eklenebilmektedir. Ve bunun bir yolu yok.
Ancak öte yandan, kış (yaz) saatine geçerken, kayış değiştirirken, internet üzerinden saat güncellenirken ölümcül sonuçlar olmayacaktır.

Henüz test etmedim ama 16 ms'den pek emin değilim. Bu konuyu google'da arattığımda sistem timer hatası genelde yaklaşık 10 ms veya 10-16 arası veriliyor.

 

İşte 3.8e-07 saniyelik bir doğruluk sağlayan yüksek çözünürlüklü bir winapi zamanlayıcı kullanan bir varyant.

 #import "Kernel32.dll"
   int QueryPerformanceCounter( ulong &lpPerformanceCount);
   int QueryPerformanceFrequency( ulong &lpFrequency);
#import


ulong QueryPerfomanceCounter() { ulong value;   if (QueryPerformanceCounter(value)) return value;   return 0 ; } 

ulong QueryPerformanceFrequency() { ulong freq;   if (QueryPerformanceFrequency(freq)) return freq;   return 0 ; }  


long GetPerfomanceCount_mcs()
{ 
   static long freq= QueryPerformanceFrequency();
   return freq ? QueryPerfomanceCounter()* 1000000 /freq : 0 ;
}


void OnStart ()
{
   Print ( "Resolution of perfomance counter:  " , 1.0 /QueryPerformanceFrequency(), " s" );
   ulong   perfcount= GetPerfomanceCount_mcs(); 
  
   while (! IsStopped ())
  {
     Comment ((GetPerfomanceCount_mcs()-perfcount)/ 1000000.0 );
     Sleep ( 10 );
  }
}