#include <Trade\Trade.mqh>

input double lotSize = 0.1;

// Variáveis globais para controle de ordens
bool orderOpened = false;
ulong orderTicket = 0;

// Variáveis para armazenar rompimento anterior
bool lastBreakoutAlta = false;
bool lastBreakoutBaixa = false;
double breakoutHigh = 0.0;
double breakoutLow = 0.0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Configurações do EA
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Função de finalização
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    // Variáveis para bandas de Bollinger
    double bollingerUpper[], bollingerLower[], bollingerMiddle[];

    // Configurações das Bandas de Bollinger
    int bbPeriod = 20;
    double bbDeviation = 2.0;

    // Obtenção das Bandas de Bollinger
    int bbHandle = iBands(_Symbol, PERIOD_M2, bbPeriod, bbDeviation, 0, PRICE_CLOSE);

    // Verifique se o handle é válido
    if (bbHandle == INVALID_HANDLE) {
        Print("Erro ao obter handle das Bandas de Bollinger: ", GetLastError());
        return;
    }

    // Inicializar os buffers das bandas de Bollinger
    ArraySetAsSeries(bollingerUpper, true);
    ArraySetAsSeries(bollingerMiddle, true);
    ArraySetAsSeries(bollingerLower, true);

    // Preencher os buffers
    if (CopyBuffer(bbHandle, 0, 0, 1, bollingerUpper) <= 0 ||
        CopyBuffer(bbHandle, 1, 0, 1, bollingerMiddle) <= 0 ||
        CopyBuffer(bbHandle, 2, 0, 1, bollingerLower) <= 0) {
        Print("Erro ao copiar buffer das Bandas de Bollinger: ", GetLastError());
        return;
    }

    // Preço atual e range da vela
    double priceHigh = iHigh(_Symbol, PERIOD_M2, 0);
    double priceLow = iLow(_Symbol, PERIOD_M2, 0);
    double priceClose = iClose(_Symbol, PERIOD_M2, 0);
    double range = priceHigh - priceLow;
    
    // Objeto para enviar ordens
    CTrade trade;

    // Verificar se há uma ordem aberta
    if (!orderOpened) {
        // Atualizar informações de rompimento e confirmação
        if (lastBreakoutAlta && priceClose > breakoutHigh)
        {
            double slBuy = priceClose - 10 * _Point; 
            if (trade.Buy(lotSize, _Symbol, slBuy))
            {
                orderOpened = true;
                orderTicket = trade.ResultOrder();
                Print("Ordem de compra aberta com sucesso após confirmação! Ticket: ", orderTicket);
                lastBreakoutAlta = false; 
            }
            else
            {
                Print("Erro ao abrir ordem de compra: ", trade.ResultRetcode(), " - ", GetLastError());
            }
        }

        if (lastBreakoutBaixa && priceClose < breakoutLow)
        {
            double slSell = priceClose + 10 * _Point; 
            if (trade.Sell(lotSize, _Symbol, slSell))
            {
                orderOpened = true;
                orderTicket = trade.ResultOrder();
                Print("Ordem de venda aberta com sucesso após confirmação! Ticket: ", orderTicket);
                lastBreakoutBaixa = false;
            }
            else
            {
                Print("Erro ao abrir ordem de venda: ", trade.ResultRetcode(), " - ", GetLastError());
            }
        }

        // Verificar rompimento de alta
        if (range >= 30 * _Point && priceClose > bollingerUpper[0]) {
            lastBreakoutAlta = true;
            breakoutHigh = priceHigh;
            Print("Possível rompimento de alta detectado.");
        }

        // Verificar rompimento de baixa
        if (range >= 30 * _Point && priceClose < bollingerLower[0]) {
            lastBreakoutBaixa = true;
            breakoutLow = priceLow;
            Print("Possível rompimento de baixa detectado.");
        }
    }

    // Fechar ordem se o preço estiver perto da linha do meio da Banda de Bollinger
    if (orderOpened)
    {
        if (priceClose >= bollingerMiddle[0] - 3 * _Point && priceClose <= bollingerMiddle[0] + 3 * _Point)
        {
            if (trade.PositionClose(orderTicket))
            {
                Print("Posição fechada porque o preço chegou perto da linha central da Banda de Bollinger.");
                orderOpened = false;
                orderTicket = 0;
            }
            else
            {
                Print("Erro ao fechar a posição: ", GetLastError());
            }
        }
    }

    // Gerenciamento de trailing stop
    ManageTrailingStop();
}

//+------------------------------------------------------------------+
//| Gerenciamento de trailing stop                                   |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
    CTrade trade;

    // Itera sobre todas as posições abertas
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong ticket = PositionGetTicket(i);
        if (ticket > 0 && PositionSelect(ticket))
        {
            double currentSL = PositionGetDouble(POSITION_SL);
            double currentTP = PositionGetDouble(POSITION_TP);
            double lastLow = iLow(_Symbol, PERIOD_M2, 1);
            double lastHigh = iHigh(_Symbol, PERIOD_M2, 1);

            // Verificar se é uma posição de compra aberta e atualizar Stop Loss
            if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            {
                if (lastLow > currentSL || currentSL == 0.0)
                {
                    trade.PositionModify(ticket, lastLow, currentTP);
                    Print("Stop Loss atualizado para posição de compra.");
                }
            }
            // Verificar se é uma posição de venda aberta e atualizar Stop Loss
            else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            {
                if (lastHigh < currentSL || currentSL == 0.0)
                {
                    trade.PositionModify(ticket, lastHigh, currentTP);
                    Print("Stop Loss atualizado para posição de venda.");
                }
            }
        }
    }
}


 vamos simplificar o codigo acima, invez de usar banda de bolinger vamos usar apenas uma media de SMA 20 periodos simples. e quando o preço cruzar acima da media de 20 e a vela que romper fechar acima da media de 20 e proxima vela fecha acima da maxima da vela anterior entao abra uma ordem de compra caso tenha alguma ordem em abertura ela sera fechada antes da abertura da nova ordem assim como ja acontece no codigo do robo,
e quando o preço cruzar abaixo da media de 20 e a vela que romper fechar abaixo da media de 20 e proxima vela fechar abaixo da maxima da vela anterior entao abra uma ordem de venda caso tenha alguma ordem em abertura ela sera fechada antes da abertura da nova ordem.