//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2020, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

input int MagicNumber = 10001;
input double InitialLots = 0.1;
input int StartHour = 0;
input int EndHour = 24;
input bool TradeOnSunday = true;
input bool TradeOnMonday = true;
input bool TradeOnTuesday = true;
input bool TradeOnWednesday = true;
input bool TradeOnThursday = true;
input bool TradeOnFriday = true;
input bool TradeOnSaturday = true;
input bool EnableBuyTrades = true;
input bool EnableSellTrades = true;
input bool EnableBuyReverseTrades = true;
input bool EnableSellReverseTrades = true;
input bool EnableMartingale = true;
input int MartingaleSteps = 3;
input double MartingaleLotMultiplier = 2;

int LastCandleIndex = -1;
double Lots = InitialLots;
int MartingaleCounter = 0;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   CTrade trade;
   trade.SetExpertMagicNumber(MagicNumber);
   double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   MqlDateTime TimeNow;
   TimeCurrent(TimeNow);

   if(!IsTradeDay(TimeNow.day_of_week) || TimeNow.hour < StartHour || TimeNow.hour > EndHour)
      return;

   if(PositionsTotal() > 0)
     {
      CheckBreakEven();
      CheckTakeProfit();
      return;
     }

   int CurrentCandleIndex = iBars(_Symbol, PERIOD_CURRENT);

   double PreviousHigh = iHigh(_Symbol, PERIOD_CURRENT, 1);
   double PreviousLow = iLow(_Symbol, PERIOD_CURRENT, 1);
   double CandleSize = PreviousHigh - PreviousLow;

   double TenPipsAboveHigh = PreviousHigh + 10 * _Point;
   double TenPipsBelowLow = PreviousLow - 10 * _Point;

   if(CurrentCandleIndex != LastCandleIndex)
     {
      if(EnableBuyTrades && MathAbs(Ask - TenPipsAboveHigh) <= _Point)
        {
         if(EnableBuyReverseTrades)
           {
            // افتتاح معامله فروش به جای خرید
            double TheStopLoss = Ask + CandleSize;
            double TheTakeProfit = Bid - CandleSize;
            trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, Bid, TheStopLoss, TheTakeProfit);
           }
         else
           {
            // افتتاح معامله خرید
            double TheStopLoss = PreviousLow - 10 * _Point;
            double TheTakeProfit = Ask + CandleSize;
            trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, Lots, Ask, TheStopLoss, TheTakeProfit);
           }

         LastCandleIndex = CurrentCandleIndex;
         if(EnableMartingale)
           {
            MartingaleCounter++;
            if(MartingaleCounter >= MartingaleSteps)
              {
               ResetMartingale();
              }
            else
              {
               Lots *= MartingaleLotMultiplier;
              }
           }
        }
      else
         if(EnableSellTrades && MathAbs(Bid - TenPipsBelowLow) <= _Point)
           {
            if(EnableSellReverseTrades)
              {
               // افتتاح معامله خرید به جای فروش
               double TheStopLoss = Bid - CandleSize;
               double TheTakeProfit = Ask + CandleSize;
               trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, Lots, Ask, TheStopLoss, TheTakeProfit);
              }
            else
              {
               // افتتاح معامله فروش
               double TheStopLoss = PreviousHigh + 10 * _Point;
               double TheTakeProfit = Bid - CandleSize;
               trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, Bid, TheStopLoss, TheTakeProfit);
              }


            LastCandleIndex = CurrentCandleIndex;
            if(EnableMartingale)
              {
               MartingaleCounter++;
               if(MartingaleCounter >= MartingaleSteps)
                 {
                  ResetMartingale();
                 }
               else
                 {
                  Lots *= MartingaleLotMultiplier;
                 }
              }
           }
     }
  }

//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsTradeDay(int dayOfWeek)
  {
   switch(dayOfWeek)
     {
      case 0:
         return TradeOnSunday;
      case 1:
         return TradeOnMonday;
      case 2:
         return TradeOnTuesday;
      case 3:
         return TradeOnWednesday;
      case 4:
         return TradeOnThursday;
      case 5:
         return TradeOnFriday;
      case 6:
         return TradeOnSaturday;
      default:
         return false;
     }
  }

//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CheckBreakEven()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
         double stopLoss = PositionGetDouble(POSITION_SL);
         double takeProfit = PositionGetDouble(POSITION_TP);


         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
           {
            if(currentPrice >= (openPrice + takeProfit) / 2 && stopLoss < openPrice)
              {
               CTrade trade;
               trade.PositionModify(ticket, openPrice, takeProfit);
              }
           }
         else
            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
              {
               if(currentPrice <= (openPrice + takeProfit) / 2 && stopLoss > openPrice)
                 {
                  CTrade trade;
                  trade.PositionModify(ticket, openPrice, takeProfit);
                 }
              }
        }
     }
  }

//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+

void CheckTakeProfit()
{
    Print("CheckTakeProfit() called.");

    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong ticket = PositionGetTicket(i);
        CPositionInfo position;
        
        if (position.SelectByTicket(ticket))
        {
            double takeProfit = position.TakeProfit();
            double currentPrice = position.PriceCurrent();

            Print("Checking position ", (string)ticket, ": TakeProfit = ", (string)takeProfit, ", CurrentPrice = ", (string)currentPrice);

            if ((position.PositionType() == POSITION_TYPE_BUY && currentPrice >= takeProfit) ||
                (position.PositionType() == POSITION_TYPE_SELL && currentPrice <= takeProfit))
            {
                Print("Take Profit reached for position ", (string)ticket);
                
                double lots = position.Volume();
                int martingaleCounter = (int)position.Magic();
                
                Print("Before ResetMartingale: Lots = ", (string)lots, ", MartingaleCounter = ", (string)martingaleCounter);
                
                ResetMartingale();
                
                Print("After ResetMartingale: Lots = ", (string)Lots, ", MartingaleCounter = ", (string)MartingaleCounter);
                
                CTrade trade;
                if (trade.PositionClose(ticket))
                {
                    Print("Position ", (string)ticket, " closed by Take Profit.");
                }
                else
                {
                    Print("Failed to close position ", (string)ticket, " by Take Profit. Error: ", (string)trade.ResultRetcode());
                }
                
                // Exit the loop after closing the position
                break;
            }
        }
    }
}

void ResetMartingale()
{
    Lots = InitialLots;
    MartingaleCounter = 0;
    
    Print("ResetMartingale called. Lots reset to ", (string)Lots, ", MartingaleCounter reset to ", (string)MartingaleCounter);
}