LIMITAR ENTRADAS APÓS ATINGIR TAKE PROFIT
- 2021.05.13
- www.mql5.com
Bom dia!
Veja se esse exemplo ajuda:
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.
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.
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.
Mas não consegui implementar aquela função no meu EA ainda.
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); }
Bom dia!!!!! Resolveu meu problema, meu amigo!
MUUUUITO OBRIGADO!
🤝
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.