//+------------------------------------------------------------------+
//|                                              MarketProfileAI.mq5 |
//|                                                Copyright JBRolim |
//|                                                        TraderMan |
//+------------------------------------------------------------------+
#property copyright "Copyright JBRolim"
#property link      "TraderMan"
#property version   "1.00"


#include <Trade/Trade.mqh>
#include <Arrays/ArrayObj.mqh>

// Create trade object
CTrade trade;

// External inputs for EA configuration
input double   LotSize = 0.1;              // Trading lot size
input int      MagicNumber = 12345;        // Unique identifier for EA trades
input int      TakeProfit = 100;           // Take profit in points
input int      StopLoss = 50;              // Stop loss in points
input bool     UseValueAreaStrategy = true; // Enable Value Area strategy
input bool     UsePOCStrategy = true;       // Enable Point of Control strategy
input int      ValueAreaPercentage = 70;    // Value Area percentage (typically 70%)
input bool     UseAlerts = true;           // Enable alert notifications
input int      ProfilePeriod = 24;         // Market profile period (hours)
input double   RiskPercent = 2.0;          // Risk percentage per trade
input bool     UseAdaptivePositionSize = true; // Adjust position size based on volatility
input int      MaxSpread = 5;              // Maximum allowed spread in points
input bool     CloseAtEndOfDay = false;    // Close all positions at end of day

// Global variables
double g_valueAreaHigh = 0;
double g_valueAreaLow = 0;
double g_pointOfControl = 0;
double g_valueAreaVolume = 0;
double g_totalVolume = 0;
int g_consecutiveWins = 0;
int g_consecutiveLosses = 0;
datetime g_lastProfileTime = 0;
double g_lastDailyRange = 0;
double g_averageRange = 0;
int g_totalTrades = 0;
double g_profitFactor = 1.0;
double g_winRate = 0.5;

// Indicator handles
int atrHandle;
int macdHandle;
int rsiHandle;
int adxHandle;
int bbHandle;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Set magic number for trade operations
   trade.SetExpertMagicNumber(MagicNumber);
   
   // Initialize indicator handles
   atrHandle = iATR(_Symbol, PERIOD_H1, 14);
   macdHandle = iMACD(_Symbol, PERIOD_H1, 12, 26, 9, PRICE_CLOSE);
   rsiHandle = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
   adxHandle = iADX(_Symbol, PERIOD_H1, 14);
   bbHandle = iBands(_Symbol, PERIOD_H1, 20, 2, 0, PRICE_CLOSE);
   
   if(atrHandle == INVALID_HANDLE || macdHandle == INVALID_HANDLE || 
      rsiHandle == INVALID_HANDLE || adxHandle == INVALID_HANDLE || 
      bbHandle == INVALID_HANDLE)
   {
      Print("Error initializing indicators");
      return INIT_FAILED;
   }
   
   // Display initialization message
   Print("MarketProfileAI EA initialized with Magic Number: ", MagicNumber);
   
   // Check if inputs are valid
   if(LotSize <= 0)
   {
      Print("Error: Invalid lot size. Must be greater than 0.");
      return INIT_PARAMETERS_INCORRECT;
   }
   
   if(TakeProfit < 0 || StopLoss < 0)
   {
      Print("Error: Take Profit and Stop Loss must be non-negative values.");
      return INIT_PARAMETERS_INCORRECT;
   }
   
   // Initialize market profile
   CalculateMarketProfile();
   
   // Load AI model weights (simulated in this version)
   if(!LoadAIModelWeights())
   {
      Print("Error: Failed to load AI model weights.");
      return INIT_FAILED;
   }
   
   // Calculate trading performance metrics
   CalculatePerformanceMetrics();
   
   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Release indicator handles
   IndicatorRelease(atrHandle);
   IndicatorRelease(macdHandle);
   IndicatorRelease(rsiHandle);
   IndicatorRelease(adxHandle);
   IndicatorRelease(bbHandle);
   
   // Cleanup and save settings
   Print("MarketProfileAI EA deinitialized. Reason code: ", reason);
   SaveAIModelWeights(); // Save learned weights for next session
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Skip processing if spread is too high
   if(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) > MaxSpread)
   {
      if(UseAlerts) Alert("Spread too high: ", SymbolInfoInteger(_Symbol, SYMBOL_SPREAD), " points");
      return;
   }
   
   // Calculate new market profile if needed (every ProfilePeriod hours)
   datetime currentTime = TimeCurrent();
   if(currentTime - g_lastProfileTime >= ProfilePeriod * 3600)
   {
      CalculateMarketProfile();
      g_lastProfileTime = currentTime;
   }
   
   // Close trades at end of day if enabled
   if(CloseAtEndOfDay && IsEndOfTradingDay())
   {
      CloseAllTrades();
      return;
   }
   
   // Check for trade management first (existing positions)
   ManageOpenTrades();
   
   // Only check for new trades if we don't have any open positions for this symbol
   if(!HasOpenTrade())
   {
      // Check entry conditions
      ENUM_ORDER_TYPE signalType = GetTradeSignal();
      
      if(signalType != -1) // If we have a valid signal
      {
         double adjustedLotSize = LotSize;
         
         // Adjust position size based on volatility if enabled
         if(UseAdaptivePositionSize)
         {
            adjustedLotSize = CalculateAdaptiveLotSize();
         }
         
         // Execute trade with proper risk management
         OpenTrade(signalType, adjustedLotSize);
      }
   }
   
   // Update performance metrics periodically
   if(g_totalTrades % 10 == 0)
   {
      CalculatePerformanceMetrics();
   }
}

//+------------------------------------------------------------------+
//| Calculate market profile values                                  |
//+------------------------------------------------------------------+
void CalculateMarketProfile()
{
   int bars = ProfilePeriod * 60; // Convert hours to minutes assuming 1-minute chart
   if(bars > Bars(_Symbol, PERIOD_M1)) bars = (int)Bars(_Symbol, PERIOD_M1);
   
   double priceArray[];
   double volumeArray[];
   ArrayResize(priceArray, bars);
   ArrayResize(volumeArray, bars);
   
   // Fill arrays with price and volume data
   for(int i = 0; i < bars; i++)
   {
      MqlRates rates[];
      if(CopyRates(_Symbol, PERIOD_M1, i, 1, rates) > 0)
      {
         priceArray[i] = (rates[0].high + rates[0].low + rates[0].close) / 3.0; // Typical price
         volumeArray[i] = (double)rates[0].tick_volume;
      }
   }
   
   // Sort price array
   ArraySort(priceArray);
   
   // Find Point of Control (price level with highest volume)
   double maxVolume = 0;
   int pocIndex = 0;
   
   for(int i = 0; i < bars; i++)
   {
      if(volumeArray[i] > maxVolume)
      {
         maxVolume = volumeArray[i];
         pocIndex = i;
      }
   }
   
   g_pointOfControl = priceArray[pocIndex];
   
   // Calculate total volume
   g_totalVolume = 0;
   for(int i = 0; i < bars; i++)
   {
      g_totalVolume += volumeArray[i];
   }
   
   // Calculate Value Area (typically 70% of total volume)
   g_valueAreaVolume = g_totalVolume * ValueAreaPercentage / 100.0;
   
   double currentVolume = volumeArray[pocIndex];
   int vaHighIndex = pocIndex;
   int vaLowIndex = pocIndex;
   
   // Extend value area up and down from POC until we reach ValueAreaPercentage
   while(currentVolume < g_valueAreaVolume && (vaHighIndex > 0 || vaLowIndex < bars - 1))
   {
      double volumeAbove = (vaHighIndex > 0) ? volumeArray[vaHighIndex - 1] : 0;
      double volumeBelow = (vaLowIndex < bars - 1) ? volumeArray[vaLowIndex + 1] : 0;
      
      if(volumeAbove > volumeBelow)
      {
         vaHighIndex--;
         currentVolume += volumeArray[vaHighIndex];
      }
      else
      {
         vaLowIndex++;
         currentVolume += volumeArray[vaLowIndex];
      }
   }
   
   g_valueAreaHigh = priceArray[vaHighIndex];
   g_valueAreaLow = priceArray[vaLowIndex];
   
   // Calculate daily range for position sizing
   MqlRates dailyRates[];
   if(CopyRates(_Symbol, PERIOD_D1, 0, 1, dailyRates) > 0)
   {
      g_lastDailyRange = dailyRates[0].high - dailyRates[0].low;
   }
   
   // Update exponential moving average of daily range
   double alpha = 0.2; // Smoothing factor
   g_averageRange = alpha * g_lastDailyRange + (1 - alpha) * g_averageRange;
   
   // Log the results
   Print("Market Profile Calculated - POC: ", g_pointOfControl, 
         " VAH: ", g_valueAreaHigh, " VAL: ", g_valueAreaLow);
         
   // Apply AI adjustments to the calculated levels
   ApplyAIAdjustments();
}

//+------------------------------------------------------------------+
//| Apply AI model adjustments to market profile levels              |
//+------------------------------------------------------------------+
void ApplyAIAdjustments()
{
   // Get indicator values
   double atr[], macd[], signal[], rsi[], adx[];
   
   ArraySetAsSeries(atr, true);
   ArraySetAsSeries(macd, true);
   ArraySetAsSeries(signal, true);
   ArraySetAsSeries(rsi, true);
   ArraySetAsSeries(adx, true);
   
   CopyBuffer(atrHandle, 0, 0, 1, atr);
   CopyBuffer(macdHandle, 0, 0, 1, macd);
   CopyBuffer(macdHandle, 1, 0, 1, signal);
   CopyBuffer(rsiHandle, 0, 0, 1, rsi);
   CopyBuffer(adxHandle, 0, 0, 1, adx);
   
   // Adjust Value Area High and Low based on trend strength
   if(adx[0] > 25) // Strong trend
   {
      if(macd[0] > signal[0]) // Uptrend
      {
         g_valueAreaHigh += atr[0] * 0.5;
         g_valueAreaLow += atr[0] * 0.2;
      }
      else // Downtrend
      {
         g_valueAreaHigh -= atr[0] * 0.2;
         g_valueAreaLow -= atr[0] * 0.5;
      }
   }
   
   // Adjust Point of Control based on RSI
   if(rsi[0] > 70) // Potentially overbought
   {
      g_pointOfControl -= atr[0] * 0.3;
   }
   else if(rsi[0] < 30) // Potentially oversold
   {
      g_pointOfControl += atr[0] * 0.3;
   }
   
   // Use AI to predict if we're in accumulation or distribution
   bool isAccumulation = (rsi[0] < 40 && adx[0] < 20);
   bool isDistribution = (rsi[0] > 60 && adx[0] < 20);
   
   if(isAccumulation)
   {
      // Tighten value area in accumulation
      double midpoint = (g_valueAreaHigh + g_valueAreaLow) / 2;
      g_valueAreaHigh = midpoint + (g_valueAreaHigh - midpoint) * 0.8;
      g_valueAreaLow = midpoint - (midpoint - g_valueAreaLow) * 0.8;
   }
   else if(isDistribution)
   {
      // Widen value area in distribution
      double midpoint = (g_valueAreaHigh + g_valueAreaLow) / 2;
      g_valueAreaHigh = midpoint + (g_valueAreaHigh - midpoint) * 1.2;
      g_valueAreaLow = midpoint - (midpoint - g_valueAreaLow) * 1.2;
   }
   
   Print("AI Adjusted Levels - POC: ", g_pointOfControl, 
         " VAH: ", g_valueAreaHigh, " VAL: ", g_valueAreaLow);
}

//+------------------------------------------------------------------+
//| Get trade signal based on price relation to key levels           |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetTradeSignal()
{
   double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   // Value Area strategy
   if(UseValueAreaStrategy)
   {
      // Buy when price returns to Value Area from below
      if(currentPrice > g_valueAreaLow && currentPrice < g_valueAreaLow + (g_pointOfControl - g_valueAreaLow) * 0.3)
      {
         if(IsPriceMovingUp())
         {
            return ORDER_TYPE_BUY;
         }
      }
      
      // Sell when price returns to Value Area from above
      if(currentPrice < g_valueAreaHigh && currentPrice > g_valueAreaHigh - (g_valueAreaHigh - g_pointOfControl) * 0.3)
      {
         if(IsPriceMovingDown())
         {
            return ORDER_TYPE_SELL;
         }
      }
   }
   
   // Point of Control strategy
   if(UsePOCStrategy)
   {
      // Buy when price bounces off the POC from above (support)
      if(MathAbs(currentPrice - g_pointOfControl) < 10 * point)
      {
         if(IsPriceMovingUp() && currentPrice > g_pointOfControl)
         {
            return ORDER_TYPE_BUY;
         }
         
         // Sell when price bounces off the POC from below (resistance)
         if(IsPriceMovingDown() && currentPrice < g_pointOfControl)
         {
            return ORDER_TYPE_SELL;
         }
      }
   }
   
   // Add AI-based trading signals
   int aiSignal = GetAISignal();
   if(aiSignal == 1) return ORDER_TYPE_BUY;
   if(aiSignal == -1) return ORDER_TYPE_SELL;
   
   return (ENUM_ORDER_TYPE)-1; // No valid signal
}

//+------------------------------------------------------------------+
//| Check if price is moving upward in the short term                |
//+------------------------------------------------------------------+
bool IsPriceMovingUp()
{
   double ema5[], ema20[];
   ArraySetAsSeries(ema5, true);
   ArraySetAsSeries(ema20, true);
   
   int ema5Handle = iMA(_Symbol, PERIOD_M5, 5, 0, MODE_EMA, PRICE_CLOSE);
   int ema20Handle = iMA(_Symbol, PERIOD_M5, 20, 0, MODE_EMA, PRICE_CLOSE);
   
   CopyBuffer(ema5Handle, 0, 0, 1, ema5);
   CopyBuffer(ema20Handle, 0, 0, 1, ema20);
   
   IndicatorRelease(ema5Handle);
   IndicatorRelease(ema20Handle);
   
   return (ema5[0] > ema20[0]);
}

//+------------------------------------------------------------------+
//| Check if price is moving downward in the short term              |
//+------------------------------------------------------------------+
bool IsPriceMovingDown()
{
   double ema5[], ema20[];
   ArraySetAsSeries(ema5, true);
   ArraySetAsSeries(ema20, true);
   
   int ema5Handle = iMA(_Symbol, PERIOD_M5, 5, 0, MODE_EMA, PRICE_CLOSE);
   int ema20Handle = iMA(_Symbol, PERIOD_M5, 20, 0, MODE_EMA, PRICE_CLOSE);
   
   CopyBuffer(ema5Handle, 0, 0, 1, ema5);
   CopyBuffer(ema20Handle, 0, 0, 1, ema20);
   
   IndicatorRelease(ema5Handle);
   IndicatorRelease(ema20Handle);
   
   return (ema5[0] < ema20[0]);
}

//+------------------------------------------------------------------+
//| Get AI model signal                                              |
//+------------------------------------------------------------------+
int GetAISignal()
{
   // Get indicator values
   double rsi[], macd[], signal[], atr[], bb_upper[], bb_lower[];
   
   ArraySetAsSeries(rsi, true);
   ArraySetAsSeries(macd, true);
   ArraySetAsSeries(signal, true);
   ArraySetAsSeries(atr, true);
   ArraySetAsSeries(bb_upper, true);
   ArraySetAsSeries(bb_lower, true);
   
   CopyBuffer(rsiHandle, 0, 0, 1, rsi);
   CopyBuffer(macdHandle, 0, 0, 1, macd);
   CopyBuffer(macdHandle, 1, 0, 1, signal);
   CopyBuffer(atrHandle, 0, 0, 1, atr);
   CopyBuffer(bbHandle, 1, 0, 1, bb_upper);
   CopyBuffer(bbHandle, 2, 0, 1, bb_lower);
   
   double current_price = SymbolInfoDouble(_Symbol, SYMBOL_LAST);
   
   // Calculate features
   double price_to_poc_distance = (current_price - g_pointOfControl) / atr[0];
   double price_relative_to_va = (current_price - g_valueAreaLow) / (g_valueAreaHigh - g_valueAreaLow);
   double price_to_bb = (current_price - bb_lower[0]) / (bb_upper[0] - bb_lower[0]);
   
   // Simple rule-based AI model (would be a neural network in production)
   int signal_strength = 0;
   
   // RSI conditions
   if(rsi[0] < 30) signal_strength += 1; // Oversold, bullish
   if(rsi[0] > 70) signal_strength -= 1; // Overbought, bearish
   
   // MACD conditions
   if(macd[0] > signal[0] && macd[0] > 0) signal_strength += 1; // Bullish
   if(macd[0] < signal[0] && macd[0] < 0) signal_strength -= 1; // Bearish
   
   // Price relative to Value Area
   if(price_relative_to_va < 0.3) signal_strength += 1; // Near lower Value Area, bullish
   if(price_relative_to_va > 0.7) signal_strength -= 1; // Near upper Value Area, bearish
   
   // Price relative to Bollinger Bands
   if(price_to_bb < 0.2) signal_strength += 1; // Near lower band, bullish
   if(price_to_bb > 0.8) signal_strength -= 1; // Near upper band, bearish
   
   // Incorporate EA performance into decision
   if(g_profitFactor < 1.0) 
   {
      // If strategy is losing, reduce signal strength
      signal_strength = (int)(signal_strength * 0.5);
   }
   
   // Return final signal
   if(signal_strength >= 2) return 1;  // Strong buy
   if(signal_strength <= -2) return -1; // Strong sell
   
   return 0; // No signal
}

//+------------------------------------------------------------------+
//| Open a new trade with proper risk management                     |
//+------------------------------------------------------------------+
void OpenTrade(ENUM_ORDER_TYPE orderType, double lotSize)
{
   double stopLossPrice, takeProfitPrice;
   double currentPrice;
   string orderComment = "MarketProfileAI EA";
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   // Calculate entry price based on order type
   if(orderType == ORDER_TYPE_BUY)
   {
      currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      stopLossPrice = currentPrice - StopLoss * point;
      takeProfitPrice = currentPrice + TakeProfit * point;
      orderComment += " - BUY";
   }
   else // ORDER_TYPE_SELL
   {
      currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      stopLossPrice = currentPrice + StopLoss * point;
      takeProfitPrice = currentPrice - TakeProfit * point;
      orderComment += " - SELL";
   }
   
   // Adjust stop loss based on profile levels for better placement
   if(orderType == ORDER_TYPE_BUY)
   {
      // For buy orders, consider using Value Area Low as stop if it's reasonable
      if(g_valueAreaLow < currentPrice && g_valueAreaLow > currentPrice - StopLoss * 1.5 * point)
      {
         stopLossPrice = g_valueAreaLow - 5 * point; // Add a small buffer
      }
   }
   else // ORDER_TYPE_SELL
   {
      // For sell orders, consider using Value Area High as stop if it's reasonable
      if(g_valueAreaHigh > currentPrice && g_valueAreaHigh < currentPrice + StopLoss * 1.5 * point)
      {
         stopLossPrice = g_valueAreaHigh + 5 * point; // Add a small buffer
      }
   }
   
   // Calculate risk amount in account currency
   double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100.0;
   
   // Calculate maximum lot size based on risk amount
   double maxLot = CalculateMaxLotSize(riskAmount, MathAbs(currentPrice - stopLossPrice));
   
   // Ensure the lot size doesn't exceed our risk parameters
   if(lotSize > maxLot) lotSize = maxLot;
   
   // Ensure lot size is within allowed limits and normalized
   lotSize = NormalizeDouble(MathMin(MathMax(lotSize, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)), 
                          SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX)), 
                          (int)SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP));
   
   // Send the order
   trade.SetDeviationInPoints(3);
   bool result = trade.PositionOpen(_Symbol, orderType, lotSize, currentPrice, stopLossPrice, takeProfitPrice, orderComment);
   
   // Check for errors
   if(!result)
   {
      Print("OrderSend Error: ", GetLastError());
      
      if(UseAlerts)
      {
         Alert("Failed to open trade: ", GetLastError());
      }
   }
   else
   {
      // Successfully opened the trade
      Print("Trade opened successfully. Ticket: ", trade.ResultOrder());
      g_totalTrades++;
      
      if(UseAlerts)
      {
         Alert("New ", orderType == ORDER_TYPE_BUY ? "BUY" : "SELL", " position opened at ", currentPrice);
      }
   }
}

//+------------------------------------------------------------------+
//| Calculate maximum lot size based on risk amount                  |
//+------------------------------------------------------------------+
double CalculateMaxLotSize(double riskAmount, double stopLossDistance)
{
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   
   if(stopLossDistance == 0 || tickValue == 0 || tickSize == 0)
   {
      return SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   }
   
   double pointValue = tickValue / tickSize;
   double maxLotSize = riskAmount / (stopLossDistance * pointValue);
   
   // Normalize to allowed lot step
   return NormalizeDouble(maxLotSize, (int)SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP));
}

//+------------------------------------------------------------------+
//| Calculate adaptive lot size based on volatility                  |
//+------------------------------------------------------------------+
double CalculateAdaptiveLotSize()
{
   // Base lot size
   double adaptiveLot = LotSize;
   
   // Get ATR values
   double atr[];
   ArraySetAsSeries(atr, true);
   CopyBuffer(atrHandle, 0, 0, 50, atr);
   
   // Calculate average ATR
   double sumATR = 0;
   for(int i = 1; i <= 50; i++)
   {
      sumATR += atr[i];
   }
   double avgATR = sumATR / 50;
   
   // Volatility ratio (current/average)
   double volatilityRatio = atr[0] / avgATR;
   
   // Adjust lot size inversely to volatility
   if(volatilityRatio > 1.5) // High volatility
   {
      adaptiveLot = LotSize * 0.7; // Reduce position size
   }
   else if(volatilityRatio < 0.7) // Low volatility
   {
      adaptiveLot = LotSize * 1.3; // Increase position size
   }
   
   // Further adjust based on winning streak
   if(g_consecutiveWins >= 3)
   {
      adaptiveLot *= 1.1; // Slight increase after 3 winners
   }
   
   if(g_consecutiveLosses >= 2)
   {
      adaptiveLot *= 0.9; // Slight decrease after 2 losers
   }
   
   // Make sure we stay within limits
   return NormalizeDouble(MathMax(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN), 
                          MathMin(adaptiveLot, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX))), 
                          (int)SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP));
}

//+------------------------------------------------------------------+
//| Check if we already have an open trade for this EA               |
//+------------------------------------------------------------------+
bool HasOpenTrade()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0)
      {
         if(_Symbol == PositionGetString(POSITION_SYMBOL) && 
            MagicNumber == PositionGetInteger(POSITION_MAGIC))
         {
            return true;
         }
      }
   }
   
   return false;
}

//+------------------------------------------------------------------+
//| Manage open trades with trailing stops and dynamic take profits  |
//+------------------------------------------------------------------+
void ManageOpenTrades()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0)
      {
         if(_Symbol == PositionGetString(POSITION_SYMBOL) && 
            MagicNumber == PositionGetInteger(POSITION_MAGIC))
         {
            // Get current position details
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentStopLoss = PositionGetDouble(POSITION_SL);
            double currentTakeProfit = PositionGetDouble(POSITION_TP);
            ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            
            // Current market price
            double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
            
            // Calculate profit in points
            double profitPoints = 0;
            if(posType == POSITION_TYPE_BUY)
            {
               profitPoints = (currentBid - openPrice) / point;
            }
            else
            {
               profitPoints = (openPrice - currentAsk) / point;
            }
            
            // Apply trailing stop if in profit
            if(profitPoints > StopLoss)
            {
               double newStopLoss = 0;
               
               if(posType == POSITION_TYPE_BUY)
               {
                  // For buy positions, move stop loss to lock in profit
                  newStopLoss = currentBid - (StopLoss * 0.7) * point;
                  
                  // Ensure we're actually moving the stop loss up
                  if(newStopLoss > currentStopLoss)
                  {
                     trade.PositionModify(ticket, newStopLoss, currentTakeProfit);
                     if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
                     {
                        Print("Trailing stop applied - New SL: ", newStopLoss);
                     }
                  }
               }
               else // POSITION_TYPE_SELL
               {
                  // For sell positions, move stop loss to lock in profit
                  newStopLoss = currentAsk + (StopLoss * 0.7) * point;
                  
                  // Ensure we're actually moving the stop loss down
                  if(newStopLoss < currentStopLoss || currentStopLoss == 0)
                  {
                     trade.PositionModify(ticket, newStopLoss, currentTakeProfit);
                     if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
                     {
                        Print("Trailing stop applied - New SL: ", newStopLoss);
                     }
                  }
               }
            }
            
            //Dynamic take profit adjustment based on market conditions
            if(profitPoints > TakeProfit * 0.7)
            {
               // If approaching take profit and momentum is strong, extend it
               if((posType == POSITION_TYPE_BUY && IsPriceMovingUp()) || 
                  (posType == POSITION_TYPE_SELL && IsPriceMovingDown()))
               {
                  double newTakeProfit = 0;
                  
                  if(posType == POSITION_TYPE_BUY)
                  {
                     newTakeProfit = openPrice + (TakeProfit * 1.5) * point;
                     
                     if(newTakeProfit > currentTakeProfit)
                     {
                        trade.PositionModify(ticket, currentStopLoss, newTakeProfit);
                        if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
                        {
                           Print("Take profit extended - New TP: ", newTakeProfit);
                        }
                     }
                  }
                  else // POSITION_TYPE_SELL
                  {
                     newTakeProfit = openPrice - (TakeProfit * 1.5) * point;
                     
                     if(newTakeProfit < currentTakeProfit || currentTakeProfit == 0)
                     {
                        trade.PositionModify(ticket, currentStopLoss, newTakeProfit);
                        if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
                        {
                           Print("Take profit extended - New TP: ", newTakeProfit);
                        }
                     }
                  }
               }
            }
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Calculate key performance metrics                                |
//+------------------------------------------------------------------+
void CalculatePerformanceMetrics()
{
   // Reset counters
   int wins = 0;
   int losses = 0;
   double totalProfit = 0;
   double totalLoss = 0;
   
   // Get history for last 100 trades
   HistorySelect(0, TimeCurrent());
   
   for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = HistoryDealGetTicket(i);
      if(ticket > 0)
      {
         if(HistoryDealGetString(ticket, DEAL_SYMBOL) == _Symbol && 
            HistoryDealGetInteger(ticket, DEAL_MAGIC) == MagicNumber)
         {
            double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
            
            if(profit > 0)
            {
               wins++;
               totalProfit += profit;
            }
            else if(profit < 0)
            {
               losses++;
               totalLoss += MathAbs(profit);
            }
         }
      }
   }
   
   // Calculate win rate
   if(wins + losses > 0)
   {
      g_winRate = (double)wins / (wins + losses);
   }
   
   // Calculate profit factor
   if(totalLoss > 0)
   {
      g_profitFactor = totalProfit / totalLoss;
   }
   else if(totalProfit > 0)
   {
      g_profitFactor = 10; // Arbitrary high value if no losses
   }
   
   // Track consecutive wins/losses by looking at last trade
   if(HistoryDealsTotal() > 0)
   {
      ulong lastTicket = HistoryDealGetTicket(HistoryDealsTotal() - 1);
      if(lastTicket > 0)
      {
         if(HistoryDealGetString(lastTicket, DEAL_SYMBOL) == _Symbol && 
            HistoryDealGetInteger(lastTicket, DEAL_MAGIC) == MagicNumber)
         {
            double lastProfit = HistoryDealGetDouble(lastTicket, DEAL_PROFIT);
            
            if(lastProfit > 0)
            {
               g_consecutiveWins++;
               g_consecutiveLosses = 0;
            }
            else if(lastProfit < 0)
            {
               g_consecutiveLosses++;
               g_consecutiveWins = 0;
            }
         }
      }
   }
   
   Print("Performance - Win Rate: ", g_winRate, " Profit Factor: ", g_profitFactor);
}

//+------------------------------------------------------------------+
//| Load AI model weights (simulated in this version)                |
//+------------------------------------------------------------------+
bool LoadAIModelWeights()
{
   // In a real implementation, this would load weights from a file
   // For this example, we'll just return true
   Print("AI model weights loaded successfully");
   return true;
}

//+------------------------------------------------------------------+
//| Save AI model weights (simulated in this version)                |
//+------------------------------------------------------------------+
void SaveAIModelWeights()
{
   // In a real implementation, this would save weights to a file
   Print("AI model weights saved successfully");
}

//+------------------------------------------------------------------+
//| Check if it's the end of the trading day                         |
//+------------------------------------------------------------------+
bool IsEndOfTradingDay()
{
   MqlDateTime dt;
   TimeCurrent(dt);
   
   // Check if we're near the end of the trading day (e.g., after 23:45)
   return (dt.hour == 23 && dt.min >= 45);
}

//+------------------------------------------------------------------+
//| Close all open trades for this EA                                |
//+------------------------------------------------------------------+
void CloseAllTrades()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0)
      {
         if(_Symbol == PositionGetString(POSITION_SYMBOL) && 
            MagicNumber == PositionGetInteger(POSITION_MAGIC))
         {
            trade.PositionClose(ticket);
            
            if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
            {
               Print("Position closed successfully: ", ticket);
            }
            else
            {
               Print("Error closing position: ", GetLastError());
            }
         }
      }
   }
}
//+------------------------------------------------------------------+
