//+------------------------------------------------------------------+
//|                                        Buman Goyang Gayung EA.mq |
//|                                        Coded by AlfaBetaCharlieD |
//|                                          anthonbudiman@gmail.com |
//+------------------------------------------------------------------+
#property copyright "anthonBudiman@gmail.com"
#property link "https://www.mql5.com"
#property version   "1.0"
#property strict

//--Input Parameters--

enum TrailingMode
  {
   StillInLoss=0,                                           // Stop Trailing Still in Loss
   AfterInProfit=1,                                         // Stop Trailing after in Profit
  };
  
enum TakeProfitMode
  {
   InPoints = 0,                                            // Take Profit in Points
   InBaseCurrency = 1,                                      // Take Profit Base Currency ($)
  };
  
enum StopLossMode
  {
   slInPoints = 0,                                          // Stop Loss in Points
   slInBaseCurrency = 1,                                    // Stop Loss in Base Currency ($)
   slnone = 2                                               // Don't Use
  };
  
enum TradingMode
  {
   text=0,                                                  // Text Appeared
   currentdot=1,                                            // Dot Appeared while Bar still opened
   closeddot=2                                              // After Closed Bar with dot
  };

bool TimeControl = true;                             // Filter time of traiding (true/false)
input string   TradingStart = "02:00";                      // Start Trade
input string   TradingEnd = "22:00";                        // End Trade 

input int MagicNumber = 123456;                             // EA Magic Number
 string Comm = "Buman Chart Pattern EA";                     // EA Comment

 string params0 = "Strategy parameters:";              // _____________________

input TradingMode TradeType = 0;                            // Strategy trading mode
input bool MartiOnlyOnce = false;                           // Martingale only once

 string params1 = "Money Management Parameters:";      // _____________________

input double FixedLots = 0.01;                              // Fixed Initial Lots
input bool MoneyManagement = false;                          // MM % (true/false)
input double PercentLots = 1;                               // MM Lots % from FreeMargin
input double MinLots = 0.01;                                // Minimum Lots
input double MaxLots = 1000;                                // Maximum Lots
input double Multiplier = 1.75;                              // Martingale Multiplier

 string params2 = "Trailing Stop Parameters:";         // _____________________

input TrailingMode Trailing = 0;                            // Trailing Stop Mode
input double TrailingStop = 15;                             // Trailing Stop in Pips
input double TrailingStart = 5;                             // Start Trailing after Pips

 string params3 = "Take Profit/Loss Parameters:";           // _____________________

input TakeProfitMode TakeProfitType = 0;                    // Take Profit Mode
input double TakeProfitValue = 100;                         // Take Profit

input StopLossMode StopLossType = 0;                        // Stop Loss Mode
input double StopLossValue = 100;                           // Stop Loss

input double LimitStop = 2;                                 // Limit Loss in % loss from Balance

 string params4 = "Time Control Parameters:";          // _____________________




int StartHours;
int StartMinutes;
int EndHours ;
int EndMinutes;
bool allowOpen,allowDay;
double pipstarget,pipslimit,balance;

int Slippage = 3;
datetime CurrentTimeB,CurrentTimeS,Refresh,CurrentDay;

string objName;

//+------------------------------------------------------------------+
//    expert start function
//+------------------------------------------------------------------+
void OnInit(){

CurrentDay = iTime(Symbol(),PERIOD_D1,0);
balance = AccountBalance();
CurrentTimeB = Time[0];
CurrentTimeS = Time[0];
Refresh = TimeCurrent();
pipstarget = TakeProfitValue/10;
pipslimit = StopLossValue/10;

StartHours = (int) StringToInteger(StringSubstr(TradingStart,0,2));
StartMinutes = (int) StringToInteger(StringSubstr(TradingStart,3,2));
EndHours = (int) StringToInteger(StringSubstr(TradingEnd,0,2));
EndMinutes = (int)  StringToInteger(StringSubstr(TradingEnd,3,2));

}

void OnTick()
{

bool SellSignal=false;
bool BuySignal=false;
double MyPoint=Point;
allowDay=true;

Comment("Balance:            ",DoubleToStr(AccountBalance(),2)," ",AccountCurrency()," \n","Equity:              ",DoubleToStr(AccountEquity(),2)," ",AccountCurrency()," \n","Daily P/L:          ",DoubleToStr(CompoundResult(),2)," ",AccountCurrency()," \n","Running P/L:       ",DoubleToStr(CompoundOpen(),2)," ",AccountCurrency());
  
  if(Digits==3 || Digits==5) MyPoint=Point*10;
  if(Digits==2) MyPoint = Point*100;
  if(Digits==1) MyPoint = Point*10;
  if(Digits==0) MyPoint = Point;
  
if(CurrentDay!=iTime(Symbol(),PERIOD_D1,0))
{
balance=AccountBalance();
CurrentDay=iTime(Symbol(),PERIOD_D1,0);
}

if(MathAbs(CompoundResult())>balance*LimitStop/100 && CompoundResult()<0)
{
allowDay=false;
CloseAllPositions();
}

if(Buys()+Sells()>1)
{
RemoveSL();
}

if(TakeProfitType==0 && TotalProfitPips()>pipstarget)
{
CloseAllPositions();
Print("Trades closed Points target reached!");
}


if(TakeProfitType==1 && TotalProfit()>TakeProfitValue)
{
CloseAllPositions();
Print("Trades closed Money target reached!");
}

if(StopLossType==0 && MathAbs(TotalProfitPips())>pipslimit && TotalProfitPips()<0)
{
CloseAllPositions();
Print("Trades closed Points limit loss reached!");
}


if(TakeProfitType==1 && MathAbs(TotalProfit())>StopLossValue && TotalProfit()<0)
{
CloseAllPositions();
Print("Trades closed Money limit loss reached!");
}

if( ( TimeHour(TimeCurrent())>StartHours || ( TimeHour(TimeCurrent())==StartHours && TimeMinute(TimeCurrent())>=StartMinutes )) &&
 ( TimeHour(TimeCurrent())<EndHours || ( TimeHour(TimeCurrent())==EndHours && TimeMinute(TimeCurrent())<=EndMinutes )) )
{
allowOpen=true;
}
else
{
allowOpen=false;
}
if(!TimeControl)
{
allowOpen=true;
}

if(TradeType==0)
{
if(Close[2] < Open[2] && Open[1] < Close[2] && Close[1] > Open[2])
{
BuySignal=true;
}
else
{
if (Close[2] < Open[2] && Close[1] > Open[1] && (Open[1] < Close[2] || Low[1] < Low[2]) && Close[1] > Close[2] + (Open[2] - Close[2]) / 2.0)BuySignal=true;
}

if (Close[3] < Open[3] && Open[2] < Close[3] && Close[2] < Close[3] && (Open[1] > Close[2] || High[1] > High[2]) && Close[1] >= Close[3])BuySignal=true;

if (Close[1] > Open[1] && Open[1] - Low[1] > 3.0 * MathMax(High[1] - Close[1], Close[1] - Open[1]))BuySignal=true;


if (Close[2] > Open[2] && Close[1] < Open[1] && Open[1] > Close[2] && (Close[1] < Open[2] || Low[1] < Low[2]))
{
SellSignal=true;
}
else
{
if(Close[2] > Open[2] && (Open[1] > Close[2] || High[1] > High[2]) && Close[1] < Close[2] - (Close[2] - Open[2]) / 2.0)SellSignal=true;
}

if (Close[3] > Open[3] && Open[2] > Close[3] && Close[2] > Close[3] && (Open[1] < Close[2] || Low[1] < Low[2]) && Close[1] < Close[3])SellSignal=true;

if (Close[1] < Open[1] && High[1] - Open[1] > 3.0 * MathMax(Close[1] - Low[1], Open[1] - Close[1]))SellSignal=true;
}

if(TradeType==1)
{
if(iCustom(NULL,0,"chart-pattern",true,true,0,0)!=EMPTY_VALUE && iCustom(NULL,0,"chart-pattern",true,true,0,0)!=0 )BuySignal=true;
if(iCustom(NULL,0,"chart-pattern",true,true,1,0)!=EMPTY_VALUE && iCustom(NULL,0,"chart-pattern",true,true,1,0)!=0)SellSignal=true;
}

if(TradeType==2)
{
if(iCustom(NULL,0,"chart-pattern",true,true,0,1)!=EMPTY_VALUE && iCustom(NULL,0,"chart-pattern",true,true,0,1)!=0 )BuySignal=true;
if(iCustom(NULL,0,"chart-pattern",true,true,1,1)!=EMPTY_VALUE && iCustom(NULL,0,"chart-pattern",true,true,1,1)!=0)SellSignal=true;
}



double InitialLots = MarketInfo(Symbol(),MODE_MINLOT);
if(!MoneyManagement) InitialLots = FixedLots;
else
{
double FreeMargin = AccountFreeMargin();
double Leverage = AccountLeverage();
double OneLotMargin = MarketInfo(Symbol(),MODE_MARGINREQUIRED);
double MarginAmount = FreeMargin*PercentLots/100;
InitialLots = MarginAmount/OneLotMargin;
double LotStep = MarketInfo(Symbol(),MODE_LOTSTEP);
InitialLots = NormalizeDouble(InitialLots/LotStep,0)*LotStep;
}

double Lots;
Lots = InitialLots;
double step = MarketInfo(NULL,MODE_LOTSTEP);

if(Buys()>0 && SellSignal)
   {
      Lots = NormalizeDouble(LastBuyVolume()*Multiplier,2);
   }
if(SellSignal && Lots==LastBuyVolume())
{
   Lots+=step;
}
if(Sells()>0 && BuySignal)
   {
      Lots = NormalizeDouble(LastSellVolume()*Multiplier,2);
   }
if(BuySignal && Lots==LastSellVolume())
{
   Lots+=step;
}
if(Buys()>0 && Sells()>0 && MartiOnlyOnce)
{
   if(BuySignal)Lots = NormalizeDouble(LastSellVolume(),2);
   if(SellSignal)Lots = NormalizeDouble(LastBuyVolume(),2);
}
if(Lots>MaxLots)Lots=MaxLots;
if(Lots<MinLots)Lots=MinLots;


int result=0;
   if( BuySignal==true && CurrentTimeB!=Time[1] && allowDay && allowOpen && OpenOrder()==1) 
      {
           result=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,0,0,Comm,MagicNumber,0,clrBlue);
           if(result>0)
           {
               Print("Buy order placed");
               CurrentTimeB=Time[1];
           }
           else
           {
               Print("Error placing buy order: " + IntegerToString(GetLastError()));
           }        
      }
result=0;
   if( SellSignal==true && CurrentTimeS!=Time[1] && allowDay && allowOpen && OpenOrder()==0)
      {
           result=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,0,0,Comm,MagicNumber,0,clrRed);
           if(result>0)
           {
               Print("Sell order placed");
               CurrentTimeS=Time[1];
           }
           else
           {
               Print("Error placing sell order: " + IntegerToString(GetLastError()));
           }
      }



if(Trailing==0 && Buys()+Sells()<=1)
{
 for(int cnt=0;cnt<OrdersTotal();cnt++)
     {
      if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES))
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)  
        {
         if(OrderType()==OP_BUY)  
           {
            if(TrailingStop>0)  
              {                 
               if(Bid-OrderOpenPrice()>MyPoint*TrailingStart)
                 {
                  if(OrderStopLoss()<Bid-MyPoint*TrailingStop)
                    {
                     (bool)OrderModify(OrderTicket(),OrderOpenPrice(),Bid-TrailingStop*MyPoint,OrderTakeProfit(),0,clrGreen);
                   
                    }
                 }
              }
           }
         if(OrderType()==OP_SELL)  
           {
            if(TrailingStop>0)  
              {                 
              
               if((OrderOpenPrice()-Ask)>(MyPoint*TrailingStart))
                 {
                  if((OrderStopLoss()>(Ask+MyPoint*TrailingStop)))
                    {
                     (bool)OrderModify(OrderTicket(),OrderOpenPrice(),Ask+MyPoint*TrailingStop,OrderTakeProfit(),0,clrRed);
                     
                    }
                 }
              }
           }
        }
     }
}

if(Trailing==1 && Buys()+Sells()<=1)
{
 for(int cnt=0;cnt<OrdersTotal();cnt++)
     {
      if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES))
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)  
        {
         if(OrderType()==OP_BUY)  
           {
            if(TrailingStop>0)  
              {                 
               if(Bid-OrderOpenPrice()>MyPoint*TrailingStop)
                 {
                  if(OrderStopLoss()<Bid-MyPoint*TrailingStop)
                    {
                     (bool)OrderModify(OrderTicket(),OrderOpenPrice(),Bid-TrailingStop*MyPoint,OrderTakeProfit(),0,clrGreen);
                    }
                 }
              }
           }
         if(OrderType()==OP_SELL)  
           {
            if(TrailingStop>0)  
              {                 
               if((OrderOpenPrice()-Ask)>(MyPoint*TrailingStop))
                 {
                  if((OrderStopLoss()>(Ask+MyPoint*TrailingStop)) || (OrderStopLoss()==0))
                    {
                     (bool)OrderModify(OrderTicket(),OrderOpenPrice(),Ask+MyPoint*TrailingStop,OrderTakeProfit(),0,clrRed);
                    }
                 }
              }
           }
        }
     }
}


}


double LastBuyVolume()
{
  double result=0;
  datetime test=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
     if(OrderSymbol()==Symbol() && OrderOpenTime()>=Refresh && OrderMagicNumber()==MagicNumber && OrderType()==OP_BUY)
      {
         if(OrderOpenTime()>test)
         {
         test=OrderOpenTime();
         result=OrderLots();
         }
      }

   }
  return (result);
}
double LastSellVolume()
{
  double result=0;
  datetime test=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
     if(OrderSymbol()==Symbol() && OrderOpenTime()>=Refresh && OrderMagicNumber()==MagicNumber && OrderType()==OP_SELL)
      {
         if(OrderOpenTime()>test)
         {
         test=OrderOpenTime();
         result=OrderLots();
         }
      }

   }
  return (result);
}

int Sells()
{
  int result=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
      {
         if( OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol() && OrderType()==OP_SELL ) result++;
      }
   }
  return (result);
}

int Buys()
{
  int result=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
      {
         if( OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol() && OrderType()==OP_BUY ) result++;
      }
   }
  return (result);
}

double TotalProfit()
{
double result=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
      {

         if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol() && OrderOpenTime()>Refresh) result+=OrderProfit();
      }
   }
   for(int j=OrdersHistoryTotal()-1;j>=0;j--)
   {
     if(OrderSelect(j,SELECT_BY_POS ,MODE_HISTORY))
      {
         if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol() && OrderOpenTime()>Refresh) result+=OrderProfit();
      }
   }
return (result);
}
double TotalProfitPips()
{
double result=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
      {

         if(OrderMagicNumber()==MagicNumber && OrderOpenTime()>Refresh && OrderSymbol()==Symbol()) result+=OrderProfit()/OrderLots()/MarketInfo(OrderSymbol(),MODE_TICKVALUE)/10;
      }
   }
   for(int j=OrdersHistoryTotal()-1;j>=0;j--)
   {
     if(OrderSelect(j,SELECT_BY_POS ,MODE_HISTORY))
      {
         if(OrderCloseTime()<Refresh)break;
         if(OrderMagicNumber()==MagicNumber && OrderCloseTime()>Refresh && OrderSymbol()==Symbol()) result+=OrderProfit()/OrderLots()/MarketInfo(OrderSymbol(),MODE_TICKVALUE)/10;
      }
   }
return (result);
}
void CloseAllPositions()
{
double closeprice=0;
string msg="";
for(int i = OrdersTotal()-1; i >= 0; i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol())
               {
                  if(OrderType()==OP_BUY)
                     {
                        closeprice = Bid;
                        msg = "Order Buy closed";
                     }
                  else
                     {
                        closeprice=Ask;
                        msg = "Order Sell closed";
                     }
                  if(OrderClose(OrderTicket(),OrderLots(),closeprice,Slippage,clrNONE)){Print(msg);}
                  else {Print("Error Closing: "+IntegerToString(GetLastError()));}
               }
           }
   }
Refresh=TimeCurrent();
}
double CompoundResult()
{
double result = 0;
for(int i=OrdersHistoryTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
         {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol()&& OrderCloseTime()>iTime(Symbol(),PERIOD_D1,0))result+=OrderProfit();
         }
      else
         {
            Print("OrderSelect error "+IntegerToString(GetLastError()));
         }
   }
for(int i=OrdersTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol() && OrderOpenTime()>iTime(Symbol(),PERIOD_D1,0))result+=OrderProfit();
         }
      else
         {
            Print("OrderSelect error "+IntegerToString(GetLastError()));
         }
   }
return (result);
}

double CompoundOpen()
{
double result = 0;
for(int i=OrdersTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol())result+=OrderProfit();
         }
      else
         {
            Print("OrderSelect error "+IntegerToString(GetLastError()));
         }
   }
return (result);
}

void RemoveSL()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
            if(OrderMagicNumber()==MagicNumber && OrderSymbol()==Symbol())
               {
                  if(OrderStopLoss()!=0)
                     {
                        (bool)OrderModify(OrderTicket(),OrderOpenPrice(),0,0,0,clrNONE);
                     }
               }
           }
   }
}

int OpenOrder ()
{
  int result=0;
  datetime test=0;
  for(int i=0;i<OrdersTotal();i++)
  {
     if(OrderSelect(i,SELECT_BY_POS ,MODE_TRADES))
     if(OrderSymbol()==Symbol() && OrderOpenTime()>=Refresh && OrderMagicNumber()==MagicNumber)
      {
         if(OrderOpenTime()>test)
         {
         test=OrderOpenTime();
         result=OrderType();
         }
      }

   }
  return (result);
}