//+------------------------------------------------------------------+
//| Expert Advisor for EMA, RSI, and ATR-based strategy             |
//+------------------------------------------------------------------+
input int EMA_Fast = 9;             // Fast EMA period
input int EMA_Low = 21;             // Low EMA period
input int RSI_Period = 14;          // RSI period
input double ATR_Period = 14;       // ATR period
input double ATR_Multiplier = 2.0;  // ATR multiplier for SL
input double Risk_Percent = 1.0;    // Risk percentage of account balance
input double TP_Multiplier = 2.0;   // Takeprofit multiplier based on SL
input double Partial_Close_R = 2.0; // R level to partially close position

// Variables
int ticket;
double SL, TP;
bool position_open = false; // To ensure only one trade at a time
bool rsi_below_50 = false; // Track RSI below 50 state
bool sl_moved_to_be = false; // Track if SL has been moved to BE
bool partial_closed = false; // Track if partial close is executed

//+------------------------------------------------------------------+
//| Custom Function: Calculate Lot Size                             |
//+------------------------------------------------------------------+
double CalculateLotSize(double stopLossPips)
{
   double riskAmount = AccountBalance() * Risk_Percent / 100.0;
   double calculatedLotSize = riskAmount / (stopLossPips * MarketInfo(Symbol(), MODE_TICKVALUE));
   return NormalizeDouble(calculatedLotSize, 2);
}

//+------------------------------------------------------------------+
//| OnTick Function: Main Trading Logic                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Calculate values based on the previous closed candle
   double emaFast = iMA(Symbol(), 0, EMA_Fast, 0, MODE_EMA, PRICE_CLOSE, 1);
   double emaLow = iMA(Symbol(), 0, EMA_Low, 0, MODE_EMA, PRICE_CLOSE, 1);
   double rsi = iRSI(Symbol(), 0, RSI_Period, PRICE_CLOSE, 1);
   double atr = iATR(Symbol(), 0, ATR_Period, 1);
   double lastClose = iClose(Symbol(), 0, 1);
   double stopLossPips = ATR_Multiplier * atr / Point;

   // Check if there is an open position
   if (OrdersTotal() > 0) {
      for (int i = 0; i < OrdersTotal(); i++) {
         if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderSymbol() == Symbol()) {
               position_open = true;

               // Partial close logic
               double openPrice = OrderOpenPrice();
               double currentProfit = (OrderType() == OP_BUY) ? (Bid - openPrice) / (stopLossPips * Point) : (openPrice - Ask) / (stopLossPips * Point);

               // Execute partial close first
               if (currentProfit >= Partial_Close_R && !partial_closed) {
                  double halfLots = NormalizeDouble(OrderLots() / 2.0, 2); // Half of the position size
                  if (OrderClose(OrderTicket(), halfLots, (OrderType() == OP_BUY) ? Bid : Ask, 3, clrYellow)) {
                     partial_closed = true;
                     Print("50% of the position closed successfully.");
                  } else {
                     Print("Failed to partially close position: ", GetLastError());
                  }
               }

               // Move SL to BE after partial close
               if (partial_closed && !sl_moved_to_be) {
                  SL = openPrice; // Move SL to entry price
                  if (OrderModify(OrderTicket(), openPrice, SL, OrderTakeProfit(), 0, clrGreen)) {
                     sl_moved_to_be = true;
                     Print("Stop loss moved to break-even.");
                  } else {
                     Print("Failed to move SL to BE: ", GetLastError());
                  }
               }
            }
         }
      }
   } else {
      position_open = false;
      partial_closed = false;
      sl_moved_to_be = false;
   }

   // Track RSI below 50
   if (rsi < 50) {
      rsi_below_50 = true; // Confirm RSI was below 50
   }

   // Entry conditions
   if (!position_open && Close[1] == lastClose) { // Ensure entry only on closed candle
      double lotSizeToUse;

      // Do not open positions if RSI <= 30 or RSI >= 70
      if (rsi <= 30 || rsi >= 70) {
         Print("RSI is in the extreme zone (<=30 or >=70), no entry allowed.");
         return;
      }

      // Sell Condition
      if (rsi_below_50 && rsi < 39 && emaFast < emaLow && lastClose < emaFast) {
         SL = Ask + stopLossPips * Point;
         TP = Ask - TP_Multiplier * stopLossPips * Point;
         lotSizeToUse = CalculateLotSize(stopLossPips);

         ticket = OrderSend(Symbol(), OP_SELL, lotSizeToUse, Bid, 3, SL, TP, "Sell Order", 0, 0, clrRed);
         if (ticket > 0) {
            position_open = true;
            rsi_below_50 = false; // Reset RSI tracking after entry
         } else {
            Print("Failed to send sell order: ", GetLastError());
         }
      }

      // Buy Condition
      if (rsi_below_50 && rsi > 61 && emaFast > emaLow && lastClose > emaFast) {
         SL = Bid - stopLossPips * Point;
         TP = Bid + TP_Multiplier * stopLossPips * Point;
         lotSizeToUse = CalculateLotSize(stopLossPips);

         ticket = OrderSend(Symbol(), OP_BUY, lotSizeToUse, Ask, 3, SL, TP, "Buy Order", 0, 0, clrBlue);
         if (ticket > 0) {
            position_open = true;
            rsi_below_50 = false; // Reset RSI tracking after entry
         } else {
            Print("Failed to send buy order: ", GetLastError());
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Initialization Function                                         |
//+------------------------------------------------------------------+
int OnInit()
{
   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Deinitialization Function                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+