Il problema del trasferimento da MT4 a MT5. O, più precisamente, l'impossibilità di eseguire alcuni algoritmi in MT5 senza 'err. - pagina 10

 
Vict:

È strano, ma non avevo pensato di farlo prima:

Si sbarazzerebbe di alcuni controlli di massa degli errori, come l'allocazione della memoria.

non è un'opzione, l'EA sarà rimosso dal grafico, ed è sufficiente "uscire su OS" prima del prossimo tick da qualsiasi punto del programma


Molto probabilmente, è possibile avvolgere elegantemente tutto in una macro, per chiamare in modo sicuro le funzioni relative all'indisponibilità dei dati sul tick corrente, ecco 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);
  }
//+------------------------------------------------------------------+

per la leggibilità del codice sarebbe bello scriverlo in questo modo:

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


Questo Try è realisticamente avvolto in una macro e "exit to OS" in caso di fallimento?

 
Igor Makanu:

è realistico avvolgere questo Try in una macro e "uscire al SO" in caso di fallimento?

#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?

Spesso scrivo ogni sorta di minimax all'inizio di una funzione, con undefine alla fine. Naturalmente, se l'azione si ripete spesso, altrimenti non ha senso.

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

E ti sbagli sull'aborto, per alcuni errori è perfetto.

 
Vict:

No?

Sì!

ma idealmente mi piacerebbe invece:

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

come questo:

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

non si tratta di rendere diversa la firma della funzione Open()... Ma in questa forma otterrò quello che vorrei davvero! ;)

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

PS: come opzione anche le variabili globalmente descritte Tryerror o bool Tryresult andrebbero bene - lo scopo di una linea "chiamata sicura", se questa chiamata finisce con un errore uscire dal corpo OnTick()

 
Igor Makanu:

come questo:

Dubito che sia possibile, anche nei plus (si può lanciare un'eccezione, ma è improbabile). Ma le cose accadono, forse qualcuno sorprenderà ...

 

Quindi, ad una rapida occhiata:

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

che è probabilmente il massimo in questa situazione.

 

Totalmente stupido, puoi farlo, vero?

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

Non l'ho compilato, ma dovrebbe funzionare.

 
Vict:

Sono così stupido che non posso farci niente, vero?

Non l'ho compilato, ma dovrebbe funzionare.

Shaitan la macchina!!! Ha funzionato!!!

errore controllato e simulato ( 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: something goes wrong


Fantastico! E il codice della macro si è rivelato davvero semplice


GRAZIE! - Sei sicuramente un mago)!

 

Sentitevi liberi di usarlo.

La macro di cui sopra ha uno svantaggio - il tipo di helper è hardcoded, non si può passare alla funzione Try che restituisce la stringa e poi il doppio senza creare due macro. Ho un interesse sportivo - come aggirarlo (scrivere una macro per tutti i tipi. In µl senza opzioni, in c++, anche se non è veramente necessario lì, ma comunque)? Nessuno è disposto a suggerire la propria variante (beh, bisogna tenersi in forma, dopo tutto)?

 
Vict:

Siete i benvenuti ad usarlo.

La macro di cui sopra ha uno svantaggio: il tipo helper è cablato, non si può passare una funzione che restituisce una stringa in Try

Perché no, il segno + non è stato cancellato!

Ecco come ho pettinato la tua macro e come ho intenzione di usarla:

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

ora il parametro macroEXCEPT è un'azione di eccezione, funziona bene come ritorno o solo ; - se si decide di non stampare nel log, ma non lasciare il corpo di 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 something goes wrong Txt

 
Igor Makanu:

Beh, voglio dire, è così:

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

Qui la gente non sembra giocare d'azzardo. Oh, ma dai!

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