//+------------------------------------------------------------------+
//|                                          A! The Unpaid Intern.mq4|
//+------------------------------------------------------------------+
#property copyright "THIS IS FREE INDICATOR AND NOT FOR SELL"
#property link      "https://forex-station.com/something-interesting-from-chatgpt-ai-please-post-here-t8475939.html"
#property strict

//--- EA INPUTS
input group "Strategy Selection"
input bool   InpUseMartingale       = false;     // true = Use Martingale, false = Use Fixed Lot (Averaging)
input bool   InpUseRecoveryMode     = false;     // true = Close basket at break-even (recovers trade)
input bool   InpUseHedging          = false;     // true = Open opposite trades instead of layering
input bool   InpUseFullMargin       = false;     // DANGER: true = Ignore MaxLayers and use all margin

input group "Grid & Lot Settings"
input double InpLotSize             = 0.01;      // Initial/Fixed lot size
input int    InpGridStepPips        = 10;        // Pips in drawdown to trigger next trade
input int    InpMaxLayers           = 200;       // Safety limit for max trades (if UseFullMargin is false)
input double InpMartingaleMultiplier= 2.0;       // Lot multiplier if Martingale is true

input group "Take Profit Settings"
input bool   InpUseCurrencyTP       = False;     // Use currency TP? If false, uses Pips TP
input double InpTakeProfitTargetCurrency = 10.0; // Target profit in account currency (e.g., 10 USD)
input int    InpTakeProfitTargetPips     = 10;   // Target profit in pips from average price (if not hedging)

input group "Risk Management"
input bool   InpUseCandleSizeFilter = true;      // Enable candle size filter?
input int    InpMaxCandleSizePips   = 30;        // Max candle size in pips to allow new trades

input group "EA Identification"
input int    InpMagicNumber         = 13579;     // EA's unique Magic Number
input int    InpSlippage            = 3;         // Slippage in points
string InpComment             = "A! The Unpaid Intern"; // Comment for EA-managed trades

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   Print("A! The Unpaid Intern Initialized.");
   Print("--- STRATEGY ---");
   Print("Martingale: ", InpUseMartingale ? "ON" : "OFF (Averaging)");
   Print("Recovery Mode (Break-even): ", InpUseRecoveryMode ? "ON" : "OFF");
   Print("Hedging: ", InpUseHedging ? "ON" : "OFF");
   Print("Use Full Margin: ", InpUseFullMargin ? "ON (DANGEROUS)" : "OFF (Using MaxLayers)");
   if(!InpUseFullMargin) Print("Max Layers Limit: ", InpMaxLayers);
   Print("Candle Size Filter: ", InpUseCandleSizeFilter ? "ON" : "OFF");
   if(InpUseCandleSizeFilter) Print("Max Candle Size: ", InpMaxCandleSizePips, " pips");
   Print("----------------");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if(!IsTradeAllowed())
      return;

   // Manage the basket of trades on the current chart
   ManageTradeBasket();
}

//+------------------------------------------------------------------+
//| Manages the entire basket of trades on the chart                 |
//+------------------------------------------------------------------+
void ManageTradeBasket()
{
   // --- Step 1: Gather info about all managed trades on the chart ---
   int buyOrders = 0, sellOrders = 0;
   double buyLots = 0, sellLots = 0;
   double buyWeightedPrice = 0, sellWeightedPrice = 0;
   double totalProfit = 0;
   double lastBuyPrice = 0, lastSellPrice = 0;
   double lastBuyLots = 0, lastSellLots = 0;
   datetime lastBuyOpenTime = 0, lastSellOpenTime = 0;

   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         // This trade is part of our basket
         totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
      if(OrderSymbol()==_Symbol && OrderMagicNumber() == InpMagicNumber)
       {
         if(OrderType() == OP_BUY)
         {
            buyOrders++;
            buyLots += OrderLots();
            buyWeightedPrice += OrderOpenPrice() * OrderLots();
            if(OrderOpenTime() > lastBuyOpenTime)
            {
               lastBuyOpenTime = OrderOpenTime();
               lastBuyPrice = OrderOpenPrice();
               lastBuyLots = OrderLots();
            }
         }
         else if(OrderType() == OP_SELL)
         {
            sellOrders++;
            sellLots += OrderLots();
            sellWeightedPrice += OrderOpenPrice() * OrderLots();
            if(OrderOpenTime() > lastSellOpenTime)
            {
               lastSellOpenTime = OrderOpenTime();
               lastSellPrice = OrderOpenPrice();
               lastSellLots = OrderLots();
            }
         }
       }
      }
   }

   int totalBasketOrders = buyOrders + sellOrders;
   if(totalBasketOrders == 0) return; // No trades to manage

   // --- Step 2: Check for Take Profit ---
   double targetProfit = InpTakeProfitTargetCurrency;
   if(InpUseRecoveryMode)
   {
      targetProfit = 0.01; // Override to break-even
   }
   
   if(totalProfit >= targetProfit)
   {
      Print("Target profit of ", DoubleToString(targetProfit, 2), " met. Closing all ", totalBasketOrders, " trades.");
      CloseAllInBasket();
      return;
   }
   
   // Pips-based TP is complex with hedging, so we only set it if not hedging.
   if(!InpUseHedging && !InpUseCurrencyTP && !InpUseRecoveryMode)
   {
       SetPipsBasedTP(buyOrders, buyLots, buyWeightedPrice, sellOrders, sellLots, sellWeightedPrice);
   }


   // --- Step 3: Check to open a new trade ---
   // Check MaxLayers limit unless "UseFullMargin" is true
   if(!InpUseFullMargin && totalBasketOrders >= InpMaxLayers)
   {
      return;
   }

   // --- Check candle size filter ---
   if(InpUseCandleSizeFilter)
   {
      double currentCandleSizePips = GetCurrentCandleSizePips();
      if(currentCandleSizePips > InpMaxCandleSizePips)
      {
         Print("Candle size (", DoubleToString(currentCandleSizePips, 1), " pips) exceeds max limit (", InpMaxCandleSizePips, " pips). No new trade opened.");
         return;
      }
   }

   // --- Check BUY side for new grid/hedge trade ---
   if(buyOrders > 0)
   {
      double priceDifference = lastBuyPrice - Ask; // How much price has dropped since last buy
      if(priceDifference >= InpGridStepPips * Point * 10)
      {
         int    orderTypeForNextTrade = InpUseHedging ? OP_SELL : OP_BUY;
         double lotSizeForNextTrade = InpUseMartingale ? lastBuyLots * InpMartingaleMultiplier : InpLotSize;
         OpenNewTrade(orderTypeForNextTrade, lotSizeForNextTrade);
         return; // Only open one trade per tick
      }
   }

   // --- Check SELL side for new grid/hedge trade ---
   if(sellOrders > 0)
   {
      double priceDifference = Bid - lastSellPrice; // How much price has risen since last sell
      if(priceDifference >= InpGridStepPips * Point * 10)
      {
         int    orderTypeForNextTrade = InpUseHedging ? OP_BUY : OP_SELL;
         double lotSizeForNextTrade = InpUseMartingale ? lastSellLots * InpMartingaleMultiplier : InpLotSize;
         OpenNewTrade(orderTypeForNextTrade, lotSizeForNextTrade);
         return; // Only open one trade per tick
      }
   }
}

//+------------------------------------------------------------------+
//| Gets the current candle size in pips                             |
//+------------------------------------------------------------------+
double GetCurrentCandleSizePips()
{
   double high = iHigh(Symbol(), 0, 0);
   double low = iLow(Symbol(), 0, 0);
   double candleSizePoints = high - low;
   double candleSizePips = candleSizePoints / (Point * 10);
   return candleSizePips;
}

//+------------------------------------------------------------------+
//| Opens a new trade with specified logic                           |
//+------------------------------------------------------------------+
void OpenNewTrade(int orderType, double lotSize)
{
   double price = (orderType == OP_BUY) ? Ask : Bid;
   lotSize = NormalizeDouble(lotSize, 2); // Normalize lot size

   // Failsafe for lot size
   if(lotSize < MarketInfo(Symbol(), MODE_MINLOT)) lotSize = MarketInfo(Symbol(), MODE_MINLOT);
   if(lotSize > MarketInfo(Symbol(), MODE_MAXLOT)) lotSize = MarketInfo(Symbol(), MODE_MAXLOT);

   // Check if there is enough free margin
   if(AccountFreeMarginCheck(Symbol(), orderType, lotSize) <= 0)
   {
      Print("If You Know, You Know ", lotSize, " lots.");
      return;
   }

   int ticket = OrderSend(Symbol(), orderType, lotSize, price, InpSlippage, 0, 0, InpComment, InpMagicNumber, 0, clrNONE);
   if(ticket > 0)
   {
      Print("New trade opened successfully: Ticket #", ticket, ", ", (orderType == OP_BUY ? "BUY" : "SELL"), " ", lotSize, " @ ", price);
   }
   else
   {
      Print("Error opening new trade: ", GetLastError());
   }
}


//+------------------------------------------------------------------+
//| Sets Pips-based TP. Only effective when not hedging.             |
//+------------------------------------------------------------------+
void SetPipsBasedTP(int buyOrders, double buyLots, double buyWAP, int sellOrders, double sellLots, double sellWAP)
{
    // Set BUY basket TP
    if(buyOrders > 0)
    {
        double avgBuyPrice = buyWAP / buyLots;
        double tp = avgBuyPrice + InpTakeProfitTargetPips * Point * 10;
        SetBasketTakeProfit(OP_BUY, tp);
    }
    // Set SELL basket TP
    if(sellOrders > 0)
    {
        double avgSellPrice = sellWAP / sellLots;
        double tp = avgSellPrice - InpTakeProfitTargetPips * Point * 10;
        SetBasketTakeProfit(OP_SELL, tp);
    }
}


//+------------------------------------------------------------------+
//| Closes all managed orders on the current chart                   |
//+------------------------------------------------------------------+
void CloseAllInBasket()
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
         {
            bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), InpSlippage, clrNONE);
            if(!result)
               Print("Failed to close order #", OrderTicket(), ". Error: ", GetLastError());
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Sets a unified TP for a specific order type                      |
//+------------------------------------------------------------------+
void SetBasketTakeProfit(int orderType, double tpPrice)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderType() == orderType && OrderMagicNumber() == InpMagicNumber)
         {
            if(OrderTakeProfit() != tpPrice)
            {
               // --- FIX IS HERE ---
               // We now check if the modification was successful
               bool result = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tpPrice, 0, clrNONE);
               if(!result)
               {
                  Print("Failed to modify TP for order #", OrderTicket(), ". Error: ", GetLastError());
               }
               // --- END OF FIX ---
            }
         }
      }
   }
}
//+------------------------------------------------------------------+