2024.07.30 02:14:59.732	2024.01.03 17:33:16   failed market sell 0.1 EURUSD sl: 1.09096 tp: 1.09066 [Invalid stops]
2024.07.30 02:14:59.732	2024.01.03 17:33:16   Erro ao abrir ordem com modo de preenchimento 1: 4756
2024.07.30 02:14:59.732	2024.01.03 17:33:16   failed market sell 0.1 EURUSD sl: 1.09096 tp: 1.09066 [Unsupported filling mode]
2024.07.30 02:14:59.732	2024.01.03 17:33:16   Erro ao abrir ordem com modo de preenchimento 2: 4756
2024.07.30 02:14:59.732	2024.01.03 17:33:16   failed market sell 0.1 EURUSD sl: 1.09096 tp: 1.09066 [Unsupported filling mode]
2024.07.30 02:14:59.732	2024.01.03 17:33:16   Erro ao abrir ordem com modo de preenchimento 0: 4756
2024.07.30 02:14:59.732	2024.01.03 17:33:16   Erro: Todos os modos de preenchimento falharam.
2024.07.30 02:14:59.732	2024.01.03 17:33:16   failed market sell 0.1 EURUSD sl: 1.09095 tp: 1.09065 [Invalid stops]
2024.07.30 02:14:59.732	2024.01.03 17:33:16   Erro ao abrir ordem com modo de preenchimento 1: 4756
2024.07.30 02:14:59.732	2024.01.03 17:33:16   failed market sell 0.1 EURUSD sl: 1.09095 tp: 1.09065 [Unsupported filling mode]
2024.07.30 02:14:59.732	2024.01.03 17:33:16   Erro ao abrir ordem com modo de preenchimento 2: 4756


//±-----------------------------------------------------------------+
//|                                                    ScalpingEA.mq5|
//|                        Copyright 2024, MetaTrader 5 User         |
//|                                              www.mql5.com        |
//±-----------------------------------------------------------------+
input double lotSize = 0.1;              // Tamanho do lote
input int emaPeriod = 5;                 // Período da EMA
input int smaPeriod = 20;                // Período da SMA
input int rsiPeriod = 14;                // Período do RSI
input int bollingerPeriod = 20;          // Período das Bandas de Bollinger
input double bollingerDeviation = 2.0;   // Desvio padrão das Bandas de Bollinger
input int stopLossPips = 10;             // Stop Loss em pips
input int takeProfitPips = 20;           // Take Profit em pips

int emaHandle;
int smaHandle;
int rsiHandle;
int bollingerHandle;

//±-----------------------------------------------------------------+
//| Expert initialization function                                   |
//±-----------------------------------------------------------------+
int OnInit()
{
   // Inicializa os indicadores
   emaHandle = iMA(_Symbol, _Period, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
   smaHandle = iMA(_Symbol, _Period, smaPeriod, 0, MODE_SMA, PRICE_CLOSE);
   rsiHandle = iRSI(_Symbol, _Period, rsiPeriod, PRICE_CLOSE);
   bollingerHandle = iBands(_Symbol, _Period, bollingerPeriod, 0, bollingerDeviation, PRICE_CLOSE);

   if (emaHandle == INVALID_HANDLE || smaHandle == INVALID_HANDLE || rsiHandle == INVALID_HANDLE || bollingerHandle == INVALID_HANDLE)
   {
      Print("Erro ao criar handles dos indicadores");
      return INIT_FAILED;
   }

   return INIT_SUCCEEDED;
}

//±-----------------------------------------------------------------+
//| Expert deinitialization function                                 |
//±-----------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Libera os handles dos indicadores
   IndicatorRelease(emaHandle);
   IndicatorRelease(smaHandle);
   IndicatorRelease(rsiHandle);
   IndicatorRelease(bollingerHandle);
}

//±-----------------------------------------------------------------+
//| Expert tick function                                             |
//±-----------------------------------------------------------------+
void OnTick()
{
   double emaValue, smaValue, rsiValue;
   double bollingerUpperValue, bollingerLowerValue;

   // Arrays temporários para receber os valores dos indicadores
   double emaArray[1], smaArray[1], rsiArray[1];
   double bollingerUpperArray[1], bollingerLowerArray[1];

   // Atualiza os valores dos indicadores
   if (CopyBuffer(emaHandle, 0, 0, 1, emaArray) <= 0 ||
       CopyBuffer(smaHandle, 0, 0, 1, smaArray) <= 0 ||
       CopyBuffer(rsiHandle, 0, 0, 1, rsiArray) <= 0 ||
       CopyBuffer(bollingerHandle, 1, 0, 1, bollingerUpperArray) <= 0 ||
       CopyBuffer(bollingerHandle, 2, 0, 1, bollingerLowerArray) <= 0)
   {
      Print("Erro ao atualizar valores dos indicadores");
      return;
   }

   emaValue = emaArray[0];
   smaValue = smaArray[0];
   rsiValue = rsiArray[0];
   bollingerUpperValue = bollingerUpperArray[0];
   bollingerLowerValue = bollingerLowerArray[0];

   double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   // Verifica se já existe uma posição aberta
   if (PositionsTotal() == 0)
   {
      // Condições de Compra
      if (emaValue > smaValue && rsiValue < 70 && currentPrice < bollingerUpperValue)
      {
         OpenOrder(ORDER_TYPE_BUY, lotSize, stopLossPips, takeProfitPips);
      }

      // Condições de Venda
      if (emaValue < smaValue && rsiValue > 30 && currentPrice > bollingerLowerValue)
      {
         OpenOrder(ORDER_TYPE_SELL, lotSize, stopLossPips, takeProfitPips);
      }
   }
}

//±-----------------------------------------------------------------+
//| Função para abrir ordens                                         |
//±-----------------------------------------------------------------+
void OpenOrder(int tradeType, double tradeLotSize, int slPipDistance, int tpPipDistance)
{
   MqlTradeRequest request;
   MqlTradeResult result;

   double price, sl, tp;
   
   if (tradeType == ORDER_TYPE_BUY)
   {
      price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      sl = price - slPipDistance * _Point;
      tp = price + tpPipDistance * _Point;
   }
   else
   {
      price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      sl = price + slPipDistance * _Point;
      tp = price - tpPipDistance * _Point;
   }

   // Verifica se os valores SL e TP são válidos
   double stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
   double freezeLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * _Point;
   double minStopDistance = MathMax(stopLevel, freezeLevel);

   if ((tradeType == ORDER_TYPE_BUY && (sl > price - minStopDistance || tp < price + minStopDistance)) ||
       (tradeType == ORDER_TYPE_SELL && (sl < price + minStopDistance || tp > price - minStopDistance)))
   {
      Print("Invalid stops ajustados: ", "Preço=", price, " SL=", sl, " TP=", tp, " StopLevel=", stopLevel, " FreezeLevel=", freezeLevel);
      return;
   }

   ZeroMemory(request);
   ZeroMemory(result);

   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = tradeLotSize;
   request.type = tradeType;
   request.price = price;
   request.sl = sl;
   request.tp = tp;
   request.deviation = 3;

   // Tentar abrir a ordem com os modos de preenchimento disponíveis
   int fillingModes[] = { ORDER_FILLING_IOC, ORDER_FILLING_RETURN, ORDER_FILLING_FOK };
   for (int i = 0; i < ArraySize(fillingModes); i++)
   {
      request.type_filling = fillingModes[i];
      if (OrderSend(request, result))
      {
         Print("Ordem aberta com sucesso: Tipo=", tradeType, " Lote=", tradeLotSize, " Preço=", price, " SL=", sl, " TP=", tp, " Preenchimento=", fillingModes[i]);
         return;
      }
      else
      {
         Print("Erro ao abrir ordem com modo de preenchimento ", fillingModes[i], ": ", GetLastError());
      }
   }

   Print("Erro: Todos os modos de preenchimento falharam.");
}