//±-----------------------------------------------------------------+
//|                                                    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;
    request.type_filling = ORDER_FILLING_FOK;  // Usar um modo de preenchimento específico

    if (OrderSend(request, result))
    {
        Print("Ordem aberta com sucesso: Tipo=", tradeType, " Lote=", tradeLotSize, " Preço=", price, " SL=", sl, " TP=", tp, " Preenchimento=", request.type_filling);
    }
    else
    {
        Print("Erro ao abrir ordem: ", GetLastError());
    }
}


2024.07.30 04:37:27.742	2024.01.04 03:49:30   failed market sell 0.1 EURUSD sl: 1.09182 tp: 1.09152 [Unsupported filling mode]
2024.07.30 04:37:27.742	2024.01.04 03:49:30   Erro ao abrir ordem: 4756
2024.07.30 04:37:27.742	2024.01.04 03:49:31   failed market sell 0.1 EURUSD sl: 1.09181 tp: 1.09151 [Unsupported filling mode]
2024.07.30 04:37:27.742	2024.01.04 03:49:31   Erro ao abrir ordem: 4756
2024.07.30 04:37:27.742	2024.01.04 03:49:32   failed market sell 0.1 EURUSD sl: 1.09180 tp: 1.09150 [Unsupported filling mode]
2024.07.30 04:37:27.742	2024.01.04 03:49:32   Erro ao abrir ordem: 4756
2024.07.30 04:37:27.742	2024.01.04 03:49:34   failed market sell 0.1 EURUSD sl: 1.09179 tp: 1.09149 [Unsupported filling mode]
2024.07.30 04:37:27.742	2024.01.04 03:49:34   Erro ao abrir ordem: 4756
2024.07.30 04:37:27.742	2024.01.04 03:49:35   failed market sell 0.1 EURUSD sl: 1.09180 tp: 1.09150 [Unsupported filling mode]
2024.07.30 04:37:27.742	2024.01.04 03:49:35   Erro ao abrir ordem: 4756