//+------------------------------------------------------------------+
//|                                                Iandecoker EA.mq4 |
//|                                  Programmer:  Rob Rice (blueruby)| 
//|                                Parital Copyright © 2006 firedave |
//|                    Partial Function Copyright © 2006, codersguru | 
//|                        Partial Function Copyright © 2006, pengie |
//+------------------------------------------------------------------+

#property copyright ""
#property link      ""


//----------------------- INCLUDES
#include <stdlib.mqh>

//----------------------- EA PARAMETER
extern string  
         Expert_Name       = "---------- Iandecoker v1.1";
extern double 
         StopLoss          = 30,
         TakeProfit        = 30,
         TrailingStop      = 0;

extern int 
         ADXPeriod         = 7,
         ADXPrice          = 0,    //0:Close 1:Open 2:High 3:Low 4:Median 5:Typical 6:Weighted
         ADXEntryLevel     = 45;
         
extern string  
         Order_Setting     = "---------- Order Setting";
extern int
         MaxBuys           = 3,
         MaxSells          = 3,
         NumberOfTries     = 5,
         Slippage          = 1;
       int  
         MagicNumber       = 4321;

extern string  
         Time_Parameters   = "---------- EA Active Time";
extern bool    
         UseHourTrade      = true;
extern int     
         StartHour         = 8,
         EndHour           = 16;
         
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 string  
         Testing_Parameters= "---------- Back Test Parameter";
extern bool
         PrintControl      = true,
         Show_Settings     = true;


bool     
         newcandle;
datetime 
         candle;
int      
         lastbar,
         currbar;


//----------------------- GLOBAL VARIABLE
static int 
         TimeFrame         = 0;
string
         TicketComment     = "Iandecoker EA",
         LastTrade;





//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{

//----------------------- GENERATE MAGIC NUMBER AND TICKET COMMENT
//----------------------- SOURCE : PENGIE
   MagicNumber    = subGenerateMagicNumber(MagicNumber, Symbol(), Period());
	TicketComment  = StringConcatenate(TicketComment, " - M", Period());
   if(Show_Settings) subPrintDetails();
   else Comment("");
   
   return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
 
//----------------------- PREVENT RE-COUNTING WHILE USER CHANGING TIME FRAME
//----------------------- SOURCE : CODERSGURU
   TimeFrame=Period(); 
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
{
  
   int   
         cnt,
         ticket,
         totalbuys,
         totalsells;
         
   bool
         BuyCondition,
         SellCondition;
         
                
         
//----------------------- TIME FILTER
   if (UseHourTrade)
   {
      if(!(Hour()>=StartHour && Hour()<=EndHour))
      {
         Comment("Non-Trading Hours!");
         return(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();


//----------------------- CALCULATE INDICATORS

     
      double ADX1 = iADX(NULL,0,ADXPeriod,ADXPrice,MODE_MAIN,0);
      double ADX2 = iADX(NULL,0,ADXPeriod,ADXPrice,MODE_MAIN,1);
      
      double DIpos1 = iADX(NULL,0,ADXPeriod,ADXPrice,MODE_PLUSDI,0);
      double DIneg1 = iADX(NULL,0,ADXPeriod,ADXPrice,MODE_MINUSDI,0);
      
      double DIpos2 = iADX(NULL,0,ADXPeriod,ADXPrice,MODE_PLUSDI,1);
      double DIneg2 = iADX(NULL,0,ADXPeriod,ADXPrice,MODE_MINUSDI,1);
         
//----------------------- CONDITION CHECKS

      if(Time[0] > candle) 
         newcandle = TRUE;
      else
         newcandle = FALSE;
         
         
//----------------------- BUY CONDITION   

      BuyCondition   = (ADX1 >= ADXEntryLevel && DIpos1 >= ADXEntryLevel && (DIpos2 < ADXEntryLevel || ADX2 < ADXEntryLevel))
;      

//----------------------- SELL CONDITION
   
      SellCondition  = (ADX1 >= ADXEntryLevel && DIneg1 >= ADXEntryLevel && (DIneg2 < ADXEntryLevel || ADX2 < ADXEntryLevel)); 


//----------------------- TOTAL ORDER BASE ON MAGICNUMBER AND SYMBOL
   totalbuys = subTotalBuys();
   totalsells = subTotalSells();
 
//----------------------- ENTRY

//----------------------- IF NO TRADE
   if(totalbuys < MaxBuys) 
      {
//----------------------- BUY CONDITION   
      if(BuyCondition && newcandle)
         {
         ticket      = subOpenOrder(OP_BUY); // open BUY order
         subCheckError(ticket,"BUY");
         LastTrade   = "BUY";
         candle = Time[0];
         return(0);
         }
      }
      
//----------------------- SELL CONDITION   
   if(totalsells < MaxSells)   
      {
      if(SellCondition && newcandle)
         {
         ticket      = subOpenOrder(OP_SELL); // open SELL order
         subCheckError(ticket,"SELL");
         LastTrade   = "SELL";
         candle = Time[0];
         return(0);
         }
      return(0);
      }
   
//----------------------- TRAILING STOP SECTION
   if(TrailingStop>0)
      {
      int total = OrdersTotal();
      for(cnt=0;cnt<total;cnt++)
         {
         OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

         if(OrderType()<=OP_SELL &&
            OrderSymbol()==Symbol() &&
            OrderMagicNumber()==MagicNumber)
            {
            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 subTotalBuys()
   {
   int
      cnt, 
      total = 0;

   for(cnt=0; cnt < OrdersTotal(); cnt++)
      {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderType() == OP_BUY &&
         OrderSymbol() == Symbol() &&
         OrderMagicNumber() == MagicNumber) total++;
      }
   return(total);
   }

// ------------------------------   
   
int subTotalSells()
   {
   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)
         { 
            PlaySound("alert.wav");
            break;
         }
         else
         {
            if(err==4 || err==137 ||err==146 || err==136) //Busy errors
            {
               Sleep(1000);
               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)
         { 
            PlaySound("alert.wav");            
            break;
         }
         else
         {
            if(err==4 || err==137 ||err==146 || err==136) //Busy errors
            {
               Sleep(1000);
               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