Bibliotheken: Fast iBarShift und Bars für MT5

 

Fast iBarShift und Bars für MT5:

Vollständige und schnelle Funktionen ähnlich denen von Bars und iBarShift aus MQL4.


Autor: Nikolai Semko

 

Seit Build 1847 von MT5 wurde der Fehler des Hängenbleibens in der Bars-Funktion behoben. Außerdem wurde die Standardfunktion iBarShift hinzugefügt.
Um die Leistung dieser Funktionen zu erhöhen (irgendwo im Bereich des 10-fachen), ist es jetzt besser, diese Codevariante zu verwenden:

int fBars(string symbol_name,ENUM_TIMEFRAMES  timeframe,datetime start_time,datetime stop_time)
  {
   static string LastSymb=NULL;
   static ENUM_TIMEFRAMES LastTimeFrame=0;
   static datetime LastTime=0;
   static datetime LastTime0=0;
   static int PerSec=0;
   static int PreBars=0;
   static datetime LastBAR=0;
   static datetime LastTimeCur=0;
   static bool flag=true;
   static int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
   datetime TimeCur;
   if(timeframe==0) timeframe=_Period;
   const bool changeTF=LastTimeFrame!=timeframe;
   const bool changeSymb=LastSymb!=symbol_name;
   const bool change=changeTF || changeSymb || flag;

   LastTimeFrame=timeframe; LastSymb=symbol_name;
   if(changeTF) PerSec=::PeriodSeconds(timeframe); if(PerSec==0) { flag=true; return(0);}

   if(stop_time<start_time)
     {
      TimeCur=stop_time;
      stop_time=start_time;
      start_time=TimeCur;
     }
   if(changeSymb)
     {
      if(!SymbolInfoInteger(symbol_name,SYMBOL_SELECT))
        {
         SymbolSelect(symbol_name,true);
         ChartRedraw();
        }
     }
   TimeCur=TimeCurrent();
   if(timeframe==PERIOD_W1) TimeCur-=(TimeCur+345600)%PerSec; // 01.01.1970 - Donnerstag. Minus 4 Tage.
   if(timeframe<PERIOD_W1) TimeCur-=TimeCur%PerSec;
   if(start_time>TimeCur) { flag=true; return(0);}
   if(timeframe==PERIOD_MN1)
     {
      MqlDateTime dt;
      TimeToStruct(TimeCur,dt);
      TimeCur=dt.year*12+dt.mon;
     }

   if(changeTF || changeSymb || TimeCur!=LastTimeCur)
      LastBAR=(datetime)SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE);

   LastTimeCur=TimeCur;
   if(start_time>LastBAR) { flag=true; return(0);}

   datetime tS,tF=0;
   if(timeframe==PERIOD_W1) tS=start_time-(start_time+345599)%PerSec-1;
   else if(timeframe<PERIOD_MN1) tS=start_time-(start_time-1)%PerSec-1;
   else  // PERIOD_MN1
     {
      MqlDateTime dt;
      TimeToStruct(start_time-1,dt);
      tS=dt.year*12+dt.mon;
     }
   if(stop_time<=LastBAR)
     {
      if(timeframe<PERIOD_W1) tF=stop_time-(stop_time)%PerSec;
      else if(timeframe==PERIOD_W1) tF=stop_time-(stop_time+345600)%PerSec;
      else // PERIOD_MN1
        {
         MqlDateTime dt0;
         TimeToStruct(stop_time-1,dt0);
         tF=dt0.year*12+dt0.mon;
        }
     }
   if(change || tS!=LastTime || tF!=LastTime0)
     { PreBars=Bars(symbol_name,timeframe,start_time,stop_time); LastTime=tS; LastTime0=tF; }
   flag=false;
   return(PreBars);
  }


int fBarShift(string symb,ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=fBars(symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==fBars(symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }
Dateien:
iBars.mqh  14 kb
 
Nikolai Semko:

Ab Build 1847 MT5 wurde der Fehler des Hängens in der Bars-Funktion behoben. Außerdem wurde die Standardfunktion iBarShift hinzugefügt.
Um die Leistung dieser Funktionen zu erhöhen (irgendwo im Bereich von 10) , ist es jetzt besser, diese Codevariante zu verwenden:

Senden Sie den Code an servicedesk, damit sie ihn als Standard in die Plattform implementieren

 
Vitaly Muzichenko:

Senden Sie den Code an servicedesk und lassen Sie ihn als Standard in die Plattform implementieren.

Wer bin ich, dass ich es ihnen sage.
Dieser Code ist plattformübergreifend. Und das Interessanteste ist, dass es keinen Gewinn auf MT4 gibt, so dass die Bars-Funktion optimal in MT4 geschrieben ist.

 
Nikolai Semko:

Wer bin ich, es ihnen zu sagen.
Dieser Code ist plattformübergreifend. Und das Interessante ist, dass es keinen Gewinn auf MT4, so dass die Bars-Funktion ist optimal in MT4 geschrieben.

Dieser Thread wird verfolgt. Fügen Sie über Tasche Ihren Beitrag.

Альтернативные реализации стандартных функций/подходов
Альтернативные реализации стандартных функций/подходов
  • 2016.09.01
  • www.mql5.com
NormalizeDouble Результат 1123275 и 1666643 в пользу MyNormalizeDouble (Optimize=1). Без оптимизации - быстрее раза в четыре (на память...
 
fxsaber:

Dieser Thread wird überwacht. Fügen Sie Ihren Beitrag durch Ihre Tasche ein.

Das geht. Aber aus irgendeinem Grund funktioniert es nicht durch die Tasche. Es klappt nicht. Es geht über den Link.

 
Nikolai Semko:

Um die Geschwindigkeit dieser Funktionen zu erhöhen (irgendwo im Bereich des 10-fachen), ist es daher besser, diese Codevariante zu verwenden:

Sind Sie nicht ein bisschen voreilig, was die Geschwindigkeit angeht? Vor allem, wenn man bedenkt, wie viele verschiedene Prüfungen in Ihrem Code enthalten sind. Ich bin zu faul, um auf das Wesentliche einzugehen, aber es fällt mir schwer zu glauben, dass ein solches Durcheinander schnell funktioniert.

 
Alexey Navoykov:

Übertreiben Sie es nicht mit der Geschwindigkeit? Vor allem, wenn man bedenkt, wie viele Prüfungen in Ihrem Code enthalten sind. Ich bin zu faul, um auf das Wesentliche einzugehen, aber es fällt mir schwer zu glauben, dass ein solches Chaos schnell funktioniert.

Sie sollten besser zu faul sein, diese Nachricht zu schreiben. ))

Für den Geschwindigkeitstest habe ich extra einen Indikator an diese Funktionen angehängt.

Die Funktion Bars wird in Mikrosekunden ausgeführt, und Prüfungen, arithmetische Operationen(sogar die Berechnung der Quadratwurzel aus einer Binärzahl) in weniger als einer Nanosekunde:

void OnStart()
  {
   ulong t;
   double sum=0;
   t=GetMicrosecondCount();
   for (double i=1; i<2;i+=0.000001 ) sum+=sqrt(i);
   t=GetMicrosecondCount()-t;
   Print("Summe von 1.000.000 Wurzeln = " + DoubleToString(sum,18)+ " für " + IntegerToString((int)t) + "Mikrosekunden".); 
  }


2018.06.14 19:23:31.188 SpeedSQRT (EURUSD,M4)   Сумма 1 000 000 корней = 1218952.6235881459433586 за 1990 микросекунд
2018.06.14 19:26:30.814 SpeedSQRT (EURUSD,M4)   Сумма 1 000 000 корней = 1218952.6235881459433586 за 1946 микросекунд
2018.06.14 19:26:34.188 SpeedSQRT (EURUSD,M4)   Сумма 1 000 000 корней = 1218952.6235881459433586 за 1946 микросекунд
2018.06.14 19:26:36.344 SpeedSQRT (EURUSD,M4)   Сумма 1 000 000 корней = 1218952.6235881459433586 за 1973 микросекунд

Aus diesem Geschwindigkeitstest können wir ersehen, dass 1 Million Zyklen zur Berechnung von Summen von Wurzeln aus Binärzahlen in 2000 Mikrosekunden ausgeführt werden.
Ein Zyklus wird also in 2 Nanosekunden ausgeführt. Ein Zyklus ist 1 Prüfung, zwei Summen von Binärzahlen, eine Berechnung der Quadratwurzel einer Binärzahl.

Dateien:
 
Nikolai Semko:

Ich hoffe, Sie sind zu faul, diesen Beitrag zu schreiben. ))

Ich habe eigens einen Geschwindigkeitstest-Indikator an diese Funktionen angehängt.

Die Funktion "Balken" wird in Mikrosekunden ausgeführt, während Prüfungen und arithmetische Operationen(sogar die Berechnung der Quadratwurzel einer Binärzahl) weniger als eine Nanosekunde dauern:

Anhand dieses Geschwindigkeitstests können wir sehen, dass 1 Million Zyklen zur Berechnung von Summen von Wurzeln aus Binärzahlen in 2000 Mikrosekunden ausgeführt werden.
Ein Zyklus wird also in 2 Nanosekunden ausgeführt. Ein Zyklus ist 1 Prüfung, zwei Summen von Binärzahlen, eine Berechnung der Quadratwurzel aus einer Binärzahl.

Ich habe noch keine neuen Builds aufgespielt, daher kann ich es nicht reproduzieren. Ich gehe davon aus, dass Ihre Funktion für einen Sonderfall optimiert ist, der in Ihrem Indikator dargestellt ist. Das Symbol ändert sich nicht, der Zeitrahmen ändert sich auch nicht usw. Deshalb wird die Funktion Bars dort wohl einmal aufgerufen. Und sowohl das Symbol als auch der Zeitrahmen sind dummerweise als Konstanten gesetzt. Deshalb ist es gut möglich, dass der Compiler Ihre gesamte Funktion optimiert hat und alles Unnötige rausgeschmissen hat.

Kurz gesagt, die Tests sind falsch. Es sollte ein Array mit Symbolen und ein Array mit Zeiträumen geben, und Sie sollten Ihre Funktion über alle diese Arrays laufen lassen. Dann können wir über etwas reden.

 
Alexey Navoykov:

Ich habe noch keine neuen Builds installiert, daher kann ich es nicht reproduzieren. Ich gehe davon aus, dass Ihre Funktion für einen speziellen Fall optimiert ist, der in Ihrem Indikator dargestellt ist. Das Symbol ändert sich nicht, der Zeitrahmen ändert sich auch nicht usw. Daher nehme ich an, dass die Funktion Bars nur einmal aufgerufen wird. Und sowohl das Symbol als auch der Zeitrahmen sind dummerweise als Konstanten gesetzt. Daher ist es gut möglich, dass der Compiler Ihre gesamte Funktion optimiert hat und alles Unnötige weggeworfen hat.

Kurz gesagt, die Tests werden falsch durchgeführt. Es sollte ein Array von Zeichen und ein Array von Zeiträumen geben. Sie sollten Ihre Funktion durch alle laufen lassen. Dann können wir über etwas reden.

Nichts von alledem ist ein Sonderfall: "Das Symbol ändert sich nicht, der Zeitrahmen ändert sich auch nicht"!

Warum - haben Sie viele solcher Indikatoren oder Expert Advisors, die ständig TF und Symbole ändern?
Sie haben natürlich recht. Wenn jeder Aufruf von Bars von einer Änderung des TF oder des Symbols begleitet wird, dann wird der Standard schneller arbeiten. Allerdings muss man in diesem Fall die statischen Variablen durch ein Array statischer Variablen ersetzen, das so groß ist wie die Anzahl der TFs. Aber ich betrachte dies als einen Sonderfall. Aber die Lösung dieses Sonderfalls hat eine Daseinsberechtigung, wenn sie notwendig ist. Vielleicht ist es sinnvoll, den Code für solche Fälle zu ändern. А ... Das ist wahrscheinlich das, was du gemeint hast.

Und zu den Konstanten - danke für den Hinweis. Ich habe es korrigiert, weil die Parameter in der ursprünglichen Funktion keine Konstanten sind. In Bezug auf die Geschwindigkeit hat sich nichts geändert.

 
Nikolai Semko:

Haben Sie eine Menge solcher Indikatoren oder Expert Advisors, die ständig TFs und Symbole ändern?

Nun, ja, ziemlich viele. Ich konzentriere mich auf die Portfolioanalyse und den Portfoliohandel. Wenn es jedoch um große Berechnungen geht, ist iBarShift dort unangebracht, weil wir mit Arrays arbeiten. Tatsächlich sind iBarShift und andere ähnliche Funktionen für seltene Aufrufe gedacht.Es ist irrational, sie in einer Schleife aufzurufen. Wir holen uns einfach das Array in CopyTime und finden schnell alles. Deshalb ist das Testbeispiel in der Praxis wenig hilfreich. Es sei denn, der Programmierer ist ein Dummie ) und ich denke nicht, dass wir uns die Mühe machen sollten, um Dummies zu unterstützen ).

Ich denke, es wäre logischer, Ihre Funktion in eine Klasse zu packen. Dann müssen Sie nicht bei jedem Aufruf das Symbol/die Periode überprüfen. Sie haben dann für jede Zeitreihe ein eigenes Objekt.