//+------------------------------------------------------------------+
//|                                                   Market_Buy.mq4 |
//|                                                         Zen_Leow |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Zen_Leow"
#property link      ""

// comment away the below line if you want instant execution with default inputs
#property show_inputs

#include <stdlib.mqh>
#include <stderror.mqh>

// This is where you set the default values for those input variables.
extern int       EA_MAGIC_NUM = 12345;
extern int       UserDefinedSpread = 0;
extern int       Slippage = 3;
extern double    TakeProfit = 10;
extern double    StopLoss = 15;
extern bool      Add_Spread_To_StopLoss = true;

extern bool      MoneyManagement = true;
extern bool      UseEquity = false;
extern double    RiskPercent = 1.5;
extern double    FixedLots = 1.0;
extern double    MaxLots = 15.0;
extern double    MinLots = 0.01;
extern int       LotsDecimalAllowed = 2;

string msg = "";
int CustomSpread = 0;
int PipFactor = 1;
int the_StopLoss = 0;


void GetSpread()
{
   // Cater for fractional pips
   if (Digits == 3 || Digits == 5)
   {
      PipFactor = 10;
   }
   
   if (UserDefinedSpread <= 0)
   {
      CustomSpread = (MarketInfo(Symbol(),MODE_SPREAD))  / PipFactor;
   }
   else
   {
      CustomSpread = UserDefinedSpread;
   }
   
   // Should we add the spread into the StopLoss?
   the_StopLoss = StopLoss;
   if (StopLoss > 0)
   {
      if (Add_Spread_To_StopLoss)
      {
         the_StopLoss = StopLoss + CustomSpread;
      }
      else
      {
         the_StopLoss = StopLoss;
      }
   }
}

bool SendOrders (int BuyOrSell, double LotSize, double PriceToOpen, double Slippage, double SL_Price, double TP_Price, string comments, datetime ExpirationTime)
{
   int ticket, errorType;
   
   if (BuyOrSell == OP_BUY)
   {  
      Print("Bid: "+Bid+" Ask: "+Ask+" | Opening Buy Order: "+Symbol()+", "+BuyOrSell+", "+LotSize+", "+PriceToOpen+", "+Slippage+", "+SL_Price+", "+TP_Price+", "+comments+", "+ExpirationTime+", Green");
      ticket=OrderSend(Symbol(),BuyOrSell,LotSize,PriceToOpen,Slippage,SL_Price,TP_Price,comments,EA_MAGIC_NUM,ExpirationTime,Green);
      if(ticket>0)
      {
         if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
         {
            Print("BUY order opened : ",OrderOpenPrice());
            msg = ticket + ": Buy position opened on "+Symbol()+" at "+ Day()+"/"+Month()+"/"+Year()+" - "+Hour()+":"+Minute()+":"+Seconds();
            Print(msg);
            return (true);
         }
      }
      else 
      {  
         errorType = GetLastError();
         Print("Error opening BUY order : ", ErrorDescription(errorType));
         msg = "CANNOT open BUY position on "+Symbol()+" at "+ Day()+"/"+Month()+"/"+Year()+" - "+Hour()+":"+Minute()+":"+Seconds();
         Print(msg);
         return (false);
      }
   }
   if (BuyOrSell == OP_SELL)
   {  
      Print("Bid: "+Bid+" Ask: "+Ask+" | Opening Sell Order: "+Symbol()+", "+BuyOrSell+", "+LotSize+", "+PriceToOpen+", "+Slippage+", "+SL_Price+", "+TP_Price+", "+comments+", "+ExpirationTime+", Red");
      ticket=OrderSend(Symbol(),BuyOrSell,LotSize,PriceToOpen,Slippage,SL_Price,TP_Price,comments,EA_MAGIC_NUM,ExpirationTime,Red);
      if(ticket>0)
      {
         if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
         {
            Print("Sell order opened : ",OrderOpenPrice());
            msg = ticket + ": Sell position opened on "+Symbol()+" at "+ Day()+"/"+Month()+"/"+Year()+" - "+Hour()+":"+Minute()+":"+Seconds();
            Print(msg);
            return (true);
         }
      }
      else 
      {  
         errorType = GetLastError();
         Print("Error opening SELL order : ", ErrorDescription(errorType));
         msg = "CANNOT open SELL position on "+Symbol()+" at "+ Day()+"/"+Month()+"/"+Year()+" - "+Hour()+":"+Minute()+":"+Seconds();
         Print(msg);
         return (false);
      }
   }
}

double PositionSizeToOpen(int StopLossPips)
{
   double PositionSize;
   double riskDollars;
   
   if (MoneyManagement && StopLossPips > 0)
   {      
      if (UseEquity)
      {
         riskDollars = (AccountEquity()/100) * RiskPercent;
      }
      else
      {
         riskDollars = (AccountBalance()/100) * RiskPercent;
      }
      PositionSize = (riskDollars / StopLossPips) / (MarketInfo(Symbol(),MODE_TICKVALUE) * PipFactor);
   }
   
   if (MoneyManagement && StopLossPips <= 0)
   {
      if (UseEquity)
      {
         PositionSize = ((AccountEquity()/100) * RiskPercent) / (MarketInfo(Symbol(),MODE_LOTSIZE) / AccountLeverage());
      }
      else
      {
         PositionSize = ((AccountBalance()/100) * RiskPercent) / (MarketInfo(Symbol(),MODE_LOTSIZE) / AccountLeverage());
      }
   }
   
   if (!MoneyManagement)
   {
      PositionSize = FixedLots;
   }
   
   if (PositionSize < MinLots)
   {
      PositionSize = MinLots;
   }
   if (PositionSize > MaxLots)
   {
      PositionSize = MaxLots;
   }
   PositionSize = NormalizeDouble(PositionSize,LotsDecimalAllowed);
   return (PositionSize);
}

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
{
//----
   GetSpread();
   double PriceToOpen;
   double TakeProfitPrice;
   double StopLossPrice;
    
   PriceToOpen = Ask;
   if (TakeProfit == 0)
   {
      TakeProfitPrice = 0;
   }
   else
   {
      TakeProfitPrice = PriceToOpen + (TakeProfit * Point * PipFactor);
      TakeProfitPrice = NormalizeDouble(TakeProfitPrice,Digits);
   }
   
   if (the_StopLoss == 0)
   {
      StopLossPrice = 0;
   }
   else
   {
      StopLossPrice = PriceToOpen - (the_StopLoss * Point * PipFactor);
      StopLossPrice = NormalizeDouble(StopLossPrice,Digits);
   }
   SendOrders(OP_BUY, PositionSizeToOpen(the_StopLoss), PriceToOpen, Slippage, StopLossPrice, TakeProfitPrice, "Market_Buy-"+EA_MAGIC_NUM, 0);
//----
   return(0);
}
//+------------------------------------------------------------------+