EA RSI Fica abrindo varias ordens

 

Olá pessoal. Sou novo em MQL5 e estou estudando um EA baseado em RSI.

Se o preço está em em 70 ou acima, ele compra e se sai do 70 e volta pra região do 70 ele compra de novo. Mesma lógica pro 30.

Mas ele está fazendo isso várias vezes. Entra na região de compra ou venda, o mesmo candle ta fazendo 2 a 3 operações. Ele só pode fazer isso quando ele sai ou está fora, e entra na região de compra ou venda.

Alguém poderia me ajudar a encontrar o erro?


#include <Trade\Trade.mqh>
CTrade trade;

input int                     periodoRSI = 3;                             //Periodo do RSI
  
input ulong                   magicNum = 123456;                          //Magic Number
input ulong                   desvPts = 20;                               //Desvio em Pontos
input ENUM_APPLIED_PRICE      rsi_preco = PRICE_CLOSE;                    //Tipo de Entrada
input ENUM_ORDER_TYPE_FILLING preenchimento = ORDER_FILLING_RETURN;       //Preenchimento da Ordem

input double                  lote = 1;                                   //Contratos
input double                  stopLoss = 200;                             //Stop Loss
input double                  takeProfit = 200;                           //Take Profit
input double                  gatilhoBE = 30;                             //Break Even
input double                  gatilhoTS = 35;                             //TraillingStop
input double                  stepTS = 15;                                //Step TraillingStop

input int                     horaInicioAbertura = 9;                     //Hora Início Abertura
input int                     minInicioAbertura = 30;                     //Minuto Iníco Abertura
input int                     horaFimAbertura = 13;                       //Hora Encerramento de Posições
input int                     minFimAbertura = 30;                        //Minuto Encerramento de Posições
input int                     horaInicioFechamento = 15;                  //Hora Fechamento de Posições
input int                     minInicioFechamento = 30;                   //Minuto Fechamento de Posições

double                        ask, bid, last;
double                        rsiArray[];
int                           rsiHandle;

double                        PRC;                                        //Preço Normalizado
double                        STL;                                        //Stop Loss Normalizado
double                        TKP;                                        //Take Profit Normalizado

bool                          posAberta;
bool                          ordPendente;
bool                          beAtivo;

MqlTick                       ultimoTick;
MqlRates                      rates[];
MqlDateTime                   horaAtual;

int OnInit()
  {
      rsiHandle = iRSI(_Symbol, _Period, periodoRSI, rsi_preco);
      if(rsiHandle==INVALID_HANDLE)
         {
            Print("Erro ao criar o RSI - ERRO", GetLastError());
            return(INIT_FAILED);
         }
      ArraySetAsSeries(rsiArray, true);
      ArraySetAsSeries(rates, true);
      
      trade.SetTypeFilling(preenchimento);
      trade.SetDeviationInPoints(desvPts);
      trade.SetExpertMagicNumber(magicNum);
      
      if(horaInicioAbertura > horaFimAbertura || horaFimAbertura > horaInicioFechamento)
         {
            Alert("Inconsistência de Horário de Negociação!");
            return(INIT_FAILED);
         }
      if(horaInicioAbertura == horaFimAbertura && minInicioAbertura >= minFimAbertura)
         {
            Alert("Inconsistência de Horário de Negociação!");
            return(INIT_FAILED);
         }
      if(horaFimAbertura == horaInicioFechamento && minFimAbertura >= minInicioAbertura)
         {
            Alert("Inconsitência de Horário de Negociação!");
            return(INIT_FAILED);
         }      

      return(INIT_SUCCEEDED);
  }

void OnTick()
  {           
      if(!SymbolInfoTick(Symbol(), ultimoTick))
         {
            Alert("Erro ao obter informações de preço: ", GetLastError());
            return;
         }
      if(CopyRates(_Symbol, _Period, 0,3, rates)<0)
         {
            Alert("Erro ao obter as informações do MqlRates: ", GetLastError());
            return;
         }
      
      if(CopyBuffer(rsiHandle, 0, 0, 5, rsiArray)<0)
         {
            Alert("Erro ao copiar os dados do RSI: ", GetLastError());
            return;
         }
      
      posAberta = false;
      for(int i = PositionsTotal()-1; i>=0; i--)
         {
            string symbol = PositionGetSymbol(i);
            ulong magic = PositionGetInteger(POSITION_MAGIC);
            if(symbol == _Symbol && magic == magicNum)
               {
                  posAberta = true;
                  break;
               }
         }
      
      ordPendente = false;
      for(int i = PositionsTotal()-1; i>=0; i--)
         {
            ulong ticket = OrderGetTicket(i);
            string symbol = OrderGetString(ORDER_SYMBOL);
            ulong magic = OrderGetInteger(ORDER_MAGIC);
            if(symbol == _Symbol && magic == magicNum)
               {
                  ordPendente = true;
                  break;
               }
         }
         
      if(!posAberta)
         {
            beAtivo = false;
         }
      if(posAberta && !beAtivo)
         {
            BreakEven(ultimoTick.last);            
         }            

      if(posAberta && beAtivo)
         {
            TrailingStop(ultimoTick.last);
         }
      
      if(HoraFechamento())
         {
            
            Comment("Horário de Fechamento de Posições");
         }
         
      
      else if(HoraNegociacao())
         {  
            
            Comment("Dentro do Horário de Negociação!");
         }
      else
         {
            
            Comment("Fora do Horário de Negociação!");
         }   
       
       
       
       
      if(rsiArray[2]<70 && rsiArray[1]>70 && rates[1].close>rates[1].open && !posAberta && !ordPendente && HoraNegociacao()) //CONDIÇÃO DE COMPRA
         {            
            PRC =  NormalizeDouble(ultimoTick.ask, _Digits);
            STL = NormalizeDouble(PRC - stopLoss, _Digits);
            TKP = NormalizeDouble(PRC + takeProfit, _Digits);
            if(trade.Buy(lote, _Symbol, PRC, STL, TKP, ""))
               {
                  Print("Ordem de Compra - sem falha. ResultRedcode: ", trade.ResultRetcode(), "RetcodeDescription:", trade.ResultRetcodeDescription());
               }
            else
               {
                  Print("Ordem de Compra - com falha. ResultRedcode: ", trade.ResultRetcode(), "RetcodeDescription:", trade.ResultRetcodeDescription());
               }
         }
      else if(rsiArray[2]>30 && rsiArray[1]<30 && rates[1].close<rates[1].open && !posAberta && !ordPendente && HoraNegociacao()) //CONDIÇÃO DE VENDA
         {            
            PRC =  NormalizeDouble(ultimoTick.bid, _Digits);
            STL = NormalizeDouble(PRC + stopLoss, _Digits);
            TKP = NormalizeDouble(PRC - takeProfit, _Digits);
            if(trade.Sell(lote,_Symbol, PRC, STL, TKP, ""))
               {
                  Print("Ordem de Venda - sem falha. ResultRedcode: ", trade.ResultRetcode(), "RetcodeDescription:", trade.ResultRetcodeDescription());
               }
            else
               {
                  Print("Ordem de Venda - com falha. ResultRedcode: ", trade.ResultRetcode(), "RetcodeDescription:", trade.ResultRetcodeDescription());
               }
         }
                    
  }
//---
//---
bool HoraNegociacao ()
   {
      TimeToStruct(TimeCurrent(), horaAtual);
      if(horaAtual.hour >= horaInicioAbertura && horaAtual.hour <= horaFimAbertura)
         {
            if(horaAtual.hour == horaInicioAbertura)
               {
                  if(horaAtual.min == minInicioAbertura)
                     {
                        return true;
                     }
                  else
                     {
                        return false;
                     }
               }
            if(horaAtual.hour == horaFimAbertura)
               {
                  if(horaAtual.min <= minFimAbertura)
                     {
                        return true; 
                     }
                  else
                     {
                        return false;
                     }   
               }  
            return true;
         }
      return false;        
   }
//---
//---
bool HoraFechamento()
   {
      TimeToStruct(TimeCurrent(), horaAtual);
      if(horaAtual.hour >= horaInicioFechamento)
         {  
            if(horaAtual.hour == horaInicioFechamento)
               {
                  if(horaAtual.min >= minInicioFechamento)
                     {
                        return true;
                     }
                  else
                     {
                        return false;
                     }   
               }
            return true;
         }
      return false;
   }

   
   

//---
//---
void TrailingStop(double preco)
   {
      for(int i = PositionsTotal()-1; i>=0; i--)
         {
            string symbol = PositionGetSymbol(i);
            ulong magic = PositionGetInteger(POSITION_MAGIC);
            if(symbol == _Symbol && magic==magicNum)
               {
                  ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
                  double StopLossCorrente = PositionGetDouble(POSITION_SL);
                  double TakeProfitCorrente = PositionGetDouble(POSITION_TP);
                  if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                     {
                        if(preco >= (StopLossCorrente + gatilhoTS) )
                           {
                              double novoSL = NormalizeDouble(StopLossCorrente + stepTS, _Digits);
                              if(trade.PositionModify(PositionTicket, novoSL, TakeProfitCorrente))
                                 {
                                    Print("TrailingStop - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                 }
                              else
                                 {
                                    Print("TrailingStop - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                 }
                           }
                     }
                  else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
                     {
                        if(preco <= (StopLossCorrente - gatilhoTS) )
                           {
                              double novoSL = NormalizeDouble(StopLossCorrente - stepTS, _Digits);
                              if(trade.PositionModify(PositionTicket, novoSL, TakeProfitCorrente))
                                 {
                                    Print("TrailingStop - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                 }
                              else
                                 {
                                    Print("TrailingStop - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                 }
                           }
                     }
               }
         }
   }
//---
//---
void BreakEven(double preco)
   {
      for(int i = PositionsTotal()-1; i>=0; i--)
         {
            string symbol = PositionGetSymbol(i);
            ulong magic = PositionGetInteger(POSITION_MAGIC);
            if(symbol == _Symbol && magic == magicNum)
               {
                  ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
                  double PrecoEntrada = PositionGetDouble(POSITION_PRICE_OPEN);
                  double TakeProfitCorrente = PositionGetDouble(POSITION_TP);
                  if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                     {
                        if( preco >= (PrecoEntrada + gatilhoBE) )
                           {
                              if(trade.PositionModify(PositionTicket, PrecoEntrada, TakeProfitCorrente))
                                 {
                                    Print("BreakEven - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                    beAtivo = true;
                                 }
                              else
                                 {
                                    Print("BreakEven - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                 }
                           }                           
                     }
                  else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
                     {
                        if( preco <= (PrecoEntrada - gatilhoBE) )
                           {
                              if(trade.PositionModify(PositionTicket, PrecoEntrada, TakeProfitCorrente))
                                 {
                                    Print("BreakEven - sem falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                    beAtivo = true;
                                 }
                              else
                                 {
                                    Print("BreakEven - com falha. ResultRetcode: ", trade.ResultRetcode(), ", RetcodeDescription: ", trade.ResultRetcodeDescription());
                                 }
                           }
                     }
               }
         }
   }
 
patrickdasilva:

Olá pessoal. Sou novo em MQL5 e estou estudando um EA baseado em RSI.

Se o preço está em em 70 ou acima, ele compra e se sai do 70 e volta pra região do 70 ele compra de novo. Mesma lógica pro 30.

Mas ele está fazendo isso várias vezes. Entra na região de compra ou venda, o mesmo candle ta fazendo 2 a 3 operações. Ele só pode fazer isso quando ele sai ou está fora, e entra na região de compra ou venda.

Alguém poderia me ajudar a encontrar o erro?


Ele entra novamente em milissegundos? Poste os logs...

Eu não recomendo "varrer" as Posições a cada Tick... É praticamente um crime contra a sua CPU. Você precisa entender quando o OnTick() é executado e ser o mais austero possível, do contrário esse robô pode colocar de joelhos qualquer máquina.

E, jamais conte que "tudo vai dar certo" com as funções do MQL5. A sua ordem pode até ter sido executada, mas o PositionsTotal() ainda pode não ter recebido esse status... Não sei se é esse o problema, mas eu não faria isso. Eu usaria o retorno do OnTradeTransaction() para confirmar a entrada e tirar esse ônus do Ontick()...

Infelizmente o MT5 é péssimo em Event Driven messages, então nosso código sempre tende a se tornar macarrônico...

;)