Caractéristiques du langage mql5, subtilités et techniques - page 89

 
Nikolai Semko:

  1. voir mon message précédent
  2. J'ai beaucoup d'exemples avec des avantages pratiques de microsecondes.

Jusqu'à présent, je ne vois qu'un seul inconvénient mentionné de GetTickCount - le fait qu'il soit limité par la résolution du timer du système, c'est un problème sérieux. Et le reste n'a pas d'utilité pratique particulière.Ce que vous faites, ce sont des tests ultra-courts de 15 millisecondes - personne ne fait cela. De tels résultats sont instables. Vous devez faire durer le test au moins une demi-seconde et alors vous pourrez en dire quelque chose.

 
Alexey Navoykov:

Personne ne fait de tests ultra-courts de 15 millisecondes. De tels résultats sont instables. Il faut au moins une demi-seconde pour que le test dure, puis on peut parler de quelque chose.

Vous avez tort. Pendant ces 15 millisecondes, la fonction GetTickCount() est appelée plus de 6 000 000 de fois.

Mon calcul est correct. La valeur GetTickCount() change toutes les 1/(2^6)=1/64 secondes (15625 microsecondes).
Développeurs, veuillez confirmer.

 
ikolai Semko:

Faux. Lafonction GetTickCount() est appelée plus de 6 000 000 de foispendant ces 15 millisecondes.

Lorsque nous mesurons les performances d'un code fonctionnel (et non d'un cheval sphérique dans le vide), nous l'exécutons pendant un intervalle de temps suffisant (des centaines de millisecondes et plus). La raison en est que les performances et la charge de travail du système changent constamment : à un moment donné, elles sont identiques, tandis qu'à un autre moment, elles sont différentes. Et les résultats varieront fortement d'un test à l'autre dans de courts intervalles. C'est pourquoi nous avons besoin d'un intervalle plus long, mais les microsecondes n'ont pas d'importance ici.

De plus, nous avons des guillemets en millisecondes et les pings sont aussi en millisecondes, donc je ne vois pas où il faudrait mettre les microsecondes. De toute façon, ce n'est pas le sujet.

Maintenant je dois inventer une solution, comment sortir de cette situation afin d'éviter les inconvénients des deux fonctions. Il n'y a pas beaucoup d'espoir pour les développeurs.

 
Alexey Navoykov:

Il faut maintenant trouver comment contourner les défauts des deux fonctions. Il n'y a pas beaucoup d'espoir pour les développeurs.

Je pense que c'est possible avec une formule comme celle-ci en première approximation :

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

Pour l'instant, c'est juste une idée à voix haute.

 

Quelques endroits où j'utilise les microsecondes

  • Custom TimeCurrent, avec une précision approximative en msec.
  • Calcul du temps d'exécution de l'ordre de bourse.
  • Calcul du temps de synchronisation de l'historique des transactions dans le Terminal.
  • Le décalage du terminal (~ 5 ms) - de combien le tick est dépassé au moment de son OnTick/OnCalculate.
  • Correction de OnTimer pour que la distance entre tous les événements temporels (et pas seulement entre voisins) soit un multiple du temps spécifié.
 
fxsaber:

Quelques endroits où j'utilise les microsecondes

  • Ajustement de OnTimer de sorte que la distance entre tous les événements temporels (pas seulement adjacents) soit un multiple du temps donné.

Deuxièmement, son erreur est la même que celle de GetTickCount(), c'est-à-dire 15 millisecondes. C'est pourquoi la signification des microsecondes n'est pas très claire. Supposons que vous ayez calculé un intervalle précis à la micro près, mais qu'en fait il arrive plusieurs MILLIONS de secondes plus tard ou plus tôt.

 
Alexey Navoykov:

Deuxièmement, son erreur est la même que celle de GetTickCount(), c'est-à-dire 15 millisecondes, donc l'intérêt des microsecondes ici n'est pas très clair. Supposons que vous calculez l'intervalle avec une micro précision, mais en fait il arrivera plusieurs MILLIONS de secondes plus tard ou plus tôt.


De plus, les commandes sont mises en file d'attente et leur exécution peut prendre 5 secondes...

 
Alexey Navoykov:

Il faut maintenant trouver comment contourner les défauts des deux fonctions. Il n'y a pas beaucoup d'espoir pour les développeurs.


Hélas.
Je ne peux vous proposer que cette variante de la fonction :

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

Pourquoi hélas ?
En effet, si vous modifiez l'heure locale ou si le programme se bloque, une erreur pouvant atteindre 16 millisecondes peut être ajoutée à la fonctionRealMicrosecondCount. Il n'y a aucun moyen de l'éviter.
Mais il n'y aura pas de conséquences fatales lors du passage à l'heure d'été, du changement de fuseau horaire, de la mise à jour de l'heure via Internet.

Dossiers :
 
Nikolai Semko:


Hélas.
ne peut offrir que cette version de la fonction :

Pourquoi hélas ?
En effet, en cas de changement de l'heure locale ou de simple blocage du logiciel, une erreur allant jusqu'à 16 millisecondes peut être ajoutée à la fonctionRealMicrosecondCount. Il n'y a aucun moyen d'y échapper.
Mais il n'y aura pas de conséquences fatales lors du passage à l'heure d'été, du changement de fuseau horaire, de la mise à jour de l'heure via Internet.

Je n'ai pas encore vérifié, mais je ne suis pas sûr de l'erreur de 16 ms. Lorsque j'ai fait une recherche sur le sujet, j'ai constaté que l'erreur de temporisation du système est généralement indiquée comme étant d'environ 10 ms, ou 10-16 ms.

 

Voici une variante utilisant un chronomètre winapi haute résolution, donnant une précision de3,8e-07 secondes.

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