#include <Trade/Trade.mqh>

// ---- INPUTS ----
input group "--- Trading Inputs ---";
input double Lots = 0.01; // Lot Size
input int TpPoints = 50; // Take Profit in points [m5-50p, h1-200p]
input int StopLossPoints = 65000; // Stop Loss in points
input ENUM_TIMEFRAMES IchimokuTimeFrame = PERIOD_CURRENT; // Timeframe (will use current timeframe)

// ---- Ichimoku Inputs ----
input int TenkanPeriod = 9; // Tenkan-sen Period
input int KijunPeriod = 26; // Kijun-sen Period
input int SenkouSpanBPeriod = 52; // Senkou Span B Period
input int Displacement = 26; // Displacement

// ---- Stochastic Inputs ----
input int StochasticKPeriod = 5; // %K period
input int StochasticDPeriod = 3; // %D period
input int StochasticSlowing = 3; // Slowing for the Stochastic

// ---- Parabolic SAR Inputs ----
input double SARStep = 0.02; // Parabolic SAR Step
input double SARMaximum = 0.2; // Parabolic SAR Maximum

// ---- Bollinger Bands Inputs ----
input int BollingerPeriod = 20; // Bollinger Bands Period
input double BollingerDeviation = 2.0; // Bollinger Bands Deviation

// ---- RSI Inputs ----
input int RsiPeriod = 14; // RSI Period
input double RsiOverbought = 70.0; // RSI Overbought Level
input double RsiOversold = 30.0; // RSI Oversold Level

// ---- ATR Inputs ----
input int AtrPeriod = 14; // ATR Period
input double AtrMultiplier = 1.5; // ATR Multiplier for volatility filter

// ---- GLOBAL VARIABLES ----
int handleIchimoku;
int handleStochastic;
int handleSAR;
int handleBollinger;
int handleRsi;
int handleAtr;

double Tenkan[], Kijun[], SenkouSpanA[], SenkouSpanB[], Chikou[];
double StochasticK[], StochasticD[];
double SAR[];
double BollingerUpper[], BollingerMiddle[], BollingerLower[];
double RsiBuffer[];
double AtrBuffer[];

CTrade trade;

int barsTotal;

// ---- EXPERT INIT ----
int OnInit()
{
    handleIchimoku = iIchimoku(_Symbol, Period(), TenkanPeriod, KijunPeriod, SenkouSpanBPeriod);
    handleStochastic = iStochastic(_Symbol, Period(), StochasticKPeriod, StochasticDPeriod, StochasticSlowing, MODE_SMA, STO_LOWHIGH);
    handleSAR = iSAR(_Symbol, Period(), SARStep, SARMaximum);
    handleBollinger = iBands(_Symbol, Period(), BollingerPeriod, BollingerDeviation, 0, PRICE_CLOSE);
    handleRsi = iRSI(_Symbol, Period(), RsiPeriod, PRICE_CLOSE);
    handleAtr = iATR(_Symbol, Period(), AtrPeriod);
    
    return(INIT_SUCCEEDED);
}

// ---- EXPERT DEINIT ----
void OnDeinit(const int reason)
{
    IndicatorRelease(handleIchimoku);
    IndicatorRelease(handleStochastic);
    IndicatorRelease(handleSAR);
    IndicatorRelease(handleBollinger);
    IndicatorRelease(handleRsi);
    IndicatorRelease(handleAtr);
}

// ---- ON TICK FUNCTION ----
void OnTick()
{
    int bars = iBars(_Symbol, Period());
    if(barsTotal != bars)
    {
        barsTotal++;
        double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

        // Copiar os dados do Ichimoku
        CopyBuffer(handleIchimoku, 0, 0, 1, Tenkan); // Tenkan-sen
        CopyBuffer(handleIchimoku, 1, 0, 1, Kijun);  // Kijun-sen
        CopyBuffer(handleIchimoku, 2, 0, 1, SenkouSpanA); // Senkou Span A
        CopyBuffer(handleIchimoku, 3, 0, 1, SenkouSpanB); // Senkou Span B
        CopyBuffer(handleIchimoku, 4, 0, 1, Chikou); // Chikou Span

        // Copiar os dados do Estocástico
        CopyBuffer(handleStochastic, 0, 0, 1, StochasticK); // %K
        CopyBuffer(handleStochastic, 1, 0, 1, StochasticD); // %D

        // Copiar os dados do Parabolic SAR
        CopyBuffer(handleSAR, 0, 0, 1, SAR);

        // Copiar os dados das Bandas de Bollinger
        CopyBuffer(handleBollinger, 0, 0, 1, BollingerUpper);  // Upper Band
        CopyBuffer(handleBollinger, 1, 0, 1, BollingerMiddle); // Middle Band
        CopyBuffer(handleBollinger, 2, 0, 1, BollingerLower);  // Lower Band

        // Copiar os dados do RSI
        CopyBuffer(handleRsi, 0, 0, 1, RsiBuffer);

        // Copiar os dados do ATR
        CopyBuffer(handleAtr, 0, 0, 1, AtrBuffer);

        // Verificar se já existem posições abertas
        bool hasOpenPosition = false;
        for(int i = 0; i < PositionsTotal(); i++)
        {
            ulong posTicket = PositionGetTicket(i);
            if(PositionSelectByTicket(posTicket) && PositionGetString(POSITION_SYMBOL) == _Symbol)
            {
                hasOpenPosition = true;
                break;
            }
        }

        // Filtro de volatilidade
        double atr = AtrBuffer[0];
        double volatilityThreshold = atr * AtrMultiplier;

        // Sinal de VENDA
        if(!hasOpenPosition && Tenkan[0] < Kijun[0] && bid < SenkouSpanA[0] && StochasticK[0] > StochasticD[0] && StochasticK[0] > 80 && bid > SAR[0]
            && bid > BollingerMiddle[0] && RsiBuffer[0] < RsiOverbought && atr < volatilityThreshold)
        {
            Print(__FUNCTION__, " > SELL Signal...");
            trade.Sell(Lots, _Symbol, 0, bid + StopLossPoints * _Point, bid - TpPoints * _Point);
        }
        // Sinal de COMPRA
        else if(!hasOpenPosition && Tenkan[0] > Kijun[0] && bid > SenkouSpanA[0] && StochasticK[0] < StochasticD[0] && StochasticK[0] < 20 && bid < SAR[0]
            && bid < BollingerMiddle[0] && RsiBuffer[0] > RsiOversold && atr < volatilityThreshold)
        {
            Print(__FUNCTION__, " > BUY Signal...");
            trade.Buy(Lots, _Symbol, 0, ask - StopLossPoints * _Point, ask + TpPoints * _Point);
        }
    }

    // Loop para verificar as posições abertas e o Take Profit
    int pointsBuy = 0;
    int pointsSell = 0;
    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong posTicket = PositionGetTicket(i);
        if(PositionSelectByTicket(posTicket))
        {
            ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);
            double posOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);

            double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            if(posType == POSITION_TYPE_BUY)
                pointsBuy += (int)((bid - posOpenPrice) / _Point);
            else if(posType == POSITION_TYPE_SELL)
                pointsSell += (int)((posOpenPrice - ask) / _Point);
        }
    }

    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong posTicket = PositionGetTicket(i);
        if(PositionSelectByTicket(posTicket))
        {
            ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE);

            if(pointsBuy > TpPoints)
            {
                // Fechar posições de compra
                if(posType == POSITION_TYPE_BUY)
                    trade.PositionClose(posTicket);
            }
            if(pointsSell > TpPoints)
            {
                // Fechar posições de venda
                if(posType == POSITION_TYPE_SELL)
                    trade.PositionClose(posTicket);
            }
        }
    }

    Comment("\nTenkan-sen: ", DoubleToString(Tenkan[0], 5),
            "\nKijun-sen: ", DoubleToString(Kijun[0], 5),
            "\nSenkou Span A: ", DoubleToString(SenkouSpanA[0], 5),
            "\nSenkou Span B: ", DoubleToString(SenkouSpanB[0], 5),
            "\nChikou: ", DoubleToString(Chikou[0], 5),
            "\nStochastic %K: ", DoubleToString(StochasticK[0], 5),
            "\nStochastic %D: ", DoubleToString(StochasticD[0], 5),
            "\nParabolic SAR: ", DoubleToString(SAR[0], 5),
            "\nBollinger Upper: ", DoubleToString(BollingerUpper[0], 5),
            "\nBollinger Middle: ", DoubleToString(BollingerMiddle[0], 5),
            "\nBollinger Lower: ", DoubleToString(BollingerLower[0], 5),
            "\nRSI: ", DoubleToString(RsiBuffer[0], 5),
            "\nATR: ", DoubleToString(AtrBuffer[0], 5),
            "\nPoints Buy: ", pointsBuy,
            "\nPoints Sell: ", pointsSell);
}



todos indicadores estao trabalhando em confluencia ?
para um decição de abertura de ordens?