Analogue à iBarShift - page 12

 
Nikolai Semko :

Vous avez dit que tout devrait fonctionner dans MQL4.

Mais ce script peut aussi être exécuté dans MQL5

Avec exact=True et le temps futur vous devriez retourner -1

Mon script a également trouvé une erreur étrange :

Cette erreur est confirmée par ce contrôle :

J'avais donc raison sur l'existence de situations anormales dans votre algorithme après tout.

C'est bien que vous ayez enfin trouvé l'erreur.

Je vais vérifier, merci.

 

Bonsoir à tous. Peut-être ai-je mal compris quelque chose, mais tout de même - on ne voit pas très bien ce qui ne va pas avec la fonction standard, qui a déjà été suggérée au début de Bars(). Je l'ai utilisé tout le temps et il n'a pas causé de problèmes. La seule chose est que vous pouvez rencontrer "array out of range" ou une valeur négative lorsque vous utilisez TimeCurrent(), mais vous devez alors faire une vérification pour cela. Exemples :

//найти бар на котором продали
Bar_sell_H4=Bars(Symbol(),PERIOD_H4,P_opentime,32000000000)-1;
if(Bar_sell_H4<=0)
   {
      Bar_time_sell_H4=Time_H4[0];
   }
else
   {
      Bar_time_sell_H4=Time_H4[Bar_sell_H4];
   }
Bars_forsearch_highfr_H1=Bars(Symbol(),PERIOD_H1,TimeCurrent(),Time_M15[B_DownTrend_M15_int]);
if(Bars_forsearch_highfr_H1<=0)
   {
      high_H1_int=0;
   }
else
   {
      high_H1_int=ArrayMaximum(High_H1,0,Bars_forsearch_highfr_H1);
   }
 
Almat Kaldybay:

Bonsoir à tous. Peut-être ai-je mal compris quelque chose, mais tout de même - on ne voit pas très bien ce qui ne va pas avec la fonction standard, qui a déjà été suggérée au début de Bars(). Je l'ai utilisé tout le temps et il n'a pas causé de problèmes. La seule chose est que vous pouvez rencontrer "array out of range" ou une valeur négative lorsque vous utilisez TimeCurrent(), mais vous devez alors faire une vérification pour cela. Exemples :

A en juger par le nombre 32000000000, c'est aussi ma création. UINT_MAX est simplement plus court et plus solide. ))

Le fait est que cette variante est plus correcte, comme il s'avère :

Bars(Symb,TimeFrame,time+1,UINT_MAX);

plutôt que

Bars(Symb,TimeFrame,time,UINT_MAX)-1;

il n'y a pratiquement aucune différence extérieure. Mais la variante supérieure répète très précisément la fonction standard iBarShift de MQL4

 
Nikolai Semko:

A en juger par le nombre 32000000000, c'est aussi ma création. UINT_MAX semble simplement plus court et plus solide. ))

Le fait est que cette variante est plus correcte, comme il s'avère :

plutôt que

il n'y a pratiquement aucune différence extérieure. Mais la variante supérieure répète très précisément la fonction standard iBarShift de MQL4.

Alors, quel est le plus facile et le bon ?

 
Vitaly Muzichenko:

Alors, quelle est la chose la plus facile et la plus juste à faire ?

Jusqu'à présent cette variante, mais maintenant je veux la compléter pour contourner le bug du gel de la fonction Bars, dont j'ai déjà fait part au Service Desk.

L'essence de ce bogue est que si, dans la fonction Bars, l'heure de début et l'heure de fin sont toutes deux à l'intérieur d'une barre ou sont dans le futur (à droite de la barre zéro), alors cette fonction se bloque pendant plus de 10 secondes.

Peut-être que je ferai une version plus rapide mais plus encombrante plus tard.

 

J'ai décidé de suivre une autre voie.
Je ne vais pas refaire iBarShift, mais je vais refaire la fonction Bars qui est défaillante.

Et la nouvelle fonction iBars ne se contentera pas de contourner le bogue du hoquet, elle sera également plus rapide que les barres originales.

D'autres pourront utiliser cette fonction et les algorithmes déjà en place fonctionneront plus rapidement.

J'ai juste besoin de temps. Je ne pourrai le faire qu'un jour plus tard.

 
Nikolai Semko:

J'ai décidé de prendre un autre chemin.
Je ne vais pas refaire iBarShift, mais je vais refaire la fonction Bars qui est défaillante.

Et la nouvelle fonction iBars ne se contentera pas de contourner le bogue du hoquet, elle sera également plus rapide que les barres originales.

D'autres pourront utiliser cette fonction et les algorithmes déjà en place fonctionneront plus rapidement.

J'ai juste besoin de temps. Je ne pourrai pas le faire avant un jour.

Très bien ! J'ai hâte d'y être !

 
Nikolai Semko:

De toute l'analyse que j'ai faite, nous pouvons conclure que cet analogue complet de l'iBarShift :

int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=Bars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==Bars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }

est de loin la plus correcte, et en même temps la plus rapide, avec l'algorithme le plus simple et le plus court.

C'est joli, mais quelque chose me perturbe...

il faudra le tester)

 

La fonction iBars est assez lourde, mais je recommande tout de même de l'utiliser à la place des Bars normales, jusqu'à ce que MQ corrige le bogue qui la bloque.

L'iBar se bloque alors que logiquement elle devrait retourner 0. En règle générale, il le renvoie pendant plus de 10 secondes. Il n'y a pas de tel bogue dans MQL4.

Dans la majorité des tâches, iBars fonctionnera plus rapidement que les barres normales, car non seulement il évitera le bogue, mais il essaiera de ne pas utiliser les fonctions Bars et SeriesInfoInteger chaque fois que possible, en raison de l'algorithme de sauvegarde des valeurs précédentes.

int iBars(string symbol_name,ENUM_TIMEFRAMES  timeframe,datetime start_time,datetime stop_time) // stop_time > start_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;
   datetime TimeCur;
   if(stop_time<start_time) {TimeCur=stop_time; stop_time=start_time; start_time=TimeCur; }
   TimeCur=TimeCurrent();
   if(start_time>TimeCur) {LastSymb=NULL; return(0);}
   if(LastTimeFrame!=timeframe) if(timeframe==PERIOD_MN1) PerSec =2419200; else PerSec=::PeriodSeconds(timeframe);
   if(LastTimeFrame!=timeframe || LastSymb!=symbol_name || ((TimeCur-LastBAR)>=PerSec && TimeCur!=LastTimeCur))
      LastBAR=(datetime)SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE);

   LastTimeCur=TimeCur;
   if(PerSec==0) return(0);
   if(start_time>LastBAR)
     {LastTimeFrame=timeframe; LastSymb=symbol_name; return(0);}

   datetime t,t0=0;
   bool check=true;
   if(timeframe<PERIOD_W1) t=start_time-(start_time-1)%PerSec;
   else if(timeframe==PERIOD_W1) t=start_time-(start_time-259201)%PerSec;
   else
     {
      PerSec=2678400;
      MqlDateTime dt;
      TimeToStruct(start_time-1,dt);
      t=dt.year*12+dt.mon;
     }
   if(stop_time<=LastBAR)
     {
      if(timeframe<PERIOD_W1) t0=stop_time-(stop_time)%PerSec;
      else if(timeframe==PERIOD_W1) t0=stop_time-(stop_time-259200)%PerSec;
      else
        {
         MqlDateTime dt0;
         TimeToStruct(stop_time,dt0);
         t0=dt0.year*12+dt0.mon;
        }
      if(t0==t) {PreBars=0; check=false;}
     }
   if((LastTimeFrame!=timeframe || LastSymb!=symbol_name || t!=LastTime || t0!=LastTime0) && check)
      PreBars=Bars(symbol_name,timeframe,start_time,stop_time);
   LastTime=t; LastTime0=t0;
   LastTimeFrame=timeframe;
   LastSymb=symbol_name;
   return(PreBars);
  }

J'ai testé cette fonction à la hausse et à la baisse. Il semble que ce soit une copie intégrale de Bars.

Peut-être peut-on le faire d'une manière plus élégante. Si vous en avez envie, vous êtes les bienvenus. Si vous trouvez des erreurs, nous les corrigerons.

Alors...

L'analogue complet de la fonction iBarsShift aura alors la forme suivante :

int iBarShift(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   int Res=iBars(Symb,TimeFrame,time+1,UINT_MAX);
   if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==iBars(Symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1);
   return(Res);
  }

Et la variante sans dernier paramètre, qui est utilisée dans la grande majorité des cas, aura cette forme :

int iBarShift1(const string Symb,const ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false)
  {
   return(iBars(Symb,TimeFrame,time+1,UINT_MAX));
  }
// ИЛИ БОЛЕЕ СОКРАЩЕННЫЙ БЕЗ ФУНКЦИИ:

iBars(Symb,TimeFrame,time+1,UINT_MAX);
 

Indicateur montrant les performances de la fonction iBars par rapport aux barres intégrées et à la fonction iBarShift de @Alain Verleyen
Temps d'exécution de la fonction en microsecondes.


Dossiers :