EA não roda todos os dias na simulação

 
Saudações amigos!
Estou no desenvolvimento desse EA, porém quando rodo ele na simulação ele não roda todos os dias corretamente. Por exemplo, se ele roda um dia e nesse dia ele teve loss, no dia seguinte que as condições são atingidas ele não opera, como se não zerasse os parametros para iniciar. Mas na sequencia, após não operar nesse dia que houve as condições cumpridas, no dia seguinte que as condições são cumpridas ele acaba operando normalmente. Não sei se tenho que adicionar algo para que esse reset seja feito de um dia para o outro ou se eu acabei adicionando algum código que está travando ele de um dia para o outro.
Espero que possam me ajudar e segue abaixo o código para análise.
#property copyright "Manolos Trading"
#include <Trade\SymbolInfo.mqh>
#include <Trade\Trade.mqh>
#include <Controls\Dialog.mqh>
#include <Controls\Label.mqh>
#include <Controls\Panel.mqh>
#include <Controls\Button.mqh>   // classe botóes
#include <Telegram.mqh>

CTrade            trade;
CSymbolInfo       simbolo;

//-------------------------------

sinput string                 delimeter1                    = "";                                                    // ROBÔ ESTRUTURA (Fatality)
sinput int                    vol_ctt                       = 1;                                                     // Numero de contratos inicial
sinput string                 fechamento                    = "17:45";                                               // Horário de Fechamento de posições
sinput bool                   HabOperar                     = true;                                                  // Habilita operação
sinput ulong                  MN_estrutura                  = 1009;                                                  // Número Mágico
string                        comentario_cond;
sinput string                 comentario_op                 = "robo-esrutura-fatality";

sinput group                  "Parametros Operacionais"
sinput string                 inicio_est                    = "10:00";           // O-Horario início de entradas 
sinput string                 termino_est                   = "17:40";           // O-Horario de termino das entradas 
input double                  meta_Geral                    = 100;               // Meta (R$) diária
input double                  limite_Geral                  = 500;               // Limite perda (R$) diário
input double                  TP2                           = 55;                // Gain estrutura (Pontos)
double                        TP;                                                // Gain final (Pontos)

sinput group                  "Hab/Desab Dias da semana"
input bool                    HabSeg                        = true;        // Operar Segunda
input bool                    HabTer                        = true;        // Operar Terça
input bool                    HabQua                        = true;        // Operar Quarta
input bool                    HabQui                        = true;        // Operar Quinta
input bool                    HabSex                        = true;        // Operar Sexta

bool                          candle_traded                 = false;       // Apenas 1 op por candle
double                        ganhos_mes, ganho_dia;
int                           comprador                     = 0;
int                           vendedor                      = 0;
double                        MinValNeg                     = 0;
double                        MaxValPos                     = 0;
double                        maximo_volume                 = 0;
int                           zerouAuto                     = 0;
int                           enviouMsg65                   = 0;
int                           enviouMsg85                   = 0;
int                           enviouMsgGain                 = 0;
int                           start_est                     = 0;
int                           encerrou_dia                  = 0;
string                        direcao_dia, condicao;
int                           primeira_hora;
double                        corpoH1, candleH1;

ENUM_TRADE_REQUEST_ACTIONS TipoAction = TRADE_ACTION_DEAL;     // Tipo de Ordem Enviada

MqlTradeRequest               requisicao;
MqlTick                       ultimoTick;
MqlDateTime                   hora_inicio_est, 
                              hora_termino_est, 
                              hora_fechamento, 
                              hora_atual;

int OnInit(){

   comprador                     = 0;
   vendedor                      = 0;
   MinValNeg                     = 0;
   MaxValPos                     = 0;
   maximo_volume                 = 0;
   zerouAuto                     = 0;
   enviouMsg65                   = 0;
   enviouMsg85                   = 0;
   enviouMsgGain                 = 0;
   start_est                     = 0;
   encerrou_dia                  = 0;
   TP                            = meta_Geral/0.2;
  
//------------------------------------------------------------------
   requisicao.type_time = ORDER_TIME_DAY;
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
   trade.SetDeviationInPoints(0);

   if(!simbolo.Name(_Symbol)){
      printf("Ativo Inválido!");
      return INIT_FAILED;
   }

   TimeToStruct(StringToTime(inicio_est), hora_inicio_est);
   TimeToStruct(StringToTime(fechamento), hora_fechamento);
   TimeToStruct(StringToTime(termino_est), hora_termino_est);

   if(TipoAction!=TRADE_ACTION_DEAL && TipoAction!= TRADE_ACTION_PENDING){
      printf("Tipo de ordem não permitido");
      return INIT_FAILED;
   }
   
   EventSetTimer(1); // Requisitar a função OnTimer de 1 em 1 segundo!   
   bot1.Token(TelegramBotToken); // Conectar Token com a API do Telegram   
   getme_result = bot1.GetMe(); // Fazer primeiro contato com o bot do telegram
   
   Print("Funcionou a conexão = ", getme_result); // se getme_result = 0 (zero), deu tudo certo
   Print("Nome do robô: ",bot1.Name() ); // Retorna nome do Robô
   
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){
   printf("Deinit reason: %d", reason);
   panel.Destroy(reason);
   EventKillTimer();
  }

void OnTick(){
 if(VerificarResultado()){
   double lucro_realizado = PositionGetDouble(POSITION_PROFIT);
   datetime dia = iTime(_Symbol, PERIOD_D1, 0);
   double lucro_corrente = Results(dia, MN_estrutura);
   double lucro_final = NormalizeDouble((lucro_corrente+lucro_realizado), 2);
   
   datetime mes = iTime(_Symbol, PERIOD_MN1, 0);
   ganho_dia = NormalizeDouble((Results(dia, MN_estrutura)), 2);
   ganhos_mes = NormalizeDouble((Results(mes, MN_estrutura)), 2);
   
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   CopyRates(_Symbol, _Period, 0, 10, rates);
// ------------------------------------------------------------------
   if(IsNewBar())
   candle_traded = false;
// ------------------------------------------------------------------
   if(!SymbolInfoTick(Symbol(),ultimoTick)){
      Alert("Erro ao obter informações de Preços: ", GetLastError());
      return;
   }

   if(!simbolo.RefreshRates())
      return;
// -----------------------------------------------------------
   // verificar se existe posicao aberta
   bool posAberta = false;
   for(int i = PositionsTotal()-1; i>=0; i--){
      string symbol = PositionGetSymbol(i);
      ulong magic = PositionGetInteger(POSITION_MAGIC);
      if(symbol == _Symbol && magic == MN_estrutura){
         posAberta = true;
         break;
      }
   }
// ------------------------------------------------------------------
   // verificar se existe ordem pendente
   bool ordPendente = false;
   for(int i = OrdersTotal()-1; i>=0; i--){
      ulong ticket = OrderGetTicket(i);
      string symbol = OrderGetString(ORDER_SYMBOL);
      ulong magic = OrderGetInteger(ORDER_MAGIC);
      if(symbol == _Symbol && magic == MN_estrutura){
         ordPendente = true;
         break;
      }
   }
// -----------------------------------------------------------
   // se não houver posição aberta e houver ordens pendentes -> deletar ordens
   if(posAberta == false && ordPendente == true) DeleteOrdens();
   if(SemPosicao() == true && SemOrdem() == false) DeleteOrdens();
// ------------------------------------------------------------------
// verificar condicoes de operacao e executar
    if(  HorarioEntrada_fc() && 
         SemPosicao() && 
         SemOrdem() && 
         encerrou_dia == 0 && 
         VerificarResultado() ){
      
      int resultado_cruzamento = Condicao_operacao();
      if(resultado_cruzamento != 0){
         if(DiasHab() && !candle_traded){
            if(resultado_cruzamento == 1){
               Compra_est();
               candle_traded = true;
            }
            if(resultado_cruzamento == -1){
               Venda_est();
               candle_traded = true;
            }
         }
      }
    }
    
    if(  !SemPosicao() && 
         encerrou_dia == 0 && 
         VerificarResultado() ){
         
      int resultado_cruzamento_2 = Condicao_operacao_2();
      if(resultado_cruzamento_2 != 0){
         if(resultado_cruzamento_2 == 2 && DiasHab() && !candle_traded){
            Compra_est2();
            candle_traded = true;
         }
         if(resultado_cruzamento_2 == -2 && DiasHab() && !candle_traded){
            Venda_est2();
            candle_traded = true;
         }
      }
    }
    
    double volume_posicao = PositionGetDouble(POSITION_VOLUME);
    if(!SemPosicao()){
       if(volume_posicao >= maximo_volume) maximo_volume = volume_posicao;
       if(lucro_final < 0 && lucro_final < MinValNeg){ 
         if(lucro_final < MinValNeg) MinValNeg = lucro_final;
       }
       if(lucro_final > 0 && lucro_final > MaxValPos){
         if(lucro_final > MaxValPos) MaxValPos = lucro_final;
       }
       if(volume_posicao > 0 && volume_posicao > maximo_volume) maximo_volume = volume_posicao;
    }
   
   if(TimeCurrent() > StringToTime("10:00")) comentario_cond =   IntegerToString(g1()) + "." + 
                                                               IntegerToString(g2()) + "." +
                                                               IntegerToString(g3()) + "." +
                                                               IntegerToString(g4()) + "." +
                                                               IntegerToString(g5()) + "." +
                                                               IntegerToString(g6()) + "." +
                                                               IntegerToString(g7()) + "." +
                                                               IntegerToString(g8());
// ------------------------------------------------------------------
// encerrar posicoes ao final do dia
   if(HorarioFechamento()){
      comprador = 0;
      vendedor = 0;
      enviouMsg65 = 0;
      enviouMsg85 = 0;
      enviouMsgGain = 0;
      zerouAuto = 0;
      MaxValPos = 0;
      MinValNeg = 0;
      start_est = 0;
      encerrou_dia = 0;
      if(!SemPosicao() || !SemOrdem()){
         Fechar();
      }
   }
   // ------------------------------------------------------------------
   if(comprador == 1 && vendedor == 0) direcao_dia = "Comprador";
   if(vendedor == 1 && comprador == 0) direcao_dia = "Vendedor";
   if(comprador == 0 && vendedor == 0) direcao_dia = "Aguardando";
   // ------------------------------------------------------------------
   condicao =  IntegerToString(g1()) + "." + 
               IntegerToString(g2()) + "." +
               IntegerToString(g3()) + "." +
               IntegerToString(g4()) + "." +
               IntegerToString(g5()) + "." +
               IntegerToString(g6()) + "." +
               IntegerToString(g7()) + "." +
               IntegerToString(g8()) + " = " + IntegerToString(g1() + g2() + g3() + g4() + g5() + g6() + g7() + g8());
   // ----------------------------------------------------------
   
   if(lucro_final >= meta_Geral){
      Fechar();
      DeleteOrdens();
      encerrou_dia = 1;
   }
   
   if(lucro_final <= -limite_Geral){
      Fechar();
      DeleteOrdens();
      encerrou_dia = 1;
   }
//------------------------------------------------------------------
   if(TimeCurrent() < StringToTime("10:00")) primeira_hora = 0; 
   if(TimeCurrent() > StringToTime("10:00") && TimeCurrent() < StringToTime("11:00")) primeira_hora = 1;
   if(TimeCurrent() > StringToTime("11:00") && TimeCurrent() < StringToTime("12:00")) primeira_hora = 2;
   if(TimeCurrent() > StringToTime("12:00") && TimeCurrent() < StringToTime("13:00")) primeira_hora = 3;
   if(TimeCurrent() > StringToTime("13:00") && TimeCurrent() < StringToTime("14:00")) primeira_hora = 4;
   if(TimeCurrent() > StringToTime("14:00") && TimeCurrent() < StringToTime("15:00")) primeira_hora = 5;
   if(TimeCurrent() > StringToTime("15:00") && TimeCurrent() < StringToTime("16:00")) primeira_hora = 6;
   if(TimeCurrent() > StringToTime("16:00") && TimeCurrent() < StringToTime("17:00")) primeira_hora = 7;
   if(TimeCurrent() > StringToTime("17:00") && TimeCurrent() < StringToTime("18:00")) primeira_hora = 8;
   
   double maxima = iHigh(_Symbol,PERIOD_H1, primeira_hora);
   double minima = iLow(_Symbol,PERIOD_H1, primeira_hora);
            
   if(TimeCurrent() > StringToTime("10:00")){
      ObjectCreate(0,"Max_H1",OBJ_HLINE,0,0,maxima);
      ObjectCreate(0,"Min_H1",OBJ_HLINE,0,0,minima);
      ObjectSetInteger(0, "Max_H1",OBJPROP_COLOR, clrGreen);
      ObjectSetInteger(0, "Min_H1",OBJPROP_COLOR, clrRed);
   }
 }
}
}

void Fechar(){
      trade.PositionClose(_Symbol);
  }

bool SemPosicao(){
   bool resultado = !PositionSelect(_Symbol);
   return resultado;
  }

bool SemOrdem(){
   for(int i=OrdersTotal()-1; i>=0; i--){
      OrderGetTicket(i);
      if(OrderGetString(ORDER_SYMBOL)==_Symbol)
         return false;
   }
   return true;
  }

int Condicao_operacao(){
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   CopyRates(_Symbol, PERIOD_M1, 0, 5, rates);
   
   MqlRates PM5[];
   ArraySetAsSeries(PM5, true);
   CopyRates(_Symbol, PERIOD_M5, 0, 5, PM5);

   if(TimeCurrent() < StringToTime("10:00")) primeira_hora = 0; 
   if(TimeCurrent() > StringToTime("10:00") && TimeCurrent() < StringToTime("11:00")) primeira_hora = 1;
   if(TimeCurrent() > StringToTime("11:00") && TimeCurrent() < StringToTime("12:00")) primeira_hora = 2;
   if(TimeCurrent() > StringToTime("12:00") && TimeCurrent() < StringToTime("13:00")) primeira_hora = 3;
   if(TimeCurrent() > StringToTime("13:00") && TimeCurrent() < StringToTime("14:00")) primeira_hora = 4;
   if(TimeCurrent() > StringToTime("14:00") && TimeCurrent() < StringToTime("15:00")) primeira_hora = 5;
   if(TimeCurrent() > StringToTime("15:00") && TimeCurrent() < StringToTime("16:00")) primeira_hora = 6;
   if(TimeCurrent() > StringToTime("16:00") && TimeCurrent() < StringToTime("17:00")) primeira_hora = 7;
   if(TimeCurrent() > StringToTime("17:00") && TimeCurrent() < StringToTime("18:00")) primeira_hora = 8;
   
   datetime dia = iTime(_Symbol, PERIOD_D1, 0);
   double maxima = iHigh(_Symbol,PERIOD_H1, primeira_hora);
   double minima = iLow(_Symbol,PERIOD_H1, primeira_hora);
   double aberturaH1 = iOpen(_Symbol, PERIOD_H1, primeira_hora);
   double fechamentoH1 = iClose(_Symbol, PERIOD_H1, primeira_hora);
   double lucro_realizado = PositionGetDouble(POSITION_PROFIT);
   double lucro_corrente = Results(dia, MN_estrutura);
   double lucro_final = NormalizeDouble((lucro_corrente+lucro_realizado), 2);
   
   if(HabOperar && comprador == 0 && vendedor == 0 && lucro_final == 0 && liberado_operar() >= 3){
      if(PM5[1].close > maxima && start_est == 0){
         if(rates[0].close >= PM5[1].high + 5){
            string text = "Robô Estruturas iniciou operação COMPRADO!";
            SendTelegramMessage( TelegramApiUrl, TelegramBotToken, ChatId,text); // no image attached
            start_est++;
            comprador = 1;
            return 1;
         }
      }
      if(PM5[1].close < minima && start_est == 0){
         if(rates[0].close <= PM5[1].low - 5){
            string text = "Robô Estruturas iniciou operação VENDIDO!";
            SendTelegramMessage( TelegramApiUrl, TelegramBotToken, ChatId,text); // no image attached
            start_est++;
            vendedor = 1;
            return -1;
         }
      }
   }
   
   return 0;
}

int Condicao_operacao_2(){
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   CopyRates(_Symbol, _Period, 0, 5, rates);
   
   if(HabOperar){
      if(rates[0].close <= rates[1].low && comprador == 1){
      return 2;
      }
      if(rates[0].close >= rates[1].high && vendedor == 1){
      return -2;
      }
   }
   
   return 0;
}

bool VerificarResultado(){
   double lucro_realizado = PositionGetDouble(POSITION_PROFIT);
   datetime dia = iTime(_Symbol, PERIOD_D1, 0);
   double lucro_corrente = Results(dia, MN_estrutura);
   double lucro_final = NormalizeDouble((lucro_corrente+lucro_realizado), 2);
   if((lucro_final <= -limite_Geral && !SemPosicao()) || ((lucro_final >= meta_Geral && !SemPosicao()) || (lucro_final >= meta_Geral*0.9 && SemPosicao()))){
      encerrou_dia = 1;
      Fechar();
      DeleteOrdens();
      return false;
   }
   
   return true;
}
 
Não sei se ficou clara a minha dúvida, mas o que acontece por exemplo é: quando eu rodo uma simulação do dia 01-03-23 até o dia 03-03-23 ele opera dia 01, não opera dia 02 e opera dia 3. Quando eu inicio a simulação no dia 02, ele opera dia 02 e não opera dia 03. Tanto no dia 01, quanto no dia 02 a estratégia stopou, foi loss. Ou seja, sempre que acontece um dia de loss ele fica 1 dia na sequencia sem operar.
 
Marcel Cardoso #Não sei se ficou clara a minha dúvida, mas o que acontece por exemplo é: quando eu rodo uma simulação do dia 01-03-23 até o dia 03-03-23 ele opera dia 01, não opera dia 02 e opera dia 3. Quando eu inicio a simulação no dia 02, ele opera dia 02 e não opera dia 03. Tanto no dia 01, quanto no dia 02 a estratégia stopou, foi loss. Ou seja, sempre que acontece um dia de loss ele fica 1 dia na sequencia sem operar.

Pelo que entendi, uma das condições para operar é a variável encerrou_dia estar zerada... Essa variável é zerada se HorarioFechamento(), porém, após a verificação dessa função, não existe nenhum return, e, na sequência, são feitas as verificações abaixo, onde o valor de encerrou_dia pode retornar para 1, desfazendo a alteração feita em HorarioFechamento():

      if(lucro_final >= meta_Geral)
        {
         Fechar();
         DeleteOrdens();
         encerrou_dia = 1;
        }

      if(lucro_final <= -limite_Geral)
        {
         Fechar();
         DeleteOrdens();
         encerrou_dia = 1;
        }

Resumindo, acho que HorarioFechamento() deve ser a última verificação a ser feita ou inclui um return após a reinicialização das variáveis nessa verificação...

 
Vinicius Pereira De Oliveira #:

Pelo que entendi, uma das condições para operar é a variável encerrou_dia estar zerada... Essa variável é zerada se HorarioFechamento(), porém, após a verificação dessa função, não existe nenhum return, e, na sequência, são feitas as verificações abaixo, onde o valor de encerrou_dia pode retornar para 1, desfazendo a alteração feita em HorarioFechamento():

Resumindo, acho que HorarioFechamento() deve ser a última verificação a ser feita ou inclui um return após a reinicialização das variáveis nessa verificação...

Coloquei o HorarioFechamento() como ultima verificação conforme vc disse e funcionou, muito obrigado!

 
Marcel Cardoso #Coloquei o HorarioFechamento() como ultima verificação conforme vc disse e funcionou, muito obrigado!

De nada!! 👍

Razão: