Especialistas: Diff_TF_MA_EA - página 2

 
fxsaber:

Na verdade, há mais erros no código. Por exemplo, está bem demonstrado que o uso do CSymbolInfo apenas por causa do estilo SB é ruim.

Fechar posições por meio de uma lista de tíquetes previamente coletada é ruim. Esse é um erro muito comum.

Acho que isso diz muita coisa:

Vale a pena entender que esse EA é para fins de treinamento.

Sobre o processamento de códigos de retorno do servidor. Pessoalmente, eu sempre os processo. Mas aqui - no testador (espero que você entenda que um EA de treinamento é feito para o testador e para melhorias posteriores por conta própria) - provavelmente não vale a pena processar todos os códigos de retorno necessários. Além disso, ter sempre seu próprio ambiente de negociação é bastante justificado tanto para a negociação real quanto para um testador.

Você pode ver o que está lá:

Primeiro, você preenche os dados sobre as posições existentes:

//--- Preenchimento de listas de tíquetes de posição
   int positions_total=PositionsTotal();
   if(prev_total!=positions_total)
     {
      FillingListTickets();
      prev_total=positions_total;
     }
   int num_b=NumberBuy();
   int num_s=NumberSell();

Em seguida, após verificar os sinais, a abertura (aqui a posição de compra é aberta):

      if(open_long)
        {
         if(num_s>0) CloseSell();
         if(num_b==0)
           {
            double sl=(InpStopLoss==0   ? 0 : CorrectStopLoss(ORDER_TYPE_BUY,InpStopLoss));
            double tp=(InpTakeProfit==0 ? 0 : CorrectTakeProfit(ORDER_TYPE_BUY,InpTakeProfit));
            double ll=trade.CheckVolume(symb,lot,symbol_info.Ask(),ORDER_TYPE_BUY);
            if(ll>0 && CheckLotForLimitAccount(POSITION_TYPE_BUY,ll))
              {
               if(trade.Buy(ll,symb,0,sl,tp))
                  FillingListTickets();
              }
           }
        }

Se o número de Sell for maior que zero - fechar. O Expert Advisor está oscilando - há sempre apenas uma posição. Portanto, não há posições de compra se houver posições de venda - não é necessário verificar o número delas aqui, bem como atualizar o ambiente de negociação nas matrizes internas do Expert Advisor.
Em seguida, ele verifica o número de posições de compra. Seu número pode ser maior que zero somente após a abertura. Mas após o fechamento da venda, o número de posições de compra é necessariamente igual a zero - um EA de swing. E não há necessidade de executar um loop procurando por algo que já é conhecido.

Em seguida, vêm as verificações mínimas de correção e a abertura de uma posição de compra. Imediatamente após retornar verdadeiro, as matrizes internas do ambiente de negociação do EA são atualizadas.

Tudo é lacônico e sem excessos. Corrija-me se eu não estiver vendo algo aqui.

 
fxsaber:

O erro está na entrada e na chamada do enum, não na distância mínima. Mas ela também é calculada incorretamente, porque


Não estou vendo isso. Mostre-me - é interessante.

 
Artyom Trishkin:

Acho que essa fala muito bem:

Vale a pena saber que esse EA é para fins de treinamento.

Sobre o processamento de códigos de retorno do servidor. Pessoalmente, eu sempre os processo. Aqui - no testador (espero que você entenda que um Expert Advisor de treinamento é feito para o testador e para suas modificações posteriores de forma independente) - provavelmente não é necessário processar todos os códigos de retorno necessários. Além disso, ter sempre seu próprio ambiente de negociação é bastante justificado tanto para a negociação real quanto para um testador.

Você não leu com atenção. Eu não queria nenhum código de retorno. CloseSell em tickets é um mal em si. O que um testador tem de fazer quando o código deve funcionar corretamente, pelo menos em uma demonstração, e não tem erros potenciais óbvios?

Deveria haver RefreshRates após CloseSell. Ele está ausente, portanto, haverá falhas até mesmo no testador se você ativar o modo de atraso. Usar uma bíblia padrão em nome do estilo SB é maléfico. E o código mostra isso muito bem.


Tendo feito apenas algumas alterações no SymbolInfo.mqh, consegui compilá-lo e usá-lo no MT4. Mas quem em sã consciência pode pensar nisso ao escrever algo em MQL4! Por que isso ocorre a muitas pessoas quando codificam em MQL5? Além de abranger muitos erros em potencial e levar tempo para aprender, também parece desajeitado.

 
fxsaber:

Você não leu com atenção. Eu não queria um código de retorno. O CloseSell em tíquetes é um mal em si. O que um testador tem de fazer quando o código deve funcionar corretamente, pelo menos em uma demonstração, e não tem erros potenciais óbvios?

Deveria haver RefreshRates após CloseSell. Ele está ausente, portanto, haverá falhas até mesmo no testador se você ativar o modo de atraso. Usar uma bíblia padrão em nome do estilo SB é maléfico. E o código mostra isso muito bem.

Após CloseSell(), há uma abertura de compra com preço zero:

      if(open_long)
        {
         if(num_s>0) CloseSell();
         if(num_b==0)
           {
            double sl=(InpStopLoss==0   ? 0 : CorrectStopLoss(ORDER_TYPE_BUY,InpStopLoss));
            double tp=(InpTakeProfit==0 ? 0 : CorrectTakeProfit(ORDER_TYPE_BUY,InpTakeProfit));
            double ll=trade.CheckVolume(symb,lot,symbol_info.Ask(),ORDER_TYPE_BUY);
            if(ll>0 && CheckLotForLimitAccount(POSITION_TYPE_BUY,ll))
              {
               if(trade.Buy(ll,symb,0,sl,tp))
                  FillingListTickets();
              }
           }
        }

Por que duas vezes RefreshRates()? Você já deu uma olhada no código de abertura do SB no CTrade? Eu dei:

//+------------------------------------------------------------------+
//| Operação de compra|
//+------------------------------------------------------------------+
bool CTrade::Buy(const double volume,const string symbol=NULL,double price=0.0,const double sl=0.0,const double tp=0.0,const string comment="")
  {
   CSymbolInfo sym;
//--- verificar o volume
   if(volume<=0.0)
     {
      m_result.retcode=TRADE_RETCODE_INVALID_VOLUME;
      return(false);
     }
//--- verificar símbolo
   sym.Name((symbol==NULL)?Symbol():symbol);
//--- verificar preço
   if(price==0.0)        
     {                   
      sym.RefreshRates();
      price=sym.Ask();   
     }                   
//---
   return(PositionOpen(sym.Name(),ORDER_TYPE_BUY,volume,price,sl,tp,comment));
  }
//+------------------------------------------------------------------+
 
Artyom Trishkin:

Após CloseSell(), a compra é aberta com um preço zero:

Por que RefreshRates() duas vezes?

Porque as funções corretas são chamadas.

Você deu uma olhada no código de abertura no CTrade?

Include\Trade\*.mqh Eu sempre observo/vigilo, porque você deve conhecer o inimigo de vista.

 
fxsaber:

Em seguida, as funções corretas são chamadas.

Include\Trade\*.mqh Eu sempre observo/vigilo, porque você deve conhecer o inimigo de vista.

Inimigo :))))

Sim, agora eu vi - nas funções corretas, o preço é lido a partir das variáveis m_tick do SB, que são preenchidas durante a atualização, e não diretamente por meio do SymbolInfoDouble() - essa não seria uma possível emboscada da qual você está falando. Além disso, não há muito código antes das funções corretas, e os preços são atualizados logo após a chegada do tique - logo no início de OnTick():

//--- Verificação de preços zero
   if(!RefreshRates()) return;
 
Artyom Trishkin:

Inimigo :)))))

Sim, agora eu vi - as funções corretas leem o preço das variáveis m_tick do SB, que são preenchidas durante a atualização, mas não diretamente por meio de SymbolInfoDouble() - esse não seria um possível problema do qual você está falando. Além disso, não há muito código antes das funções corretas, e os preços são atualizados imediatamente após a chegada do tique - logo no início de OnTick():

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação.

Expert Advisors: Diff_TF_MA_EA

fxsaber, 2018.02.01 22:10

Depois de fazer pouquíssimas alterações no SymbolInfo.mqh, acabei compilando-o e usando-o no MT4. Mas quem em sã consciência pode pensar nisso ao escrever algo em MQL4! Por que isso ocorre a muitas pessoas quando codificam em MQL5? Além de abranger muitos erros potenciais, levar tempo para aprender, também parece desajeitado.

Vou jogar uma pedra no jardim da MQL4. Bid/Ask com RefreshRates forçados é ruim. Mas há uma macro-construção maravilhosa que fornece um resultado conciso e sem erros.
 
fxsaber:
Vou jogar uma pedra no jardim da MQL4. Bid/Ask com RefreshRates forçados é ruim. Mas há uma macro-construção maravilhosa que oferece um resultado inconfundível e conciso.

Eu estava esperando que você selasse seu cavalo corcunda :)))))

É suficiente usar SymbolInfoDouble() nessas funções corretas para obter os preços necessários. No entanto, é isso que faço em minhas funções semelhantes. Aqui, o programador confiou em vão nos dados recebidos do objeto de símbolo - eles são fornecidos antigos - gravados em m_tick somente durante a atualização.

 
Artyom Trishkin:

Estou esperando que você sele seu cavalo corcunda :))))))

É suficiente usar SymbolInfoDouble() nessas funções para obter os preços necessários. No entanto, é isso que faço em minhas funções semelhantes. Aqui, o programador se baseou nos dados recebidos do objeto de símbolo em vão - eles são fornecidos antigos - e gravados em m_tick somente durante a atualização.

Aqui surge uma pergunta lógica: quem o obrigou a obter os dados mais simples em OOP? Na MQL4, ele sempre recebeu esses dados sem problemas, mas o que mudou em sua mente?

Cavalo Corcunda

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação.

MT4-Tester VS MT5-Tester

fxsaber, 2017.05.08 10:04 AM

Graças ao subj encontrei o culpado, isso sempre acontece quando há uma oportunidade de comparar.

Consultor especialista mostrando o bug

// Código MQL4&5

#property strict

#ifdef __MQL5__
  #define Bid (SymbolInfoDouble(_Symbol, SYMBOL_BID))
  #define Ask (SymbolInfoDouble(_Symbol, SYMBOL_ASK))
#endif // __MQL5__

#define  PRINT(A) Print(#A + " = " + (string)(A));

void OnTick()
{
  static bool FirstRun = true;
  
  static const double PrevBid = Bid;
  static const double PrevAsk = Ask;
  
  if (FirstRun)
  {
    PRINT((PrevBid != Bid) || (PrevAsk != Ask))
    
    FirstRun = false;
  }
}


MT4

2017.05.08 10:57:33.056 2017.04.10 00:00:08  TDS_Test EURUSD,M1: (PrevBid!=Bid)||(PrevAsk!=Ask) = false


MT5

2017.05.08 11:01:31.266 2017.04.10 00:00:08   (PrevBid!=Bid)||(PrevAsk!=Ask) = true
 
Os códigos foram atualizados. Vamos dar uma olhada na biblioteca padrão