Análogo a iBarShift - página 12

 
Nikolai Semko :

Has dicho que todo debería funcionar en MQL4.

Pero este script también se puede ejecutar en MQL5

Con exact=True y tiempo futuro debería devolver -1

Mi script también encontró un extraño error:

Este error se confirma con esta comprobación:

Así que tenía razón sobre la existencia de situaciones anormales en su algoritmo después de todo.

Es bueno que finalmente hayas encontrado el error

Lo comprobaré, gracias.

 

Buenas noches a todos. Tal vez esté malinterpretando algo, pero aun así, no está muy claro qué es lo que falla en la función estándar, que ya se ha sugerido al principio de Bars(). Lo he usado siempre y no me ha causado ningún problema. Lo único es que puedes encontrarte con un "array fuera de rango" o un valor negativo cuando uses TimeCurrent(), pero entonces tienes que hacer una comprobación para ello. Ejemplos:

//найти бар на котором продали
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:

Buenas noches a todos. Tal vez esté malinterpretando algo, pero aun así, no está muy claro qué es lo que falla en la función estándar, que ya se ha sugerido al principio de Bars(). Lo he usado siempre y no ha causado ningún problema. Lo único es que puedes encontrarte con un "array fuera de rango" o un valor negativo cuando uses TimeCurrent(), pero entonces tienes que hacer una comprobación para ello. Ejemplos:

A juzgar por el número 32000000000 esta también es mi creación. UINT_MAX es simplemente más corto y tiene un aspecto más sólido. ))

La cuestión es que esta variante es más correcta, como resulta:

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

en lugar de

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

no hay casi ninguna diferencia externa. Pero la variante superior repite con mucha precisión la función estándar iBarShift de MQL4

 
Nikolai Semko:

A juzgar por el número 32000000000, esta también es mi creación. UINT_MAX simplemente parece más corto y más sólido. ))

La cuestión es que esta variante es más correcta, como resulta:

en lugar de

no hay casi ninguna diferencia externa. Pero la variante superior repite con mucha precisión la función estándar iBarShift de MQL4.

Entonces, ¿cuál es la más fácil y la correcta?

 
Vitaly Muzichenko:

Entonces, ¿qué es lo más fácil y lo que hay que hacer?

Hasta aquí esta variante, pero ahora quiero complementarla para evitar el error de congelación de la función de Bares, sobre el que ya he informado al Service Desk.

La esencia de este error es que si en la función Bars tantostart_time comostop_time están dentro de una barra o están en el futuro (a la derecha de la barra cero), entonces esta función se cuelga durante más de 10 segundos.

Quizá más adelante haga una versión adecuada más rápida pero más engorrosa.

 

He decidido tomar un camino diferente.
No voy a rehacer el iBarShift, pero sí la función de Bares con fallos.

Y la nueva función iBars no sólo evitará el error de hipo, sino que también será más rápida que la Bars original.

Otros podrán utilizar esta función y los algoritmos ya existentes funcionarán más rápidamente.

Sólo necesito tiempo. No podré hacerlo hasta un día después.

 
Nikolai Semko:

He decidido tomar un camino diferente.
No voy a rehacer el iBarShift, pero sí la función de Bares con fallos.

Y la nueva función iBars no sólo evitará el error de hipo, sino que también será más rápida que la Bars original.

Otros podrán utilizar esta función y los algoritmos ya existentes funcionarán más rápidamente.

Sólo necesito tiempo. No podrá hacerlo antes de un día.

¡Muy bien! Estoy deseando que llegue.

 
Nikolai Semko:

De todo el análisis que he hecho, podemos concluir que este análogo completo del 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);
  }

es, con mucho, la más correcta y, al mismo tiempo, la más rápida y con el algoritmo más sencillo y corto.

Es bonito, pero algo me confunde...

tendrá que probarlo )

 

La función iBars es bastante engorrosa, pero sigo recomendando su uso en lugar de las Barras normales, hasta que MQ solucione el error de cuelgue que tiene.

El iBar se cuelga cuando lógicamente debería devolver 0. Por regla general, lo devuelve durante más de 10 segundos. En MQL4 no existe este error.

En la mayoría de las tareas, iBars funcionará más rápido que el Bars normal, ya que no sólo evitará el error, sino que intentará no utilizar las funciones Bars y SeriesInfoInteger siempre que sea posible debido al algoritmo de guardado de valores anteriores.

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

He probado esta función a fondo. Parece ser una copia completa de Bares.

Quizás se pueda hacer de una manera más elegante. Si tienes ganas, eres bienvenido. Si encuentra errores, los corregiremos.

Así que...

Entonces el análogo completo de la función iBarsShift tendrá la siguiente forma:

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

Y la variante sin último parámetro, que se utiliza en la gran mayoría de los casos tendrá esta forma:

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

Indicador que muestra el rendimiento de la función iBars en comparación con las Barras incorporadas y la función iBarShift de @Alain Verleyen
Tiempo de ejecución de la función en microsegundos.


Archivos adjuntos: