LIMITAR ENTRADAS APÓS ATINGIR TAKE PROFIT

 

Boa noite a todos, 
Estou a alguns dias quebrando a cabeça para fazer o meu EA filtrar um determinado tipo de entrada e gostaria da ajuda de vocês.

A estratégia é simples: é usado um canal de keltner, um candle fecha dentro do canal e o proximo candle rompendo o canal pra cima, é gerada uma ordem de compra, se romper pra baixo é venda.
Junto com as ordens de abertura da posição estão configurados os stop loss e take profit, bem como o breakeven e o trailling stop.

Agora que vem o problema: Preciso condicionar as entradas para que NÃO seja feita uma nova entrada caso o TAKE PROFIT tenha sido executado no candle anterior ou no candle atual.

Tenho tido esse problema porque as vezes o take profit é executado num momento onde está configurado um padrão de entrada, rompendo o canal de keltner.
Então preciso fazer com que ele não abra novas operações nessas ocasiões.

Preciso que o preço volte para dentro do canal antes de abrir uma nova operação.

Vou deixa em anexo uma imagem mostrando a situação citada.



Ficarei muito agradecido se alguém conseguir me ajudar nessa! Um abraço.

Arquivos anexados:
ex.png  34 kb
 

Bom dia!


Veja se esse exemplo ajuda:

https://www.mql5.com/pt/forum/369235#comment_22315671

Como só entrar na próxima ordem no segundo candle após o TakeProfit ou StopLoss?
Como só entrar na próxima ordem no segundo candle após o TakeProfit ou StopLoss?
  • 2021.05.13
  • www.mql5.com
Amigos sou iniciante em MQL5 já programo em Php...
 
Vinicius de Oliveira:

Bom dia!


Veja se esse exemplo ajuda:

https://www.mql5.com/pt/forum/369235#comment_22315671

Boa noite, amigo! 
Realmente essa solução resolveria meu problema!!! Mas quebrei a cabeça e não consegui implementar essa função no meu EA.
Li todos os artigos relacionados e não consegui.. com certeza é falta de experiência no assunto.
Se puder me dar uma força em relação ao local onde devo "encaixar" essa função.. (Ex: OnInit, OnTick...) Estou com essa dúvida tbm.

Vou deixar o EA em anexo.. Se puder olhar e me dar essa força eu agradeço.
Arquivos anexados:
EA_Keltner.mq5  31 kb
 

Eu faria o seguinte, após bater take profit ou stop loss, o EA tem que esperar x velas se formarem para liberar uma nova entrada, então no caso seria somente um contador.

 
Eduardo Oliveira:

Eu faria o seguinte, após bater take profit ou stop loss, o EA tem que esperar x velas se formarem para liberar uma nova entrada, então no caso seria somente um contador.

Então, meu camarada.. foi exatamente isso que o Vinicius apresentou na resposta acima: após acionar o TP ou SL aguardar "X" velas para procurar uma nova operação.
Mas não consegui implementar aquela função no meu EA ainda.
 
savio95:
Boa noite, amigo! 
Realmente essa solução resolveria meu problema!!! Mas quebrei a cabeça e não consegui implementar essa função no meu EA.
Li todos os artigos relacionados e não consegui.. com certeza é falta de experiência no assunto.
Se puder me dar uma força em relação ao local onde devo "encaixar" essa função.. (Ex: OnInit, OnTick...) Estou com essa dúvida tbm.

Vou deixar o EA em anexo.. Se puder olhar e me dar essa força eu agradeço.

Bom dia!


Seria assim para aguardar, no mínimo, 1 candle após o encerramento de uma posição:

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

//+------------------------------------------------------------------+
//|                        DADOS DO INDICADOR                        |
//+------------------------------------------------------------------+ 

#property indicator_chart_window
#property indicator_buffers 10
#property indicator_plots   4
#property indicator_label1  "Average"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrDeepSkyBlue,clrPaleVioletRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
#property indicator_label2  "Upperband"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
#property indicator_label3  "Lowerband"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2
#property indicator_label4  "Keltner MA trend"
#property indicator_type4   DRAW_COLOR_BARS
#property indicator_color4  clrDeepSkyBlue,clrPaleVioletRed
#property indicator_style4  STYLE_SOLID
//
enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage   // Heiken ashi average
};
//
enum enMaModes
{
   ma_Simple,  // Simple moving average
   ma_Expo     // Exponential moving average
};
//
enum enMaVisble
{
   mv_Visible,    // Middle line visible
   mv_NotVisible  // Middle line not visible
};
//
enum enCandleMode
{
   cm_None,   // Do not draw candles nor bars
   cm_Bars,   // Draw as bars
   cm_Candles // Draw as candles
};
//
enum enAtrMode
{
   atr_Rng,   // Calculate using range
   atr_Atr    // Calculate using ATR
};

//+------------------------------------------------------------------+
//|                             INPUTS                               |
//+------------------------------------------------------------------+

input ENUM_TIMEFRAMES         TimeFrame       = PERIOD_CURRENT;  // Time frame
input int                     MAPeriod        = 20;              // Moving average period
input enMaModes               MAMethod        = ma_Expo;         // Moving average type
input enMaVisble              MAVisible       = mv_Visible;      // Midlle line visible ?
input enPrices                Price           = pr_typical;      // Moving average price 
input color                   MaColorUp       = clrWhite;        // Color for slope up
input color                   MaColorDown     = clrWhite;        // Color for slope down
input int                     AtrPeriod       = 14;              // Range period
input double                  AtrMultiplier   = 0.4;             // Range multiplier
input enAtrMode               AtrMode         = atr_Rng;         // Range calculating mode 
input enCandleMode            ViewBars        = cm_None;         // View bars as :
input bool                    Interpolate     = true;            // Interpolate mtf data

input ulong                   magicNum = 123456;//Magic Number
input ulong                   desvPts = 0;//Desvio em Pontos
input ENUM_ORDER_TYPE_FILLING preenchimento = ORDER_FILLING_RETURN;//Preenchimento da Ordem

input double                  Contratos = 1;//Nº de Contratos
input double                  stopLoss = 250;//Stop Loss
input double                  takeProfit = 85;//Take Profit
input double                  gatilhoBE = 40;//Gatilho BreakEven
input double                  gatilhoTS = 50;//Gatilho TrailingStop
input double                  stepTS = 40;//Step TrailingStop

double                        PRC;//Preço normalizado
double                        STL;//StopLoss normalizado
double                        TKP;//TakeProfit normalizado

double                        Upperband[];
double                        Lowerband[];
double                        Average[];

bool                          posAberta;
bool                          ordPendente;
bool                          beAtivo;

MqlTick                       ultimoTick;
MqlRates                      rates[];
//
double                        channelBo[];
double                        channelBh[];
double                        channelBl[];
double                        channelBc[];
double                        channelUp[];
double                        channelDn[];
double                        ma[];
double                        colorBuffer[];
double                        colorBufferb[];
double                        countBuffer[];
ENUM_TIMEFRAMES               timeFrame;
int                           mtfHandle;
int                           atrHandle;
bool                          calculating;

//---Variaveis Globais Para Plotar Indicador no Gráfico
int                           handle = INVALID_HANDLE;
int                           sub_window=(int)ChartGetInteger(0,0);

//---Variaveis Globais do Controle de Operações no Mesmo Candle
bool Operamos_Nesta_Vela=false;
string TIME_Abertura_Ultimo_Candle;
string Hora_Ultimo_Negocio;
//

int OnInit()
  {
      ChartSetInteger(0, CHART_SHOW_GRID, false);
     
      handle = iCustom(Symbol(), Period(), "KeltnerChannel.ex5", TimeFrame, MAPeriod, MAMethod, MAVisible, Price, MaColorUp, MaColorDown, AtrPeriod, AtrMultiplier, AtrMode, ViewBars, Interpolate);
      if(handle==INVALID_HANDLE)
         {
            Print("Erro ao criar Keltner - erro", GetLastError());
            return(INIT_FAILED);
         }
      
      if(ChartIndicatorsTotal(0,0) < 1)
         {
            ChartIndicatorAdd(0,0,handle);
         }
      
      ArraySetAsSeries(rates, true);
      ArraySetAsSeries(Upperband, true);
      ArraySetAsSeries(Lowerband, true);
      ArraySetAsSeries(Average, true);     
      
      trade.SetTypeFilling(preenchimento);
      trade.SetDeviationInPoints(desvPts);
      trade.SetExpertMagicNumber(magicNum);
      
      return(INIT_SUCCEEDED);
  }
//
void OnDeinit(const int reason)
{

  ChartIndicatorDelete(0, sub_window, ChartIndicatorName(0, sub_window, 0));
  handle=INVALID_HANDLE;
 
}
//  
void OnTick()
  {               
//+------------------------------------------------------------------+
//|         VERIFICAR SE JÁ ABRIU OPERAÇÃO NO CANDLE ATUAL           |
//+------------------------------------------------------------------+   
    TIME_Abertura_Ultimo_Candle=TimeToString((SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE)),TIME_SECONDS);
    
       if(Hora_Ultimo_Negocio < TIME_Abertura_Ultimo_Candle)
         {
         Operamos_Nesta_Vela=false;
         }

       if(Hora_Ultimo_Negocio > TIME_Abertura_Ultimo_Candle)
         {
         Operamos_Nesta_Vela=true;
         }     
//       
     
      if(!SymbolInfoTick(Symbol(),ultimoTick))
         {
            Alert("Erro ao obter informações de Preços: ", GetLastError());
            return;
         }
        
      if(CopyRates(_Symbol, _Period, 0, 3, rates)<0)
         {
            Alert("Erro ao obter as informações de MqlRates: ", GetLastError());
            return;
         }
      
      if(CopyBuffer(handle, 2, 0, 3, Upperband)<0)
         {
            Alert("Erro ao copiar dados do Keltner: ", GetLastError());
            return;
         }
      
      if(CopyBuffer(handle, 3, 0, 3, Lowerband)<0)
         {
            Alert("Erro ao copiar dados do Keltner: ", 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 = OrdersTotal()-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(CheckTradePause(1) && rates[2].close > Lowerband[2] && rates[2].close < Upperband[2] && rates[1].open < Upperband[1] && rates[1].open > Lowerband[1] && rates[1].close > Upperband[1] && !posAberta && !ordPendente && Operamos_Nesta_Vela==false)
         {
            PRC = NormalizeDouble(ultimoTick.ask, _Digits);
            STL = NormalizeDouble(PRC - stopLoss, _Digits);
            TKP = NormalizeDouble(PRC + takeProfit, _Digits);
            if(trade.Buy(Contratos, _Symbol, PRC, STL, TKP, ""))
               
               Hora_Ultimo_Negocio=TimeToString(TimeCurrent(),TIME_SECONDS);  
    
                  Operamos_Nesta_Vela=true; 
         }
               
 
         
      else if(CheckTradePause(1) && rates[2].close > Lowerband[2] && rates[2].close < Upperband[2] && rates[1].open < Upperband[1] && rates[1].open > Lowerband[1] && rates[1].close < Lowerband[1] && !posAberta && !ordPendente && Operamos_Nesta_Vela==false)
         {
            PRC = NormalizeDouble(ultimoTick.bid, _Digits);
            STL = NormalizeDouble(PRC + stopLoss, _Digits);
            TKP = NormalizeDouble(PRC - takeProfit, _Digits);
            if(trade.Sell(Contratos, _Symbol, PRC, STL, TKP, ""))
              
               Hora_Ultimo_Negocio=TimeToString(TimeCurrent(),TIME_SECONDS);
    
                  Operamos_Nesta_Vela=true; 
         }
              
}
  
//---
//---
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());
                                 }
                           }
                     }
               }
         }
   }
//+------------------------------------------------------------------+
//| Verifica se o intervalo para o próximo trade foi cumprido        |
//+------------------------------------------------------------------+
bool CheckTradePause(int nBars)
  {
   //--- Determina quantas barras até o próximo trade
   datetime time_start = iTime(_Symbol, PERIOD_CURRENT, nBars);

   if(HistorySelect(time_start, TimeCurrent()))
     {
      for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
        {
         const ulong Ticket = HistoryDealGetTicket(i);

         if(HistoryDealGetString(Ticket, DEAL_SYMBOL) == _Symbol && HistoryDealGetInteger(Ticket, DEAL_MAGIC) == magicNum)
           {return(false);}
        }
     }
   else
     {
      Print("Erro ao recuperar o histórico de operações ...");
      return(false);
     }

   //--- Intervalo cumprido
   return(true);
  }
 
Vinicius de Oliveira:

Bom dia!


Seria assim para aguardar, no mínimo, 1 candle após o encerramento de uma posição:

Bom dia!!!!! Resolveu meu problema, meu amigo! 
MUUUUITO OBRIGADO!
 
savio95:
Bom dia!!!!! Resolveu meu problema, meu amigo! 
MUUUUITO OBRIGADO!

🤝