//+------------------------------------------------------------------+
//|                                                                  |
//|                                Copyright ?2014, pipster          |
//|                                SteadyGold Limit Order Ver.       |
//+------------------------------------------------------------------+
#property copyright "©PIPSTER"
#property link      ""
#include <stdlib.mqh>
#include <stderror.mqh> 

// Input parameters
input double Lots = 0;
input double LotPercent = 1;
input double TP = 9999;
input bool UseBE=false;
input double BE = 100;
input double LockIn=00;
input bool UseSL = false;
input double SL = 0;
input double Buffer = 60;
input double GridStep = 40;
input double Slip = 50;
input int NoOfSteps =  3;
input double EquityGainMultiple = 15;
input double EquityLossMultiple = 15;
input int StartingHour = 12;
input int StartingMin = 29;
input int StartingSecond = 01; 
input int StoppingHour = 12;
input int StoppingMin = 30;

double CurrentPL;
string Pair;
double StartingEquity, LS;
double EquityGain, DesiredEquity, MaxLoss;
bool StartTrade = false;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
     GlobalVariablesDeleteAll();
     Pair = Symbol();
     return(0);
}
  
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
     return(0);
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
   int i;
   double Step = MarketInfo(Pair,MODE_LOTSTEP);
   
   if(Lots!=0)
      LS=Lots;
   else
      LS = MathCeil((LotPercent/1000)*AccountBalance())*Step;      
   
   EquityGain = EquityGainMultiple*100*LS;
   double EquityLoss = EquityLossMultiple*100*LS;
   
   bool OpenOrdersExist;
   OpenOrdersExist = false;

   for(int cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
      OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES);
      if (OrderSymbol() == Pair)
      {
         if(OrderComment()=="Gold Mine Buy"||OrderComment()=="Gold Mine Sell")
            OpenOrdersExist = true;
      }
   }
   if(!OpenOrdersExist)
   {
      WriteStartingEquity();
   }
   
   ReadStartingEquity();
   DesiredEquity = StartingEquity + EquityGain;
   MaxLoss = StartingEquity - EquityLoss;
   
   Comment("Current Time:"+Hour()+":"+Minute()+"\nStarting Equity: "+StartingEquity+" Max Loss: "+EquityLoss+"\nCurrent P/L: "+CurrentPL+" Current LotSize: "+LS);
   
   CheckPL();
   CheckNoOfTrades();
   
   if(UseBE)
      ModifyOrders();
      
   CheckTime();
   return(0);
}

//+------------------------------------------------------------------+
//|  Check Time function                                             |
//+------------------------------------------------------------------+
void CheckTime()
{
   if(DayOfWeek()>=0 && DayOfWeek()<=6)
   {
      if(Hour() == StartingHour && Minute() == StartingMin && Seconds() >= StartingSecond)
         StartTrade=true;
   }      
   if(Hour() == StoppingHour && Minute() == StoppingMin)
      StartTrade=false;
   
   if(StartTrade)
      CheckForOpenOrders();
}


//+------------------------------------------------------------------+
//|  Check for Open Orders function                                  |
//+------------------------------------------------------------------+
void  CheckForOpenOrders()
{
   bool OpenOrdersExist = false;

   for(int cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
      OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES);
      if (OrderSymbol() == Pair)
      {
         if(OrderComment()=="Gold Mine Buy"||OrderComment()=="Gold Mine Sell")
            OpenOrdersExist = true;
      }
   }
   if(!OpenOrdersExist)
   {
      WriteStartingEquity();
      PlacePendingOrders();
   }
   else
   {
   }   
   return(0);
}

//+------------------------------------------------------------------+
//|  Place Pending Orders function                                   |
//+------------------------------------------------------------------+
void PlacePendingOrders()
{
   
   double BuyOpenPrice, SellOpenPrice;
   bool BuyTradePlacedProperly, SellTradePlacedProperly;
   int cnt;
   double Spread = MarketInfo(Pair,MODE_SPREAD)*Point;
   
   double AskPrice = Ask;
   double BidPrice = Bid;
   
   for(cnt=1;cnt<NoOfSteps+1;cnt++)
   {
      
      if(cnt == 1)
      {
         BuyOpenPrice = AskPrice+Buffer*Point;
         BuyTradePlacedProperly = OpenBuyPendingOrder(BuyOpenPrice);
         
         SellOpenPrice = BidPrice-Buffer*Point;
         SellTradePlacedProperly = OpenSellPendingOrder(SellOpenPrice);
      }
      if(cnt > 1)
      {
         BuyOpenPrice = BuyOpenPrice+(GridStep*Point)+Spread;
         BuyTradePlacedProperly = OpenBuyPendingOrder(BuyOpenPrice);
         
         SellOpenPrice = SellOpenPrice-(GridStep*Point)-Spread;
         SellTradePlacedProperly = OpenSellPendingOrder(SellOpenPrice);
      }   
      if(!BuyTradePlacedProperly&&!SellTradePlacedProperly)
      {
       return(0);  
      }
   }
}

//+------------------------------------------------------------------+
//|  Open Buy Pending Orders function                                |
//+------------------------------------------------------------------+
bool OpenBuyPendingOrder(double BOP)
{
   int TicketNumberBuy;
   double TProfit, SLoss;
   double Spread = MarketInfo(Pair,MODE_SPREAD)*Point;
   bool PlacedTrade = false;
   bool ModifiedTrade = false;
   double Free = AccountBalance();
   double OneLot = MarketInfo(Pair,MODE_MARGINREQUIRED);
   double Step = MarketInfo(Pair,MODE_LOTSTEP);   
   
   TicketNumberBuy = OrderSend(Pair,OP_SELLLIMIT,LS,BOP,Slip,0,0,"Gold Mine Buy");
   
   if(TicketNumberBuy == -1)
   {
      Alert("Buy Order failed, Error NO: "+GetLastError());
      PlacedTrade = false;
   }
   else
   {
      PlacedTrade = true;
   }
   if(PlacedTrade)
   {
      if(OrderSelect(TicketNumberBuy,SELECT_BY_TICKET)==true)
      {
         TProfit = OrderOpenPrice() + TP*Point;
         if(UseSL)
         {
            SLoss = OrderOpenPrice() - Spread - SL*Point;
         }
         else
         {
            SLoss = OrderStopLoss();
         }
         if(OrderModify(OrderTicket(),OrderOpenPrice(),SLoss,TProfit,0,0)==true)
         {
            ModifiedTrade = true;
         }
         else
            Alert("Error modifying BuyTrade= "+GetLastError());
      }
   }
   return(true);
}

//+------------------------------------------------------------------+
//|  Open Sell Pending Orders function                               |
//+------------------------------------------------------------------+
bool OpenSellPendingOrder(double SOP)
{
   int TicketNumberSell;
   double TProfit, SLoss;
   double Spread = MarketInfo(Pair,MODE_SPREAD)*Point;
   bool PlacedTrade = false;
   bool ModifiedTrade = false;
   double Free = AccountBalance();
   double OneLot = MarketInfo(Pair,MODE_MARGINREQUIRED);
   double Step = MarketInfo(Pair,MODE_LOTSTEP);   
   
   TicketNumberSell = OrderSend(Pair,OP_BUYLIMIT,LS,SOP,Slip,0,0,"Gold Mine Sell");
   
   if(TicketNumberSell == -1)
   {
      Alert("Sell Order failed, Error No: "+GetLastError());
      PlacedTrade = false;
   }
   else
   {
      PlacedTrade = true;
   }
   if(PlacedTrade)
   {
      if(OrderSelect(TicketNumberSell,SELECT_BY_TICKET)==true)
      {
         TProfit = OrderOpenPrice() - TP*Point;
         if(UseSL)
         {
            SLoss = OrderOpenPrice() + Spread + SL*Point;
         }
         else
         {
            SLoss = OrderStopLoss();
         }
         if(OrderModify(OrderTicket(),OrderOpenPrice(),SLoss,TProfit,0,0)==true)
         {
            ModifiedTrade = true;
         }
         else
            Alert("Error modifying SellTrade= "+GetLastError());
      }
   }

   return(true);
}

//+------------------------------------------------------------------+
//|  ReadStartingEquity function                                     |
//+------------------------------------------------------------------+
void ReadStartingEquity()
{
   if(GlobalVariableCheck("StartEquity"))
   {
      StartingEquity = GlobalVariableGet("StartEquity");
   }
   else
   {
      StartingEquity = AccountEquity();
      GlobalVariableSet("StartEquity",StartingEquity);
   }
}

//+------------------------------------------------------------------+
//|  WriteStartingEquity function                                    |
//+------------------------------------------------------------------+
void WriteStartingEquity()
{
   if(GlobalVariableSet("StartEquity",AccountEquity())>0)
   {
   } 
   else 
      Alert("Error writing Starting Equity: ",GetLastError());
}

//+------------------------------------------------------------------+
//|  CheckPL function                                                |
//+------------------------------------------------------------------+
void CheckPL()
{
   CurrentPL=0;
   for (int i=OrdersTotal()-1;i>=0;i--) 
   {
      OrderSelect(i,SELECT_BY_POS);
      if(OrderSymbol()==Pair)
      {
         if(OrderType()==OP_BUY||OrderType()==OP_SELL)
         {
            CurrentPL = CurrentPL+OrderProfit();
         }
      }
   }
   if(AccountEquity()>DesiredEquity||AccountEquity()<MaxLoss)
      CloseAllOrders();
}

//+------------------------------------------------------------------+
//|  Check No of trades function                                     |
//+------------------------------------------------------------------+
void CheckNoOfTrades()
{
   int BC=0;
   int SC=0;
   for (int i=OrdersTotal()-1;i>=0;i--) 
   {
      OrderSelect(i,SELECT_BY_POS);
      if(OrderSymbol()==Pair)
      {
         if(OrderType()==OP_BUY||OrderType()==OP_SELLLIMIT)
         {
            BC = BC+1;
         }
         if(OrderType()==OP_SELL||OrderType()==OP_BUYLIMIT)
         {
            SC = SC+1;
         }
      }
   }
   if(BC==0||SC==0)
      CloseAllOrders();
}

//+------------------------------------------------------------------+
//|  Close All Orders function                                       |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
   for(int count = 0; count<3; count ++)
   {
      // iterate the orders
      for (int i=OrdersTotal()-1;i>=0;i--) 
      {
         // select the order
         OrderSelect(i,SELECT_BY_POS);
         // close or kill depending on order type
         if(OrderSymbol()==Pair)
         {
            if(OrderComment()=="Gold Mine Buy"||OrderComment()=="Gold Mine Sell")
            {
               switch(OrderType()) 
               {
                  case OP_BUY:  OrderClose(OrderTicket(),OrderLots(),Bid,Slip); break;
                  case OP_SELL: OrderClose(OrderTicket(),OrderLots(),Ask,Slip); break;
                  default:      break;
               }
            }   
         }       
      }
      Sleep(300);
   }
   for(count = 0; count<3; count ++)
   {
      // iterate the orders
      for (i=OrdersTotal()-1;i>=0;i--) 
      {
         // select the order
         OrderSelect(i,SELECT_BY_POS);
         // close or kill depending on order type
         if(OrderSymbol()==Pair)
         {
            if(OrderComment()=="Gold Mine Buy"||OrderComment()=="Gold Mine Sell")
            {
               switch(OrderType()) 
               {
                  case OP_BUYSTOP:  OrderDelete(OrderTicket()); break;
                  case OP_BUYLIMIT:  OrderDelete(OrderTicket()); break;
                  case OP_SELLSTOP: OrderDelete(OrderTicket()); break;
                  case OP_SELLLIMIT: OrderDelete(OrderTicket()); break;
               }
            }   
         }       
      }
      Sleep(300);
   }
   return(0);
}

//+------------------------------------------------------------------+
//|  Modify Orders function                                          |
//+------------------------------------------------------------------+
void ModifyOrders()
{
   double SLoss;
   for (int i=OrdersTotal()-1;i>=0;i--) 
   {
      OrderSelect(i,SELECT_BY_POS);
      if(OrderSymbol()==Pair)
      {
         if(OrderType()==OP_BUY)
         {
            if(OrderComment()=="London Grid EA Buy")
            {
               if(OrderStopLoss()==0)
               {
                  if(Bid > (OrderOpenPrice()+BE*Point))
                  {
                     SLoss = OrderOpenPrice()+LockIn*Point;
                     if(OrderModify(OrderTicket(),OrderOpenPrice(),SLoss,OrderTakeProfit(),0,0)==true)
                     {
                     }
                     else
                        GetLastError();
                  }
               }
            }
         }
         if(OrderType()==OP_SELL)
         {
            if(OrderComment()=="London Grid EA Sell")
            {
               if(OrderStopLoss()==0)
               {
                  if(Ask < (OrderOpenPrice()-BE*Point))
                  {
                     SLoss = OrderOpenPrice()-LockIn*Point;
                     if(OrderModify(OrderTicket(),OrderOpenPrice(),SLoss,OrderTakeProfit(),0,0)==true)
                     {
                     }
                     else
                        GetLastError();
                  }
               }
            }
         }
      }
   }   
}

