O problema da transferência do MT4 para o MT5. Ou, mais precisamente, a incapacidade de executar alguns algoritmos no MT5 sem errar. - página 10

 
Vict:

É estranho, mas eu não pensei em fazer isso antes:

Ele se livraria de alguma massa de verificações de erros, como alocação de memória.

não uma opção, a EA será removida do gráfico, e você só precisará "sair para OS" antes do próximo tick de qualquer lugar no programa


Muito provavelmente, é possível envolver tudo elegantemente em uma macro, para chamar com segurança funções relacionadas à indisponibilidade de dados no tick atual, aqui está um "boneco".

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 a legibilidade do código, seria bom simplesmente escrevê-lo dessa maneira:

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


Isto é Tenta ser realisticamente envolto em uma macro e "saída para OS" em caso de falha?

 
Igor Makanu:

é realista embrulhar esta tentativa em uma macro e "saída para OS" em caso de falha?

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

Não?

Muitas vezes escrevo todos os tipos de minimáximos logo no início de uma função, com indefinição no final. Naturalmente, se a ação se repete com freqüência, caso contrário, não faz sentido.

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

E você está errado sobre o aborto, para alguns erros ele é perfeito.

 
Vict:

Não?

Sim!

mas o ideal seria que, em vez disso, eu gostasse:

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

assim:

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

não é uma questão de fazer a assinatura da função Open() diferente... Mas nesta forma eu vou conseguir o que realmente gostaria! ;)

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

PS: como uma opção mesmo as variáveis descritas globalmente Tryerror ou bool Tryresult fariam - o propósito de uma linha "chamada segura", se esta chamada terminasse com uma saída de erro do corpo OnTick()

 
Igor Makanu:

assim:

Duvido que seja possível, mesmo nos pontos positivos (pode-se abrir uma exceção, mas é improvável). Mas as coisas acontecem, talvez alguém surpreenda ...

 

Portanto, com uma rápida olhada:

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

que é provavelmente o máximo nesta situação.

 

Totalmente burro, você pode fazer isso, não pode?

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

Ainda não o compilei, mas deve funcionar.

 
Vict:

Sou tão estúpido, não posso evitar, não é mesmo?

Eu não a compilei, mas deve funcionar.

Shaitan, a máquina!!! Funcionou!!!

erro verificado e 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) Erro: algo dá errado


E o código macro acabou por ser muito simples.


OBRIGADO! - Você é definitivamente um mágico!)

 

Por favor, sinta-se livre para usá-lo.

A macro acima tem uma desvantagem - o tipo de helper é hardcoded, você não pode passar para tentar função de retorno de corda e depois dobrar sem criar duas macros. Tenho um interesse esportivo - como contorná-lo (para escrever uma macro para todos os tipos). Em µl sem opções, em c++, embora não seja realmente necessário lá, mas ainda assim)? Ninguém está disposto a sugerir sua própria variante (bem, você tem que se manter em forma, afinal de contas)?

 
Vict:

Você é bem-vindo a usá-lo.

A macro acima tem uma desvantagem - o tipo de ajudante é por fios, você não pode passar uma função que retorna uma corda em Try

Por que não? O sinal + não foi cancelado!

é assim que eu combino sua macro e como eu planejo usá-la:

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

agora o parâmetro macroEXCEPTO é uma ação de exceção, funciona bem como retorno ou apenas; - se você decidir desimprimir para registrar, mas não deixe o corpo 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) duplo Aberto(int) : erro #999 algo dá errado Txt

 
Igor Makanu:

Bem, quer dizer, é assim:

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

As pessoas aqui não parecem estar jogando. Ah, vamos lá.

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