//+------------------------------------------------------------------+
//|                                               MACD Histogram.mq4 |
//|     Copyright © 2006, firedave based on babarmughal trading plan | 
//|                    Partial Function Copyright © 2006, codersguru | 
//|                        Partial Function Copyright © 2006, pengie |
//|                 MACD Indicator Copyright © 2005, David W. Thomas | 
//|                                        http://www.fx-review.com/ | 
//|                                        http://www.forex-tsd.com/ | 
//+------------------------------------------------------------------+

#property copyright "Copyright © 2006, firedave"
#property link      "http://www.fx-review.com"


//----------------------- INCLUDES
#include <stdlib.mqh>


//----------------------- EA PARAMETER
extern string  
         Expert_Name       = "---------- MACD Histogram EA v1";
extern double 
         StopLoss          = 100,
         TakeProfit        = 0,
         TrailingStop      = 40;

extern string  
         Indicator_Setting = "---------- Indicator Setting";
extern int
         FastMAPeriod      = 12,
         SlowMAPeriod      = 26,
         SignalMAPeriod    = 9;         

extern string  
         Exit_Setting      = "---------- Exit Setting";
extern bool
         ConfirmedOnEntry  = true,  // TRUE:entry on the next signal bar
         StopAndReverse    = true,  // TURE:if signal change, exit and reverse order
         PureSAR           = true,  // TRUE:no SL, no TP, no TS
         OneEntryPerBar    = true;
extern string  
         Order_Setting     = "---------- Order Setting";
extern int
         NumberOfTries     = 5,
         Slippage          = 5;

extern string  
         Time_Parameters   = "---------- EA Active Time";
extern bool    
         UseHourTrade      = false;         
extern int     
         StartHour         = 10,
         EndHour           = 11;
         
extern string  
         MM_Parameters     = "---------- Money Management";
extern double 
         Lots              = 1;
extern bool 
         MM                = false, //Use Money Management or not
         AccountIsMicro    = false; //Use Micro-Account or not
extern int 
         Risk              = 10; //10%

extern bool 
         Show_Settings     = true;


//----------------------- GLOBAL VARIABLE
static int 
         TimeFrame         = 0;
string
         TicketComment     = "MACDHistogramEA v1",
         LastTrade;
int
         MagicNumber       = 1234;

double
         alpha             = 0,
         alpha_1           = 0;
         
datetime
         CheckTime,
         CheckEntryTime;  



//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{

//----------------------- GENERATE MAGIC NUMBER AND TICKET COMMENT
//----------------------- SOURCE : PENGIE
   MagicNumber    = subGenerateMagicNumber(MagicNumber, Symbol(), Period());
	TicketComment  = StringConcatenate(TicketComment, "-", Symbol(), "-", Period());
   if(Show_Settings) subPrintDetails();
   else Comment("");
   
//----------------------- INITIALIZE PURE Stop And Reverse
//----------------------- NO STOP LOSS, NO TAKE PROFIT, NO TRAILING STOP
   if(PureSAR)
   {
      StopLoss       = 0;
      TakeProfit     = 0;
      TrailingStop   = 0;
   }

//----------------------- INITIALIZE MACD VARIABLE
 	alpha          = 2.0 / (SignalMAPeriod + 1.0);
	alpha_1        = 1.0 - alpha;

	
   return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
 
//----------------------- PREVENT RE-COUNTING WHILE USER CHANGING TIME FRAME
//----------------------- SOURCE : CODERSGURU
   TimeFrame=Period(); 
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
{
   double 
         HistogramBufferPrevious,
         HistogramBufferCurrent;
                   
   int   
         cnt,
         ticket,
         total;
         
   bool
         BuyCondition,
         SellCondition;
                 
         
//----------------------- TIME FILTER
   if (UseHourTrade)
   {
      if(!(Hour()>=StartHour && Hour()<=EndHour))
      {
         Comment("Non-Trading Hours!");
         return(0);
      }
   }
//----------------------- ONE ENTRY PER BAR
      if(OneEntryPerBar)
      {
         if(CheckEntryTime== iTime(NULL,TimeFrame,0)) return(0); else CheckEntryTime = iTime(NULL,TimeFrame,0);
      }         


//----------------------- CHECK CHART NEED MORE THAN 100 BARS
   if(Bars<100)
   {
      Print("bars less than 100");
      return(0);  
   }


//----------------------- ADJUST LOTS IF USING MONEY MANAGEMENT
   if(MM) Lots = subLotSize();


//----------------------- SET VALUE FOR VARIABLE
//----------------------- MACD
   if(ConfirmedOnEntry)
   {
      HistogramBufferPrevious = iCustom(NULL,TimeFrame,"iMACD",FastMAPeriod,SlowMAPeriod,SignalMAPeriod,2,2);
      HistogramBufferCurrent  = iCustom(NULL,TimeFrame,"iMACD",FastMAPeriod,SlowMAPeriod,SignalMAPeriod,2,1);
   }
   else
   {
      HistogramBufferPrevious = iCustom(NULL,TimeFrame,"iMACD",FastMAPeriod,SlowMAPeriod,SignalMAPeriod,2,1);
      HistogramBufferCurrent  = iCustom(NULL,TimeFrame,"iMACD",FastMAPeriod,SlowMAPeriod,SignalMAPeriod,2,0);
   }
   

//----------------------- CONDITION CHECK
//----------------------- BUY CONDITION   
   BuyCondition      = (HistogramBufferPrevious<HistogramBufferCurrent &&
                        HistogramBufferPrevious<=0 &&
                        HistogramBufferCurrent>=0);

//----------------------- SELL CONDITION   
   SellCondition     = (HistogramBufferPrevious>HistogramBufferCurrent &&
                        HistogramBufferPrevious>=0 &&
                        HistogramBufferCurrent<=0);   



//----------------------- EXIT CONDITION
//----------------------- not available



//----------------------- STOP AND REVERSE
if(StopAndReverse)
   {
      if((StopAndReverse && LastTrade=="BUY" && SellCondition) ||
         (StopAndReverse && LastTrade=="SELL" && BuyCondition))
      {
         total = OrdersTotal();
         for(cnt=0;cnt<total;cnt++)
         {
            OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

            if(OrderType()<=OP_SELL &&
               OrderSymbol()==Symbol() &&
               OrderMagicNumber()==MagicNumber)
            {
               if(OrderType()==OP_BUY)   // buy position is opened   
               {
                  OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,Violet);
                  return(0);
               }
               if(OrderType()==OP_SELL)   // sell position is opened   
               {
                  OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Violet);
                  return(0);
               }
            }
         }  
      }
   }


//----------------------- ENTRY
//----------------------- TOTAL ORDER BASE ON MAGICNUMBER AND SYMBOL
   total = subTotalTrade();

//----------------------- IF NO TRADE
   if(total<1) 
   {
//----------------------- BUY CONDITION   
      if(BuyCondition)
      {
         ticket      = subOpenOrder(OP_BUY); // open BUY order
         subCheckError(ticket,"BUY");
         LastTrade   = "BUY";
         return(0);
      }

//----------------------- SELL CONDITION   
      if(SellCondition)
      {
         ticket      = subOpenOrder(OP_SELL); // open SELL order
         subCheckError(ticket,"SELL");
         LastTrade   = "SELL";
         return(0);
      }
      return(0);
   }
   
//----------------------- TRAILING STOP SECTION
   if(TrailingStop>0)
   {
      total = OrdersTotal();
      for(cnt=0;cnt<total;cnt++)
      {
         OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

         if(OrderType()<=OP_SELL &&
            OrderSymbol()==Symbol() &&
            OrderMagicNumber()==MagicNumber)
         {
            if(OrderType()==OP_BUY)   // buy position is opened   
            {
               subTrailingStop(OrderType());
               return(0);
            }
            if(OrderType()==OP_SELL)   // sell position is opened   
            {
               subTrailingStop(OrderType());
               return(0);
            }
         }
      }
   }            
   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()
{
   int
      cnt, 
      total = 0;

   for(cnt=0;cnt<OrdersTotal();cnt++)
   {
      OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
      if(OrderType()<=OP_SELL &&
         OrderSymbol()==Symbol() &&
         OrderMagicNumber()==MagicNumber) total++;
   }
   return(total);
}

//----------------------- OPEN ORDER FUNCTION
//----------------------- SOURCE   : CODERSGURU
//----------------------- SOURCE   : PENGIE
//----------------------- MODIFIED : FIREDAVE
int subOpenOrder(int type)
{
   int
         ticket      = 0,
         err         = 0,
         c           = 0;
         
   double         
         aStopLoss   = 0,
         aTakeProfit = 0,
         bStopLoss   = 0,
         bTakeProfit = 0;

   if(StopLoss!=0)
   {
      aStopLoss   = Ask-StopLoss*Point;
      bStopLoss   = Bid+StopLoss*Point;
   }
   
   if(TakeProfit!=0)
   {
      aTakeProfit = Ask+TakeProfit*Point;
      bTakeProfit = Bid-TakeProfit*Point;
   }
   
   if(type==OP_BUY)
   {
      for(c=0;c<NumberOfTries;c++)
      {
         ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,aStopLoss,aTakeProfit,TicketComment,MagicNumber,0,Green);
         err=GetLastError();
         if(err==0)
         { 
            break;
         }
         else
         {
            if(err==4 || err==137 ||err==146 || err==136) //Busy errors
            {
               Sleep(5000);
               continue;
            }
            else //normal error
            {
               break;
            }  
         }
      }   
   }
   if(type==OP_SELL)
   {   
      for(c=0;c<NumberOfTries;c++)
      {
         ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,bStopLoss,bTakeProfit,TicketComment,MagicNumber,0,Red);
         err=GetLastError();
         if(err==0)
         { 
            break;
         }
         else
         {
            if(err==4 || err==137 ||err==146 || err==136) //Busy errors
            {
               Sleep(5000);
               continue;
            }
            else //normal error
            {
               break;
            }  
         }
      }   
   }  
   return(ticket);
}

//----------------------- TRAILING STOP FUNCTION
//----------------------- SOURCE   : CODERSGURU
//----------------------- MODIFIED : FIREDAVE
void subTrailingStop(int Type)
{
   if(Type==OP_BUY)   // buy position is opened   
   {
      if(Bid-OrderOpenPrice()>Point*TrailingStop &&
         OrderStopLoss()<Bid-Point*TrailingStop)
      {
         OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
         return(0);
      }
   }

   if(Type==OP_SELL)   // sell position is opened   
   {
      if(OrderOpenPrice()-Ask>Point*TrailingStop)
      {
      if(OrderStopLoss()>Ask+Point*TrailingStop || OrderStopLoss()==0)
      {
         OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
         return(0);
      }
      }
   }
}



//----------------------- CHECK ERROR CODE FUNCTION
//----------------------- SOURCE : CODERSGURU
void subCheckError(int ticket, string Type)
{
    if(ticket>0) 
    {
      if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print(Type + " order opened : ",OrderOpenPrice());
    }
    else Print("Error opening " + Type + " order : ", ErrorDescription(GetLastError()));
}

//----------------------- GENERATE MAGIC NUMBER BASE ON SYMBOL AND TIME FRAME FUNCTION
//----------------------- SOURCE   : PENGIE
//----------------------- MODIFIED : FIREDAVE
int subGenerateMagicNumber(int MagicNumber, string symbol, int timeFrame)
{
   int isymbol = 0;
   if (symbol == "EURUSD")       isymbol = 1;
   else if (symbol == "GBPUSD")  isymbol = 2;
   else if (symbol == "USDJPY")  isymbol = 3;
   else if (symbol == "USDCHF")  isymbol = 4;
   else if (symbol == "AUDUSD")  isymbol = 5;
   else if (symbol == "USDCAD")  isymbol = 6;
   else if (symbol == "EURGBP")  isymbol = 7;
   else if (symbol == "EURJPY")  isymbol = 8;
   else if (symbol == "EURCHF")  isymbol = 9;
   else if (symbol == "EURAUD")  isymbol = 10;
   else if (symbol == "EURCAD")  isymbol = 11;
   else if (symbol == "GBPUSD")  isymbol = 12;
   else if (symbol == "GBPJPY")  isymbol = 13;
   else if (symbol == "GBPCHF")  isymbol = 14;
   else if (symbol == "GBPAUD")  isymbol = 15;
   else if (symbol == "GBPCAD")  isymbol = 16;
   else                          isymbol = 17;
   if(isymbol<10) MagicNumber = MagicNumber * 10;
   return (StrToInteger(StringConcatenate(MagicNumber, isymbol, timeFrame)));
}

//----------------------- PRINT COMMENT FUNCTION
//----------------------- SOURCE : CODERSGURU
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,0) + " | ";
   sComment = sComment + "MM=" + subBoolToStr(MM) + " | ";
   sComment = sComment + "Risk=" + DoubleToStr(Risk,0) + "%" + NL;
   sComment = sComment + sp;
  
   Comment(sComment);
}

//----------------------- BOOLEN VARIABLE TO STRING FUNCTION
//----------------------- SOURCE : CODERSGURU
string subBoolToStr ( bool value)
{
   if(value) return ("True");
   else return ("False");
}


//----------------------- END FUNCTION