#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

// ---- ADX Inputs ----
input int ADXPeriod = 14; // ADX Period

// ---- CCI Inputs ----
input int CCI_Period = 14; // Período do CCI

// ---- Spread Maximum ----
input double MaxSpread = 30.0; // Maximum spread in points

// ---- GLOBAL VARIABLES ----
int handleIchimoku;
int handleStochastic;
int handleSAR;
int handleBollinger;
int handleRsi;
int handleAtr;
int handleADX; // Handle for ADX
int handleCCI; // Handle for CCI
int handleSMA200;
int handleSMA20;

double Tenkan[], Kijun[], SenkouSpanA[], SenkouSpanB[], Chikou[];
double StochasticK[], StochasticD[];
double SAR[];
double BollingerUpper[], BollingerMiddle[], BollingerLower[];
double RsiBuffer[];
double AtrBuffer[];
double ADXBuffer[]; // Buffer for ADX
double CCIBuffer[]; // Buffer for CCI
double SMA200[];
double SMA20[];

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);
    handleADX = iADX(_Symbol, Period(), ADXPeriod); // Initialize ADX
    handleCCI = iCCI(_Symbol, Period(), CCI_Period, PRICE_TYPICAL); // Initialize CCI
    handleSMA200 = iMA(_Symbol, Period(), 200, 0, MODE_SMA, PRICE_CLOSE);
    handleSMA20 = iMA(_Symbol, Period(), 20, 0, MODE_SMA, PRICE_CLOSE);
    
    return(INIT_SUCCEEDED);
}

// ---- EXPERT DEINIT ----
void OnDeinit(const int reason)
{
    IndicatorRelease(handleIchimoku);
    IndicatorRelease(handleStochastic);
    IndicatorRelease(handleSAR);
    IndicatorRelease(handleBollinger);
    IndicatorRelease(handleRsi);
    IndicatorRelease(handleAtr);
    IndicatorRelease(handleADX); // Release ADX handle
    IndicatorRelease(handleCCI); // Release CCI handle
    IndicatorRelease(handleSMA200);
    IndicatorRelease(handleSMA20);
}

// ---- 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);
        double spread = (ask - bid) / _Point;

        // Verificar spread máximo
        if(spread > MaxSpread)
        {
            Print(__FUNCTION__, " > Spread too high: ", spread, " points");
            return;
        }

        // 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);

        // Copiar os dados do ADX
        CopyBuffer(handleADX, 0, 0, 1, ADXBuffer); // ADX

        // Copiar os dados do CCI
        CopyBuffer(handleCCI, 0, 0, 1, CCIBuffer); // CCI

        // Copiar os dados do SMA de 200 períodos
        CopyBuffer(handleSMA200, 0, 0, 1, SMA200);

        // Copiar os dados do SMA de 20 períodos
        CopyBuffer(handleSMA20, 0, 0, 1, SMA20);

        // 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;

        // Calcular a diferença percentual entre as médias móveis de 20 e 200 períodos
        double smaDistance = (SMA20[0] - SMA200[0]) / SMA200[0] * 100;

        // Limite para diferença percentual (exemplo: 2% - ajustado para ser mais rigoroso)
        double smaThreshold = 2.0;

        // Sinal de VENDA
        if(!hasOpenPosition && smaDistance < smaThreshold && Tenkan[0] < Kijun[0] && bid < SenkouSpanA[0]
            && StochasticK[0] > StochasticD[0] && StochasticK[0] > 80 && bid > SAR[0]
            && bid > BollingerMiddle[0] && atr < volatilityThreshold
            && SMA20[0] < SMA200[0] && bid < SMA200[0] 
            && RsiBuffer[0] < RsiOverbought && ADXBuffer[0] > 20 && CCIBuffer[0] > 100) // ADX e CCI como filtros
        {
            Print(__FUNCTION__, " > SELL Signal...");
            trade.Sell(Lots, _Symbol, 0, bid + StopLossPoints * _Point, bid - TpPoints * _Point);
        }
        
        // Sinal de COMPRA
        else if(!hasOpenPosition && smaDistance < smaThreshold && Tenkan[0] > Kijun[0] && bid > SenkouSpanA[0]
            && StochasticK[0] < StochasticD[0] && StochasticK[0] < 20 && bid < SAR[0]
            && bid < BollingerMiddle[0] && atr < volatilityThreshold
            && SMA20[0] > SMA200[0] && bid > SMA200[0]
            && RsiBuffer[0] > RsiOversold && ADXBuffer[0] > 20 && CCIBuffer[0] < -100) // ADX e CCI como filtros
        {
            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);

            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),
            "\nADX: ", DoubleToString(ADXBuffer[0], 5), // Exibir o valor do ADX
            "\nCCI: ", DoubleToString(CCIBuffer[0], 5), // Exibir o valor do CCI
            "\nSMA 200: ", DoubleToString(SMA200[0], 5),
            "\nSMA 20: ", DoubleToString(SMA20[0], 5),
            "\nPoints Buy: ", pointsBuy,
            "\nPoints Sell: ", pointsSell);
}

o indicador SAR esta trabalhando em confluencia com os outros indicadores?
me explique en detalhes