Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 89

 
Nikolai Semko:

  1. siehe meinen vorherigen Beitrag
  2. Ich habe viele Beispiele für den praktischen Nutzen von Mikrosekunden.

Bislang sehe ich nur einen einzigen erwähnten Nachteil von GetTickCount - die Tatsache, dass es durch die Auflösung des Systemtimers begrenzt ist, das ist ein ernstes Problem. Und der Rest ist von keinem besonderen praktischen Nutzen.Was Sie machen, sind ultrakurze Tests von 15 Millisekunden - das macht niemand. Solche Ergebnisse sind instabil. Sie müssen den Test mindestens eine halbe Sekunde dauern lassen, dann können Sie etwas darüber sagen.

 
Alexey Navoykov:

Niemand führt Ultrakurztests von 15 Millisekunden durch. Solche Ergebnisse sind instabil. Man braucht mindestens eine halbe Sekunde, bis der Test beendet ist, dann kann man über etwas reden.

Sie irren sich. Während dieser 15 Millisekunden wird die Funktion GetTickCount() mehr als 6 000 000 Mal aufgerufen.

Meine Berechnung ist korrekt. Der Wert von GetTickCount() ändert sich alle 1/(2^6)=1/64 Sekunden (15625 Mikrosekunden).
Entwickler, bitte bestätigen.

 
ikolai Semko:

Falsch.Die Funktion GetTickCount() wirdin diesen 15 Millisekunden mehr als 6 000 000 Mal aufgerufen.

Wenn wir die Leistung eines funktionierenden Codes (kein kugelförmiges Pferd im Vakuum) messen, wird er für ein ausreichendes Zeitintervall (Hunderte von Millisekunden und mehr) ausgeführt. Der Grund dafür ist, dass sich die Leistung des Systems und die Arbeitslast ständig ändern. In einem Moment ist es das eine, im nächsten Moment ist es etwas anderes. Daher werden die Ergebnisse von Test zu Test in kurzen Intervallen stark variieren. Deshalb brauchen wir ein längeres Intervall, aber Mikrosekunden spielen da keine Rolle mehr.

Außerdem haben wir Anführungszeichen in Millisekunden, und Pings werden auch in Millisekunden angegeben, so dass ich nicht erkennen kann, wo Mikrosekunden stehen sollten. Wie auch immer, das ist nicht der Punkt.

Jetzt muss ich eine Lösung finden, wie ich aus dieser Situation herauskomme, um die Nachteile beider Funktionen zu vermeiden. Es gibt nicht viel Hoffnung für die Entwickler.

 
Alexey Navoykov:

Jetzt müssen wir herausfinden, wie wir die Unzulänglichkeiten beider Funktionen umgehen können. Für die Entwickler gibt es nicht viel Hoffnung.

Ich denke, dass dies mit einer solchen Formel in erster Näherung möglich ist:

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

Bis jetzt ist es nur eine Idee, die laut ausgesprochen wird.

 

Einige Stellen, an denen ich Mikrosekunden verwende

  • Custom TimeCurrent, mit ungefährer Genauigkeit auf msec.
  • Berechnung der Ausführungszeit von Handelsaufträgen.
  • Berechnung der Synchronisationszeit der Handelshistorie im Terminal.
  • Verzögerung des Terminals (~ 5 ms) - um wie viel der Tick zum Zeitpunkt seines OnTick/OnCalculate veraltet ist.
  • Korrektur von OnTimer, so dass der Abstand zwischen beliebigen (nicht nur benachbarten) Time-Events ein Vielfaches der angegebenen Zeit ist.
 
fxsaber:

Einige Stellen, an denen ich Mikrosekunden verwende

  • Anpassung von OnTimer, so dass der Abstand zwischen beliebigen (nicht nur benachbarten) Zeitereignissen ein Vielfaches der angegebenen Zeit ist.

Zweitens ist der Fehler derselbe wie bei GetTickCount(), d.h. 15 Millisekunden. Deshalb ist die Bedeutung von Mikrosekunden nicht ganz klar. Angenommen, Sie haben ein mikrogenaues Intervall berechnet, aber in Wirklichkeit kommt es mehrere MILLIONEN Sekunden später oder früher.

 
Alexey Navoykov:

Zweitens ist der Fehler derselbe wie bei GetTickCount(), d.h. 15 Millisekunden, so dass nicht ganz klar ist, was der Sinn von Mikrosekunden hier ist. Angenommen, Sie berechnen das Intervall mit Mikropräzision, aber tatsächlich wird es mehrere MILLIONEN Sekunden später oder früher kommen.


Außerdem werden Befehle in eine Warteschlange gestellt und die Ausführung kann bis zu 5 Sekunden dauern...

 
Alexey Navoykov:

Jetzt müssen wir herausfinden, wie wir die Unzulänglichkeiten beider Funktionen umgehen können. Für die Entwickler gibt es nicht viel Hoffnung.


Leider.
kann ich Ihnen nur diese Variante der Funktion anbieten:

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);
  }

Warum Alas?
Denn wenn Sie die Ortszeit ändern oder sich ein Programm einfach aufhängt, kann ein Fehler von bis zu 16 Millisekunden zur FunktionRealMicrosecondCount hinzugefügt werden. Es lässt sich nicht vermeiden.
Aber die Umstellung auf Sommerzeit, die Zeitzonenumstellung und die Zeitaktualisierung über das Internet haben keine fatalen Folgen.

Dateien:
 
Nikolai Semko:


Leider kann
nur diese Version der Funktion anbieten:

Warum Alas?
Denn im Falle einer Änderung der Ortszeit oder eines einfachen Software-Hangups kann der FunktionRealMicrosecondCount ein Fehler von bis zu 16 Millisekunden hinzugefügt werden. Daran führt kein Weg vorbei.
Aber die Umstellung auf Sommerzeit, Zeitzonenwechsel, Zeitaktualisierung über das Internet hat keine fatalen Folgen.

Ich habe es noch nicht überprüft, aber ich bin mir bei 16 ms nicht so sicher. Als ich das Thema gegoogelt habe, wird der System-Timer-Fehler in der Regel mit etwa 10 ms oder 10-16 ms angegeben.

 

Hier ist eine Variante, die einen hochauflösenden winapi-Timer verwendet und eine Genauigkeit von3,8e-07 Sekunden ergibt.

#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);
  }
}