//+------------------------------------------------------------------+ //| SMA21_EMA50_EA.mq4 | //| Exemplo base para MetaTrader 4 | //+------------------------------------------------------------------+ #property strict //---- Inputs input double Lots = 0.10; input int StopBufferPoints = 50; // buffer extra em pontos abaixo/acima das medias input int Slippage = 5; input int MagicNumber = 21050; input bool UseTakeProfit = false; input int TakeProfitPoints = 200; input int MaxSpreadPoints = 50; //---- Controle de novo candle datetime lastBarTime = 0; //+------------------------------------------------------------------+ //| Função: verifica se há ordem aberta no símbolo | //+------------------------------------------------------------------+ bool HasOpenPosition(string symb) { for(int i = OrdersTotal() - 1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == symb && OrderMagicNumber() == MagicNumber) { if(OrderType() == OP_BUY || OrderType() == OP_SELL) return true; } } } return false; } //+------------------------------------------------------------------+ //| Função: retorna spread em pontos | //+------------------------------------------------------------------+ int GetSpreadPoints() { return (int)((Ask - Bid) / Point); } //+------------------------------------------------------------------+ //| Função: detectar novo candle | //+------------------------------------------------------------------+ bool IsNewBar() { datetime currentBarTime = Time[0]; if(currentBarTime != lastBarTime) { lastBarTime = currentBarTime; return true; } return false; } //+------------------------------------------------------------------+ //| Função: calcula SMA21 e EMA50 | //+------------------------------------------------------------------+ void GetMAs(int shift, double &sma21, double &ema50) { sma21 = iMA(Symbol(), 0, 21, 0, MODE_SMA, PRICE_CLOSE, shift); ema50 = iMA(Symbol(), 0, 50, 0, MODE_EMA, PRICE_CLOSE, shift); } //+------------------------------------------------------------------+ //| Função: abre compra | //+------------------------------------------------------------------+ bool OpenBuy(double stopLoss, double takeProfit) { double price = NormalizeDouble(Ask, Digits); int ticket = OrderSend(Symbol(), OP_BUY, Lots, price, Slippage, stopLoss, takeProfit, "SMA21_EMA50 Buy", MagicNumber, 0, clrBlue); if(ticket < 0) { Print("Erro ao abrir BUY. Código: ", GetLastError()); return false; } Print("BUY aberto com sucesso. Ticket: ", ticket); return true; } //+------------------------------------------------------------------+ //| Função: abre venda | //+------------------------------------------------------------------+ bool OpenSell(double stopLoss, double takeProfit) { double price = NormalizeDouble(Bid, Digits); int ticket = OrderSend(Symbol(), OP_SELL, Lots, price, Slippage, stopLoss, takeProfit, "SMA21_EMA50 Sell", MagicNumber, 0, clrRed); if(ticket < 0) { Print("Erro ao abrir SELL. Código: ", GetLastError()); return false; } Print("SELL aberto com sucesso. Ticket: ", ticket); return true; } //+------------------------------------------------------------------+ //| Função principal | //+------------------------------------------------------------------+ void OnTick() { // trabalha apenas em novo candle if(!IsNewBar()) return; // checa spread if(GetSpreadPoints() > MaxSpreadPoints) { Print("Spread alto demais: ", GetSpreadPoints(), " pontos."); return; } // se já existe operação, não faz nada if(HasOpenPosition(Symbol())) { Print("Já existe posição aberta. Nenhuma nova operação será executada."); return; } // pega valores das medias no candle fechado double sma21_1, ema50_1; double sma21_0, ema50_0; GetMAs(1, sma21_1, ema50_1); // candle fechado GetMAs(0, sma21_0, ema50_0); // candle atual // dados do candle atual double open0 = Open[0]; double close1 = Close[1]; double high0 = High[0]; double low0 = Low[0]; // regra de compra: // candle atual abre acima das duas medias if(open0 > sma21_0 && open0 > ema50_0) { double stopRef = MathMin(sma21_0, ema50_0); double sl = NormalizeDouble(stopRef - StopBufferPoints * Point, Digits); double tp = 0; if(UseTakeProfit) tp = NormalizeDouble(Ask + TakeProfitPoints * Point, Digits); // evita stop inválido if(sl >= Ask) { Print("Stop loss inválido para BUY. SL >= preço de entrada."); return; } OpenBuy(sl, tp); return; } // regra de venda: // candle atual abre abaixo das duas medias if(open0 < sma21_0 && open0 < ema50_0) { double stopRef = MathMax(sma21_0, ema50_0); double sl = NormalizeDouble(stopRef + StopBufferPoints * Point, Digits); double tp = 0; if(UseTakeProfit) tp = NormalizeDouble(Bid - TakeProfitPoints * Point, Digits); // evita stop inválido if(sl <= Bid) { Print("Stop loss inválido para SELL. SL <= preço de entrada."); return; } OpenSell(sl, tp); return; } }