Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 89

 
Nikolai Semko:

  1. vedere il mio post precedente
  2. Ho un sacco di esempi con vantaggi pratici di microsecondi.

Finora vedo solo uno svantaggio menzionato di GetTickCount - il fatto che sia limitato dalla risoluzione del timer di sistema, questo è un problema serio. E il resto non ha una particolare utilità pratica.Quello che stai facendo è un test ultracorto di 15 millisecondi - nessuno lo fa. Tali risultati sono instabili. Devi far durare il test almeno mezzo secondo e poi potrai dire qualcosa.

 
Alexey Navoykov:

Nessuno fa test ultracorti di 15 millisecondi. Tali risultati sono instabili. È necessario almeno mezzo secondo perché il test duri, poi si può parlare di qualcosa.

Ti sbagli. Durante questi 15 millisecondi, la funzione GetTickCount() viene chiamata più di 6 000 000 volte.

Il mio calcolo è corretto. Il valore di GetTickCount() cambia ogni 1/(2^6)=1/64 secondi (15625 microsecondi).
Sviluppatori, per favore confermate.

 
ikolai Semko:

Sbagliato. Lafunzione GetTickCount() viene chiamata più di 6 000 000 voltein questi 15 millisecondi.

Quando misuriamo le prestazioni di un codice funzionante (non un cavallo sferico nel vuoto), viene eseguito per un intervallo di tempo sufficiente (centinaia di millisecondi e oltre). La ragione è che le prestazioni del sistema e il carico di lavoro cambiano costantemente - un momento è uno, mentre un altro momento è diverso. E i risultati varieranno notevolmente da test a test in intervalli brevi. Ecco perché abbiamo bisogno di un intervallo più lungo, ma i microsecondi non contano.

Inoltre, abbiamo le virgolette in millisecondi e anche i ping sono in millisecondi, quindi non vedo dove dovrebbero essere messi i microsecondi. Comunque, non è questo il punto.

Ora devo inventare una soluzione, come uscire da questa situazione in modo da evitare gli inconvenienti di entrambe le funzioni. Non c'è molta speranza per gli sviluppatori.

 
Alexey Navoykov:

Ora dobbiamo capire come aggirare le carenze di entrambe le funzioni. Non c'è molta speranza per gli sviluppatori.

Penso che sia possibile con una formula come questa in prima approssimazione:

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

Per ora è solo un'idea ad alta voce.

 

Alcuni posti dove uso i microsecondi

  • Custom TimeCurrent, con una precisione approssimativa al msec.
  • Calcolo del tempo di esecuzione dell'ordine di compravendita.
  • Calcolo del tempo di sincronizzazione della storia del trading nel terminale.
  • Il ritardo del terminale (~ 5 ms) - di quanto il tick è superato al momento del suo OnTick/OnCalculate.
  • Correzione di OnTimer in modo che la distanza tra qualsiasi (non solo i vicini) Time-events sia un multiplo del tempo specificato.
 
fxsaber:

Alcuni posti dove uso i microsecondi

  • Regolazione di OnTimer in modo che la distanza tra qualsiasi evento Time (non solo adiacente) sia un multiplo del tempo dato.

In secondo luogo, il suo errore è lo stesso di GetTickCount(), cioè 15 millisecondi. Ecco perché il significato dei microsecondi non è molto chiaro. Supponiamo che abbiate calcolato un intervallo preciso al micro, ma in realtà verrà diversi MILIONI di secondi dopo o prima.

 
Alexey Navoykov:

In secondo luogo, il suo errore è lo stesso di GetTickCount(), cioè 15 millisecondi, quindi non è molto chiaro quale sia il punto dei microsecondi qui. Supponiamo che si calcoli l'intervallo con microprecisione, ma in realtà arriverà diversi MILIONI di secondi dopo o prima.


Inoltre i comandi si mettono in coda e l'esecuzione può avvenire in 5 secondi...

 
Alexey Navoykov:

Ora dobbiamo capire come aggirare le carenze di entrambe le funzioni. Non c'è molta speranza per gli sviluppatori.


Ahimè,
posso offrirvi solo questa variante della funzione:

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

Perché Alas?
Perché se cambiate l'ora locale o semplicemente avete un blocco del programma, un errore fino a 16 millisecondi può essere aggiunto alla funzioneRealMicrosecondCount. Non c'è modo di evitarlo.
Ma non ci saranno conseguenze fatali quando si passa all'ora legale, al cambio di fuso orario, all'aggiornamento dell'ora via Internet.

 
Nikolai Semko:


Ahimè,
può offrire solo questa versione della funzione:

Perché Alas?
Perché in caso di cambiamento dell'ora locale o semplicemente di blocco del software, un errore fino a 16 millisecondi può essere aggiunto alla funzioneRealMicrosecondCount. Non c'è modo di evitarlo.
Ma non ci saranno conseguenze fatali quando si passa all'ora legale, al cambio di fuso orario, all'aggiornamento dell'ora via Internet.

Non ho ancora controllato, ma non sono così sicuro di 16 ms. Quando ho cercato su Google l'argomento, di solito l'errore del timer di sistema è dato come circa 10 ms, o 10-16 ms.

 

Ecco una variante che utilizza un timer winapi ad alta risoluzione, dando una precisione di3,8e-07 secondi.

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