//+------------------------------------------------------------------+
//|                                               PendingOrderEA.mq4 |
//+------------------------------------------------------------------+

int  TF=1;

bool New_Bar;
int  ErrorCode;

//----------------------- INCLUDES
#include <stdlib.mqh>


//----------------------- EA EXTERNAL PARAMETER ---------------------------------//
extern string  Expert_Name    = "---------- PendingOrderEA",
               Expert_Name2   = "---------- For current price set EntryLevel = 0";

extern double  Distance       = 200,
               StopLoss       = 800,
               TakeProfit     = 800,
               TrailingStop   = 0;

extern bool SignalMail = False;
extern bool UseStopLoss = True;
extern bool UseTakeProfit = False;
extern bool UseTrailingStop = True;

extern string  Order_Setting  = "---------- Order Setting";

extern int     NumberOfTries  = 5,
               Slippage       = 5,
               MagicNumber    = 12432;

extern string  MM_Parameters  = "---------- Money Management";

extern double  Lots           = 0.01;

extern bool    MM                 = false, //Use Money Management or not
               AccountIsMicro     = false, //Use Micro-Account or not
               UseCurrentBidPrice=false; //Use correntcandle
extern int     Risk = 10; // 10%

extern string  Testing_Parameters="---------- Back Test Parameter";
extern bool    Show_Settings=true;

//----------------------- GLOBAL VARIABLE -----------------------//
static int     TimeFrame     = 0;
string         TicketComment = "PendingOrderEA", LastTrade;
bool           TradeAllow    = true,
               EntryAllow    = true;
int            P = 1;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   if(Show_Settings) subPrintDetails();
   else Comment("");

   return(0);
  }
  
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
   TimeFrame=Period();
   return(0);
  }
  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   if(Period()!=TF)
     {
      Comment("Please switch back to the correct timeframe.\nTrading is disabled!");
      return(0);
     }
        
   Check_New_Bar();
   if(New_Bar==true)
     {

      if(MM) Lots=subLotSize();

      HAChangePendingOrder("EURUSD",Lots,Slippage,StopLoss,TakeProfit,MagicNumber);

     }

   return(0);
  }
//----------------------- END PROGRAM

//+------------------------------------------------------------------+
//| FUNCTION DEFINITIONS
//+------------------------------------------------------------------+

//----------------------- MONEY MANAGEMENT FUNCTION  
//----------------------- SOURCE : CODERSGURU
double subLotSize()
  {
   double lotMM=MathCeil(AccountFreeMargin() *Risk/1000)/100;

   if(AccountIsMicro==false) //normal account
     {
      if(lotMM < 0.1)                  lotMM = Lots;
      if((lotMM > 0.5) && (lotMM < 1)) lotMM = 0.5;
      if(lotMM > 1.0)                  lotMM = MathCeil(lotMM);
      if(lotMM > 100)                  lotMM = 100;
     }
   else //micro account
     {
      if(lotMM < 0.01)                 lotMM = Lots;
      if(lotMM > 1.0)                  lotMM = MathCeil(lotMM);
      if(lotMM > 100)                  lotMM = 100;
     }

   return (lotMM);
  }
  
  
//-- NUMBER OF ORDER BASE ON SYMBOL AND MAGICNUMBER FUNCTION --//
int subTotalTrade(string Symbl)
  {
   int cnt, total=0;
   for(cnt=0;cnt<OrdersTotal();cnt++)
     {
      int ticket=OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
      if(OrderType()<=OP_SELL && 
         OrderSymbol()==Symbl && 
         OrderMagicNumber()==MagicNumber) total++;
     }
   return(total);
  }
  
  

//-- DELETE ORDER FUNCTION --//
void subDeleteOrder(string Symbl)
  {
   int cnt, total=0;

   total=OrdersTotal();
   for(cnt=total-1;cnt>=0;cnt--)
     {
      int ticket=OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);

      if(OrderSymbol()==Symbl && 
         OrderMagicNumber()==MagicNumber)
        {
         switch(OrderType())
           {
            case OP_BUYLIMIT :
            case OP_BUYSTOP  :
            case OP_SELLLIMIT:
            case OP_SELLSTOP :
              ticket=OrderDelete(OrderTicket());
           }
        }
     }
  }
  
//-- TRAILINGSTOP FUNCTION --//  
void subTrailingStop(int Type)
  {
   if(Type==OP_BUY) // buy position is opened   
     {
      if(Bid-OrderOpenPrice()>Point*TrailingStop && 
         OrderStopLoss()<Bid-Point*TrailingStop)
        {
         int ticket=OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
        }
     }

   if(Type==OP_SELL) // sell position is opened   
     {
      if(OrderOpenPrice()-Ask>Point*TrailingStop)
        {
         if(OrderStopLoss()>Ask+Point*TrailingStop || OrderStopLoss()==0)
           {
            ticket=OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
           }
        }
     }
  }


//+------------------------------------------------------------------+
//| Write comments                                                   |
//+------------------------------------------------------------------+
void subPrintDetails()
  {

   string sComment   = "";
   string sp         = "-----------------------------------------------------------------\n";
   string NL         = "\n";

   sComment = sp;
   sComment = sComment + "TakeProfit=" + DoubleToStr(TakeProfit,0) + " | ";
   sComment = sComment + "TrailingStop=" + DoubleToStr(TrailingStop,0) + " | ";
   sComment = sComment + "StopLoss=" + DoubleToStr(StopLoss,0) + NL;
   sComment = sComment + sp;
   sComment = sComment + "Lots=" + DoubleToStr(Lots,2) + " | ";
   sComment = sComment + "MM=" + subBoolToStr(MM) + " | ";
   sComment = sComment + "Risk=" + DoubleToStr(Risk,0) + "%" + NL;

   Comment(sComment);
  }

//-- BOOLEN VARIABLE TO STRING FUNCTION --//
string subBoolToStr(bool value)
  {
   if(value) return ("True");
   else return ("False");
  }
//-- END FUNCTION


//+-- BUY/SELL function--+
int HAChangePendingOrder(string Symb,double Lts,double Slippge,double StopLss,double TakePrfit,int MagicNmber)
  {
   double
   cnt;
   subDeleteOrder(Symb);
   double StopLossLevel, TakeProfitLevel, StopLevel, BuyLevel, SellLevel;

   StopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) + MarketInfo(Symbol(), MODE_SPREAD); // Defining minimum StopLevel

   if (StopLoss < StopLevel) StopLoss = StopLevel;
   if (TakeProfit < StopLevel) TakeProfit = StopLevel;   

   if(TradeAllow)
     {         

     BuyLevel = NormalizeDouble(MarketInfo(Symb,MODE_BID)+Distance*Point, Digits);
     SellLevel = NormalizeDouble(MarketInfo(Symb,MODE_BID)-Distance*Point,Digits);

      int total=subTotalTrade(Symb);
      if(total<1 && EntryAllow)
        {
         Print(Symb);
         if(Close[1]>Open[1] && Close[2]<Open[2])
           {          
               if (UseStopLoss) StopLossLevel = Ask - StopLoss * Point * P; else StopLossLevel = 0.0;
               if (UseTakeProfit) TakeProfitLevel = Ask + TakeProfit * Point * P; else TakeProfitLevel = 0.0;

               RefreshRates();

               if((BuyLevel-Ask)<10*Point)
                 {
                  Print("Invalid Entry Price or Distance on "+Symb);
                  Print(Symb+" Buylevel "+BuyLevel);
                  return(99);
                 }                            

               int ticket=OrderSend(Symb,OP_BUYSTOP,Lts,Ask,Slippge,0,0,"",MagicNmber,0,Green);
               if(ticket>-1) 
               {
                 ticket = OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
                 ticket = OrderModify(ticket,OrderOpenPrice(),StopLossLevel,TakeProfitLevel,0,Green);
               }
                              
               // Error Handling
               if(ticket==-1)
                 {
                  ErrorCode=GetLastError();
                  string ErrDesc=ErrorDescription(ErrorCode);
                  //string ErrAlert=StringConcatenate("Buy - Error "+Symb+" "+BuyLevel+StopLss*Point,ErrorCode,": ",ErrDesc);
                  string ErrAlert=StringConcatenate("Buy - Error " + BuyLevel*Point,ErrorCode,": ",ErrDesc);
                  Alert(ErrAlert);
                  string ErrLog=StringConcatenate("Bid: ",MarketInfo(Symb,MODE_BID)," Ask: ",MarketInfo(Symb,MODE_ASK)," Lots: ",Lts);
                  Print(ErrLog);
                  return(false);
                 }
           }
         else
         
         
         if (Close[1]<Open[1] && Close[2]>Open[2])
           {
               if (UseStopLoss) StopLossLevel = Bid + StopLoss * Point * P; else StopLossLevel = 0.0;
               if (UseTakeProfit) TakeProfitLevel = Bid - TakeProfit * Point * P; else TakeProfitLevel = 0.0;

               RefreshRates();

               if((Bid-SellLevel)<10*Point)
                 {
                  Print("Invalid Entry Price or Distance on "+Symb);
                  Print(Symb+" Selllevel "+SellLevel);
                  return(99);
                 }
                 
               ticket=OrderSend(Symb,OP_SELLSTOP,Lts,Bid,Slippge,0,0,"",MagicNmber,0,Green);
               if(ticket>-1) 
               {
                 ticket = OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
                 ticket = OrderModify(ticket,OrderOpenPrice(),StopLossLevel,TakeProfitLevel,0,Green);
               }
                                
               //ticket=OrderSend(Symb,OP_SELLSTOP,Lts,Bid,Slippge,StopLossLevel,TakeProfitLevel,"PendingEA-Rob",MagicNmber,0,Red);
               // Error Handling
               if(ticket==-1)
                 {
                  ErrorCode=GetLastError();
                  ErrDesc=ErrorDescription(ErrorCode);
                  //ErrAlert=StringConcatenate("Sell - Error "+Symb+" "+StopLossLevel+StopLss*Point,ErrorCode,": ",ErrDesc);
                  ErrAlert=StringConcatenate("Sell - Error " + SellLevel*Point,ErrorCode,": ",ErrDesc);
                  Alert(ErrAlert);
                  ErrLog=StringConcatenate("Bid: ",MarketInfo(Symb,MODE_BID)," Ask: ",MarketInfo(Symb,MODE_ASK)," Lots: ",Lts);
                  Print(ErrLog);
                  return(false);
                 }
           }
         return(0);
        }
      EntryAllow=false;
     }


//------------TRAILING STOP SECTION-----------//
   if(TrailingStop>0 && subTotalTrade(Symb)>0)
     {
      total=OrdersTotal();
      for(cnt=0;cnt<total;cnt++)
        {
         ticket=OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);

         if(OrderType()<=OP_SELL && 
            OrderSymbol()==Symb && 
            OrderMagicNumber()==MagicNumber)
           {
            subTrailingStop(OrderType());
            return(0);
           }
        }
     }
   if(total==1)
     {
      subDeleteOrder(Symb);
      TradeAllow=false;
     }
   return(4);
  }


//+------------------------------------------------------------------+
//| Check for new bar                                                |
//+------------------------------------------------------------------+
void Check_New_Bar()
  {
   static datetime New_Time=0;
   New_Bar=false;
   if(New_Time!=Time[0])
     {
      New_Time= Time[0];
      New_Bar = true;
     }
  }
//+------------------------------------------------------------------+

