El problema de la transferencia de MT4 a MT5. O, más precisamente, la incapacidad de ejecutar algunos algoritmos en MT5 sin'err. - página 10

 
Vict:

Es extraño, pero no se me había ocurrido hacerlo antes:

Se desharía de una masa de comprobaciones de errores, como la asignación de memoria.

no es una opción, el EA se eliminará del gráfico, y sólo hay que "salir al SO" antes del siguiente tick desde cualquier lugar del programa


Lo más probable es que se pueda envolver elegantemente todo en una macro, para llamar de forma segura a las funciones relacionadas con la falta de disponibilidad de datos en el tick actual, aquí hay un "dummy"

void OnStart()
  {
   for(int i=0;i<10;i++)
     {
      double o=Open(i);
      if(o>0.0) printf("%d : %f",i,o);
      else
        {
         printf("Error № %d ",(int)o);
         return;
        }
     }
  }
//+------------------------------------------------------------------+

double Open(int shift)
  {
   ResetLastError();
   double result=iOpen(NULL,0,shift);
   int err=GetLastError();
   if(err>0) result=-err;
   return(result);
  }
//+------------------------------------------------------------------+

para la legibilidad del código sería bueno escribirlo así:

void OnStart()
  {
   for(int i=0;i<10;i++)
     {
      double o=Try( Open(i),"Текст сообщения" );
      printf("%d : %f",i,o);
     }
  }


¿Es realista tratar de envolver una macro y "salir al sistema operativo" en caso de fallo?

 
Igor Makanu:

¿es realista envolver este Try en una macro y "salir al SO" en caso de fallo?

#define  Try(VAR, EXPR, MES)          \
   VAR = EXPR;                       \
   if (VAR <= 0.0) {                 \
     printf("Error: %s ", MES);      \
     return;                         \
   }

double o;
Try(o, Open(i), "something goes wrong");

¿No?

A menudo escribo todo tipo de mínimos al principio de una función, con undefine al final. Naturalmente, si la acción se repite a menudo, de lo contrario no tiene sentido.

#define  MYERR_HANDLER(INDEX)                                \
{                                                           \
   Alert(__FILE__, " ", __LINE__, "-", INDEX, ": error");   \
   this.state = obst_error;                                 \
   return obev_no_event;                                    \
}

Y te equivocas con el aborto, es perfecto con algunos errores.

 
Vict:

¿No?

¡Sí!

pero lo ideal sería que lo quisiera en su lugar:

double o;
Try(o, Open(i), "something goes wrong");

así:

double o = Try(Open(i), "something goes wrong");

no es cuestión de hacer la firma de la función Open() diferente... Pero de esta forma conseguiré lo que realmente me gustaría. ;)

----------------------

PD: como opción incluso las variables descritas globalmente Tryerror o bool Tryresultar harían - el propósito de una línea "llamada segura", si esta llamada terminó con una salida de error del cuerpo OnTick()

 
Igor Makanu:

así:

Dudo que sea posible, incluso en los pluses (puedes lanzar una excepción, pero es poco probable). Pero las cosas suceden, tal vez alguien sorprenda ...

 

Así que, de un vistazo rápido:

Try(double, o, Open(i), "something goes wrong");

que es probablemente el máximo en esta situación.

 

Totalmente tonto, puedes hacerlo, ¿no?

double Try_helper;
#define  Try(EXPR, MES)               \
   Try_helper = EXPR;                \
   if (Try_helper <= 0.0) {          \
     printf("Error: %s ", MES);      \
     return;                         \
   }

double o = Try(Open(i), "something goes wrong");

No lo he compilado, pero debería funcionar.

 
Vict:

Soy tan estúpido que no puedo evitarlo, ¿verdad?

No lo he compilado, pero debería funcionar.

¡¡¡Shaitan la máquina!!! ¡Funcionó!

error comprobado y simulado ( shift>5 )

double Try_helper;
#define  Try(EXPR, MES)               \
   Try_helper = EXPR;                \
   if (Try_helper <= 0.0) {          \
     printf("Error: %s ", MES);      \
     return;                         \
   }

void OnStart()
  {
   for(int i=0;i<10;i++)
     {
      
      double o = Try(Open(i), "something goes wrong");
      printf("%d : %f",i,o);
     }
  }
//+------------------------------------------------------------------+

double Open(int shift)
  {
   ResetLastError();
   double result=iOpen(NULL,0,shift);
   int err=GetLastError()>0;
   if(err>0) result=-err;
   if(shift>5) result = -999;
   return(result);
  }
//+------------------------------------------------------------------+

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 0 : 1.115010

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 1 : 1.114670

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 2 : 1.114590

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 3 : 1.114400

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 4 : 1.115240

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) 5 : 1.115450

2019.07.31 16:58:48.154 tst1 (EURUSD,H1) Error: algo va mal


¡Impresionante! Y el código de la macro resultó ser realmente sencillo


¡GRACIAS! - Definitivamente eres un mago).

 

Por favor, siéntase libre de usarlo.

La macro anterior tiene una desventaja - el tipo de helper está codificado, no se puede pasar a la función Try que devuelve la cadena y luego el doble sin crear dos macros. Tengo un interés deportivo: cómo evitarlo (escribir una macro para todos los tipos. En µl sin opciones, en c++, aunque no es realmente necesario allí, pero aún así)? ¿Nadie está dispuesto a sugerir su propia variante (bueno, hay que mantenerse en forma, después de todo)?

 
Vict:

Puede utilizarlo.

La macro anterior tiene una desventaja: el tipo helper es rígido, no se puede pasar una función que devuelva una cadena a Try

¿Por qué no? ¡El signo + nunca ha sido cancelado!

así es como he peinado su macro, y como pienso utilizarla:

int    _GetLastError;
double _Try_helper;
string _Try_FUNCSIG;
#define  Try(FUNC,MSG, EXCEPT) _Try_helper=FUNC;if(_GetLastError>0){printf("%s : error № %d %s ",_Try_FUNCSIG,_GetLastError,MSG);EXCEPT;}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   for(int i=0;i<10;i++)
     {

      double o = Try(Open(i), "something goes wrong"+Txt(),return);
      printf("%d : %f",i,o);
     }
  }
//+------------------------------------------------------------------+

double Open(int shift)
  {
   _Try_FUNCSIG=__FUNCSIG__;
   ResetLastError();
   double result=iOpen(NULL,0,shift);
   _GetLastError=GetLastError();
   if(shift>5)_GetLastError=999;
   return(result);
  }
//+------------------------------------------------------------------+
string Txt()
{
return(" Txt ");

ahora el parámetro de la macroEXCEPT es una acción de excepción, funciona bien como return o simplemente ; - si decides no imprimir en el registro, pero no dejes el cuerpo de OnTick()

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 0 : 1.113350

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 1 : 1.114180

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 2 : 1.115110

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 3 : 1.115010

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 4 : 1.114670

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) 5 : 1.114590

2019.07.31 19:01:28.353 tst1 (EURUSD,H1) double Open(int) : error #999 algo va mal Txt

 
Igor Makanu:

Bueno, es decir, es así:

string f(int) {return "hello world";}
double f(double) {return 35;}

int main()
{
   double d = Try(f(0.), "double error");
   string s = Try(f(0), "stirng error");
   cout << s << "-" << d << endl;  // hello world-35
   return 0;
}

La gente aquí no parece apostar. Oh, vamos.

template <typename T> T Try_helper;
#define  Try(EXPR, MES)                                  \
   Try_helper<decltype(EXPR)> = EXPR;                   \
   if (Try_helper<decltype(EXPR)> == decltype(EXPR){}) {\
      printf("%s\n", MES);                              \
      return 1;                                         \
   }