UniversalMACrossEA-mod





//+------------------------------------------------------------------+
//|                                           UniversalMACrossEA.mq4 |
//|                                       Copyright © 2006, firedave | 
//|                    Partial Function Copyright © 2006, codersguru | 
//|                        Partial Function Copyright © 2006, pengie |
//|                                        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       = "---------- Universal MA Cross EA v5";
extern double 
         StopLoss          = 100,
         TakeProfit        = 200,
         TrailingStop      = 40;

extern string  
         Indicator_Setting = "---------- Indicator Setting";
extern int
         FastMAPeriod      = 10,
         FastMAType        = 1,    //0:SMA 1:EMA 2:SMMA 3:LWMA
         FastMAPrice       = 0,    //0:Close 1:Open 2:High 3:Low 4:Median 5:Typical 6:Weighted
         SlowMAPeriod      = 80,
         SlowMAType        = 1,    //0:SMA 1:EMA 2:SMMA 3:LWMA
         SlowMAPrice       = 0,    //0:Close 1:Open 2:High 3:Low 4:Median 5:Typical 6:Weighted
         MinCrossDistance  = 0;    //Always positive, 0:disable

extern string  
         Exit_Setting      = "---------- Exit Setting";
extern bool
         ReverseCondition  = false, // TRUE:buy-sell , sell-buy
         ConfirmedOnEntry  = true,  // TRUE:entry on the next signal bar
         OneEntryPerBar    = true,
         StopAndReverse    = true,  // TURE:if signal change, exit and reverse order
         PureSAR           = false;  // TRUE:no SL, no TP, no TS

extern string  
         ThirdEMA_Setting  = "---------- Third MA Setting";
extern bool
         UseThirdMA        = false,
         UseCounterTrend   = false;         
extern int
         ThirdMAPeriod     = 100,
         ThirdMAType       = 1,    //0:SMA 1:EMA 2:SMMA 3:LWMA
         ThirdMAPrice      = 0,    //0:Close 1:Open 2:High 3:Low 4:Median 5:Typical 6:Weighted
         CTStopLoss        = 0,
         CTTakeProfit      = 0;         
         
extern string  
         Order_Setting     = "---------- Order Setting";
extern int
         NumberOfTries     = 5,
         Slippage          = 5,
         MaxOpenTrade      = 2,
         MagicNumber       = 1234;

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 string  
         Alert_Setting     = "---------- Alert Setting";
extern bool
         EnableAlert       = true;
extern string
         SoundFilename     = "alert.wav";

extern string  
         Testing_Parameters= "---------- Back Test Parameter";
extern bool
         PrintControl      = true,
         Show_Settings     = true;


//----------------------- GLOBAL VARIABLE
static int 
         TimeFrame         = 0;
string
         TicketComment     = "UniversalMACrossEA v5",
         LastTrade,
         LastAlert;
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());

//----------------------- SET MinCrossDistance ALWAYS POSITIVE
   MinCrossDistance = MathAbs(MinCrossDistance);

//----------------------- SHOW EA SETTING ON THE CHART
//----------------------- SOURCE : CODERSGURU
   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;
      StopAndReverse = true;
   }

//----------------------- MaxTrade ALWAYS >= 1
   if(MaxOpenTrade<=0) MaxOpenTrade = 1;
   
   return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
 
//----------------------- PREVENT RE-COUNTING WHILE USER CHANGING TIME FRAME
//----------------------- SOURCE : CODERSGURU
   TimeFrame=Period(); 
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
{
   double 
         FastMAPrevious,
         FastMACurrent,
         SlowMAPrevious,
         SlowMACurrent,
         ThirdMAValue;
                   
   int   
         cnt,
         ticket,
         total;
         
   bool
         BuyCondition,
         SellCondition,
         CounterTrend;
         
//----------------------- 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);  
   }

//----------------------- TRAILING STOP SECTION
   if(TrailingStop>0 && subTotalTrade()>0)
   {
      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());
         }
      }
   }            

//----------------------- ADJUST LOTS IF USING MONEY MANAGEMENT
   if(MM) Lots = subLotSize();


//----------------------- SET VALUE FOR VARIABLE
//----------------------- MACD
   if(ConfirmedOnEntry)
   {
      if(CheckTime==iTime(NULL,TimeFrame,0)) return(0); else CheckTime = iTime(NULL,TimeFrame,0);
   
      FastMAPrevious = iMA(NULL,TimeFrame,FastMAPeriod,0,FastMAType,FastMAPrice,2);
      FastMACurrent  = iMA(NULL,TimeFrame,FastMAPeriod,0,FastMAType,FastMAPrice,1);
      SlowMAPrevious = iMA(NULL,TimeFrame,SlowMAPeriod,0,SlowMAType,SlowMAPrice,2);
      SlowMACurrent  = iMA(NULL,TimeFrame,SlowMAPeriod,0,SlowMAType,SlowMAPrice,1);
   }
   else
   {
      FastMAPrevious = iMA(NULL,TimeFrame,FastMAPeriod,0,FastMAType,FastMAPrice,1);
      FastMACurrent  = iMA(NULL,TimeFrame,FastMAPeriod,0,FastMAType,FastMAPrice,0);
      SlowMAPrevious = iMA(NULL,TimeFrame,SlowMAPeriod,0,SlowMAType,SlowMAPrice,1);
      SlowMACurrent  = iMA(NULL,TimeFrame,SlowMAPeriod,0,SlowMAType,SlowMAPrice,0);
   }
   

//----------------------- CONDITION CHECK
   if(!ReverseCondition)
   {
//----------------------- BUY CONDITION   
      BuyCondition   = (FastMAPrevious<SlowMAPrevious &&
                        FastMACurrent>SlowMACurrent &&
                        (FastMACurrent-SlowMACurrent)>=MinCrossDistance*Point);      

//----------------------- SELL CONDITION   
      SellCondition  = (FastMAPrevious>SlowMAPrevious &&
                        FastMACurrent<SlowMACurrent &&
                        (SlowMACurrent-FastMACurrent)>=MinCrossDistance*Point);
                        
      if(EnableAlert)
      {
         if(BuyCondition && LastAlert!="UP")
         {
            subCrossAlert("UP");
            LastAlert = "UP";
         }            
         if(SellCondition && LastAlert!="DOWN")
         {
            subCrossAlert("DOWN");
            LastAlert ="DOWN";
         }
      }                        
   }
   else
   {
//----------------------- BUY CONDITION   
      SellCondition  = (FastMAPrevious<SlowMAPrevious &&
                        FastMACurrent>SlowMACurrent &&
                        (FastMACurrent-SlowMACurrent)>=MinCrossDistance*Point);      

//----------------------- SELL CONDITION   
      BuyCondition   = (FastMAPrevious>SlowMAPrevious &&
                        FastMACurrent<SlowMACurrent &&
                        (SlowMACurrent-FastMACurrent)>=MinCrossDistance*Point);

      if(EnableAlert)
      {
         if(SellCondition && LastAlert!="UP")
         {
            subCrossAlert("UP");
            LastAlert = "UP";
         }            
         if(BuyCondition && LastAlert!="DOWN")
         {
            subCrossAlert("DOWN");
            LastAlert ="DOWN";
         }
      }                        
   }                        

//+------------------------------------------------------------------+
//| ADDITIONAL FILTER                                                |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| THIRD MOVING AVERAGE                                             |
//+------------------------------------------------------------------+
   if(UseThirdMA)
   {
      ThirdMAValue = iMA(NULL,TimeFrame,ThirdMAPeriod,0,ThirdMAType,ThirdMAPrice,0);

      if(!UseCounterTrend)
      {      
         BuyCondition  = (BuyCondition  && Ask>ThirdMAValue);
         SellCondition = (SellCondition && Bid<ThirdMAValue);
      }
      else
      {
         CounterTrend = ((BuyCondition  && Ask<ThirdMAValue) ||
                        (SellCondition && Bid>ThirdMAValue));
      }
   }

//----------------------- EXIT CONDITION
//----------------------- not available



//----------------------- STOP AND REVERSE
if(StopAndReverse && subTotalTrade()>0)
   {
      if((LastTrade=="BUY" && SellCondition) || (LastTrade=="SELL" && BuyCondition))
      {
         subCloseOrder();
         if(IsTesting() && PrintControl) Print("STOP AND REVERSE !");
      }
   }


//----------------------- ENTRY
//----------------------- TOTAL ORDER BASE ON MAGICNUMBER AND SYMBOL
   total = subTotalTrade();

//----------------------- IF NUMBER TRADE LESS THAN MaxTrade
   if(total<MaxOpenTrade && (BuyCondition || SellCondition)) 
   {

//----------------------- ONE ENTRY PER BAR
      if(OneEntryPerBar)
      {
         if(CheckEntryTime==iTime(NULL,TimeFrame,0)) return(0); else CheckEntryTime = iTime(NULL,TimeFrame,0);
      }         

//----------------------- BUY CONDITION   
      if(BuyCondition)
      {
         if(!CounterTrend)
         {
            ticket = subOpenOrder(OP_BUY,StopLoss,TakeProfit);
         }
         else
         {
            ticket = subOpenOrder(OP_BUY,CTStopLoss,CTTakeProfit);
         }
         subCheckError(ticket,"BUY");
         LastTrade = "BUY";
         return(0);
      }

//----------------------- SELL CONDITION   
      if(SellCondition)
      {
         if(!CounterTrend)
         {
            ticket = subOpenOrder(OP_SELL,StopLoss,TakeProfit);
         }
         else
         {
            ticket = subOpenOrder(OP_SELL,CTStopLoss,CTTakeProfit);
         }
         subCheckError(ticket,"SELL");
         LastTrade = "SELL";
         return(0);
      }
      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 stoploss, int takeprofit)
{
   int
         ticket      = 0,
         err         = 0,
         c           = 0;
         
   double         
         aStopLoss   = 0,
         aTakeProfit = 0,
         bStopLoss   = 0,
         bTakeProfit = 0;

   if(stoploss!=0)
   {
      aStopLoss   = NormalizeDouble(Ask-stoploss*Point,4);
      bStopLoss   = NormalizeDouble(Bid+stoploss*Point,4);
   }
   
   if(takeprofit!=0)
   {
      aTakeProfit = NormalizeDouble(Ask+takeprofit*Point,4);
      bTakeProfit = NormalizeDouble(Bid-takeprofit*Point,4);
   }
   
   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);
}


//----------------------- CLOSE ORDER FUNCTION
void subCloseOrder()
{
   int
      cnt, 
      total = 0;

   total = OrdersTotal();
   for(cnt=total-1;cnt>=0;cnt--)
   {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

      if(OrderSymbol()==Symbol() &&
         OrderMagicNumber()==MagicNumber)
      {
         switch(OrderType())
         {
            case OP_BUY      :
               OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,Violet);
               break;
               
            case OP_SELL     :
               OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Violet);
               break;
               
            case OP_BUYLIMIT :
            case OP_BUYSTOP  :
            case OP_SELLLIMIT:
            case OP_SELLSTOP :
               OrderDelete(OrderTicket());
         }
      }
   }      
}


//----------------------- 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 + "Reverse Entry Condition=" + subBoolToStr(ReverseCondition) + NL;
   sComment = sComment + "Confirmed On Entry=" + subBoolToStr(ConfirmedOnEntry) + NL;
   sComment = sComment + "Stop And Reverse=" + subBoolToStr(StopAndReverse) + NL;
   sComment = sComment + "Pure SAR=" + subBoolToStr(PureSAR) + NL;
   sComment = sComment + sp;
   sComment = sComment + "Lots=" + DoubleToStr(Lots,2) + " | ";
   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");
}

//----------------------- ALERT ON MA CROSS
//----------------------- SOURCE : FIREDAVE
void subCrossAlert(string type)
{
   string AlertComment;
   
   if(type=="UP")   AlertComment = "Moving Average Cross UP !";
   if(type=="DOWN") AlertComment = "Moving Average Cross DOWN !";
   
   Alert(AlertComment);
   PlaySound(SoundFilename);
}


//----------------------- END FUNCTION



Sample





Analysis



Market Information Used:



Indicator Curves created:


Indicators Used:

Moving average indicator


Custom Indicators Used:

Order Management characteristics:
Checks for the total of open orders

It automatically opens orders when conditions are reached
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy

Other Features:

It issuies visual alerts to the screen
It plays sound alerts

BackTest : EURUSD on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.63 Total Net Profit:-149.00

BackTest : USDJPY on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.61 Total Net Profit:-87.38

BackTest : USDCHF on H1

From 2009-12-01 to 2010-01-01 Profit Factor:1.05 Total Net Profit:10.65

BackTest : USDCAD on H1

From 2009-12-01 to 2010-01-01 Profit Factor:2.51 Total Net Profit:414.89

BackTest : EURUSD on H1

From 2009-08-01 to 2009-10-01 Profit Factor:0.97 Total Net Profit:-22.00

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-02-27 Profit Factor:0.56 Total Net Profit:-613.00

BackTest : USDCAD on H1

From 2009-01-01 to 2010-01-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-03-01 to 2010-03-27 Profit Factor:1.37 Total Net Profit:153.00

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-04-16 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-04-01 to 2010-04-30 Profit Factor:0.77 Total Net Profit:-114.00

BackTest : EURUSD on H1

From 2010-05-01 to 2010-05-31 Profit Factor:0.90 Total Net Profit:-29.00

BackTest : EURUSD on H1

From 2010-06-01 to 2010-06-30 Profit Factor:1.13 Total Net Profit:62.00

Request Backtest for UniversalMACrossEA-mod


From : (yyyy/mm/dd) To: (yyyy/mm/dd)

Pair: Period: