HedgeEA_v5.9_v1





/*-----------------------------+
|			       |
| Shared by www.Aptrafx.com    |
|			       |
+------------------------------*/

//+------------------------------------------------------------------+
//|                                                      HedgeEA.mq4 |
//|                                 Copyright © 2006, ForexForums.org|
//+------------------------------------------------------------------+

//first v  used code from (EA's by Igorad,waltini) by kokas,cturner
//v5.0 latest greatest version by kokas
//v5.1 10-23-06 added bollinger filter, micro account by cturner
//v5.2 10-24-06 added logic to catch and fix 1 of the 2 trades not being placed due to error
//v5.3 10-24-06 correlation logic built in by Nicholishen  
//v5.4 10-24-06 bug fixes on open orders by cturner
//v5.5 10-30-06 added short/long option that was missing by cturner
//v5.6 10-30-06 added Autotrade, to stop entering automatic after exit, by kokas
//v5.7 31-10-06 MM routine corrected, by kokas (fully support of micro accounts)
//v5.8 05-11-06 AutoTakeProfit as a percentage of AccountBalance()
//v5.9 20-11-06 eMail Notification on close orders, UsePips including Swap, AutoProfit using Bollinger
//   
//   To do List:
//   
//   - AutoRatio Include Correlation
//   - Trailling for the hedge
//   


#property copyright "Copyright © 2006, ForexForums.org"
#property link      "http://www.forexforums.org/"

#include <stdlib.mqh>

//---- input parameters
extern string     eaname           = "[5.9]";                       // Expert Name and first part of comment line
extern int        Magic            = 1002;                          // Magic Number ( 0 - for All positions)
extern bool       Autotrade        = true;                          // Set to false to prevent an entry after an exit
extern string     Symbol1          = "GBPJPY";
extern bool       Symbol1isLong    = true;                          // Set to true to put long orders on the second pair
extern string     Symbol2          = "CHFJPY";
extern bool       Symbol2isLong    = false;                         // Set to true to put long orders on the second pair
extern string     Lotsizes         = "Set Ratio to 1 to use equal";
extern double     Lots             = 0.12;                           // Lots for first pair if MM is turned off
extern double     Ratio            = 1.8;                           // Ratio between the two pairs
extern bool       UseAutoRatio     = true;
extern string     Data             = " Input Data ";
extern bool       StopManageAcc    = false;                         // Stop of Manage Account switch(Close All Trades)
extern double     MaxLoss          = 0;                             // Maximum total loss in pips or USD 
extern string     Data2            = "Correlation Settings";
extern bool       UseCorrelation   = true;                         // Set to true if you want to use correlation as an entry signal
extern int        cPeriod          = 20;                            // If the correlation is used to check before put new Orders 
extern double     MinCorrelation   = 0.75; 
extern double     MaxCorrelation   = 1.0;
extern string     Data3            = "Bollinger Band Settings";
extern bool       UseBollinger     = false;                         // Set to true to use Bollinger bands as an entry signal
extern string     Bollinger_Symbol = "GBPCHF";
extern double     Bollinger_Period = 20;                           // Period must be in minutes
extern double     Bollinger_TF     = 60;
extern double     Bollinger_Dev    = 2;
extern string     Data4            = "SWAP Settings";               
extern bool       UseSwap          = true;                          // Select true if you want to use swap on profit calculation
extern string     Data5            = "Money Management";
extern bool       AccountIsMicro   = false;                          // Set true if you use a micro account
extern double     ProfitTarget     = 50;                            // Profit target in pips or USD  
extern bool       UsePips          = true;
extern bool       MoneyManagement  = false;
extern double     Risk             = 20;                            // Risk
extern bool       AutoProfit       = false;                          // When the price of Bolliner pair passes the Upper Bollinger close all trades
extern bool       EmailReport      = false;

string comment = "";
string eBody = "";
string eSubject = "";
string TradeSymbol ="";
int totalPips=0;
double  totalProfits=0;
double BandsLower = 0;
double BandsUpper = 0;
bool CloseSignal=false;
bool signal1=true;
bool signal2=true;
double valueswap = 0;
double Correlation;
double Bands;
int ticket1=0
   ,ticket2=0
   ,Symbol1SP
   ,Symbol2SP
   ,Order1=0
   ,Order2=0
   ,c1=0
   ,c2=0
   ,Symbol1OP
   ,Symbol2OP
   ,numords=0
   ;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 

   //____________________________________________________________________________________________         
   if(Symbol1isLong){Symbol1OP=OP_BUY;}
   else           {Symbol1OP=OP_SELL;}
   
   if(Symbol2isLong){Symbol2OP=OP_BUY;}
   else           {Symbol2OP=OP_SELL;}
   //____________________________________________________________________________________________ 
   //CloseSignal=false;
//----
   return(0);
  }

// ---- Scan Open Trades
int ScanOpenTrades()
{   
           
   Order1=0;Order2=0;  
   int total = OrdersTotal();
   int numords = 0;
   for(int cnt=0; cnt<=total-1; cnt++)
   {
    OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
    //if(OrderMagicNumber()==Magic)
    if(Magic > 0) if(OrderMagicNumber() == Magic) numords++;
    {
    if(OrderType()==Symbol1OP && OrderMagicNumber() == Magic && OrderSymbol()==Symbol1)Order1  += 1;
    if(OrderType()==Symbol2OP && OrderMagicNumber() == Magic && OrderSymbol()==Symbol2)Order2  += 1;
    }    
   }
//   int total = OrdersTotal();
//int numords = 0;
    
  // for(int cnt=0; cnt<=total-1; cnt++) 
   //{        
//   OrderSelect(cnt, SELECT_BY_POS);            
  //    if(OrderType()<=OP_SELL)
    //  {
      //if(Magic > 0) if(OrderMagicNumber() == Magic) numords++;
//      if(Magic == 0) numords++;
  //    }
//   }   
   return(numords);
}

//+--------- --------- --------- --------- --------- --------- ----+
//+ Calculate cost in USD of 1pip of given symbol
//+--------- --------- --------- --------- --------- --------- ----+
double PipCost (string TradeSymbol) {
double Base, Cost;
string TS_13, TS_46, TS_4L;

TS_13 = StringSubstr (TradeSymbol, 0, 3);
TS_46 = StringSubstr (TradeSymbol, 3, 3);
TS_4L = StringSubstr (TradeSymbol, 3, StringLen(TradeSymbol)-3);

Base = MarketInfo (TradeSymbol, MODE_LOTSIZE) * MarketInfo (TradeSymbol, 
MODE_POINT);
if ( TS_46 == "USD" )
Cost = Base;
else if ( TS_13 == "USD" )
Cost = Base / MarketInfo (TradeSymbol, MODE_BID);
else if ( PairExists ("USD"+TS_4L) )
Cost = Base / MarketInfo ("USD"+TS_4L, MODE_BID);
else
Cost = Base * MarketInfo (TS_46+"USD" , MODE_BID);

return(Cost) ;
}

//+--------- --------- --------- --------- --------- --------- ----+
//+ Returns true if given symbol exists
//+--------- --------- --------- --------- --------- --------- ----+
bool PairExists (string TradeSymbol) {
return ( MarketInfo (TradeSymbol, MODE_LOTSIZE) > 0 );
}


// Generate Comment on OrderSend 
string GenerateComment(string eaname, int Magic)
{
   return (StringConcatenate(eaname, "-", Magic));
}

// Closing of Open Orders      
void OpenOrdClose()
{
    int total=OrdersTotal();
    for (int cnt=0;cnt<total;cnt++)
    { 
    OrderSelect(cnt, SELECT_BY_POS);   
    int mode=OrderType();
    bool res = false; 
    bool condition = false;
    if ( Magic>0 && OrderMagicNumber()==Magic ) condition = true;
    else if ( Magic==0 ) condition = true;
      if (condition && ( mode==OP_BUY || mode==OP_SELL ))
      { 
         if (EmailReport) SendMail(eSubject,eBody);
// - BUY Orders         
         if(mode==OP_BUY)
         {  
         res = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),3,Yellow);
            if( !res )
            {
            Print(" BUY: OrderClose failed with error #",GetLastError());
            Print(" Ticket=",OrderTicket());
            Sleep(3000);
            }
         break;
         }
         else     
// - SELL Orders          
         if( mode == OP_SELL)
         {
         res = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),3,White);
                
            if( !res )
            {
            Print(" SELL: OrderClose failed with error #",GetLastError());
            Print(" Ticket=",OrderTicket());
            Sleep(3000);
            }
         break;    
         }  
      }                  
   }
}

void TotalProfit()
{
   int total=OrdersTotal();
   totalPips = 0;
   totalProfits = 0;
   for (int cnt=0;cnt<total;cnt++)
   { 
   OrderSelect(cnt, SELECT_BY_POS);   
   int mode=OrderType();
   bool condition = false;
   if ( Magic>0 && OrderMagicNumber()==Magic ) condition = true;
   else if ( Magic==0 ) condition = true;   
      if (condition)
      {               
         switch (mode)
         {
         case OP_BUY:
            totalPips += MathRound((MarketInfo(OrderSymbol(),MODE_BID)-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT));
            //totalPips += MathRound((Bid-OrderOpenPrice())/Point);
            totalProfits += OrderProfit();
            break;
            
         case OP_SELL:
            totalPips += MathRound((OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_POINT));
            //totalPips += MathRound((OrderOpenPrice()-Ask)/Point);
            totalProfits += OrderProfit();
            break;
         }
      }            
	}
}

void SwapProfit()
{
   int total=OrdersTotal();
   valueswap = 0;
   for (int cnt=0;cnt<total;cnt++)
   { 
   OrderSelect(cnt, SELECT_BY_POS);   
   int mode=OrderType();
   bool condition = false;
   if ( Magic>0 && OrderMagicNumber()==Magic ) condition = true;
   else if ( Magic==0 ) condition = true;   
      if (condition)
      {      
      if (UsePips){
      valueswap = valueswap + OrderSwap()/PipCost(OrderSymbol());
      } else {
      valueswap = valueswap + OrderSwap();      
      }   
      }            
	}
}

void ChartComment()
{
   string sComment   = "";
   string sp         = "****************************\n";
   string NL         = "\n";

   sComment = sp;
   sComment = sComment + "Open Positions      = " + ScanOpenTrades() + NL;
   sComment = sComment + "Current Ratio       = " + DoubleToStr(Ratio,2) + NL;
   
   if (UsePips) {
     sComment = sComment + "Current Profit(Pip)= " + totalPips + NL;
   } else {
     sComment = sComment + "Current Profit(USD) = " + DoubleToStr(totalProfits,2) + NL + NL; 
   }
   if(UseCorrelation){sComment = sComment + "Correlation              = " + DoubleToStr(Correlation,3) + NL + NL;}
   if(UseBollinger){sComment = sComment + "Bollinger Middle           = " + DoubleToStr(Bands,4) + NL;} 
   if(UseBollinger){sComment = sComment + "Bollinger Pair Price       = " + DoubleToStr(MarketInfo(Bollinger_Symbol,MODE_ASK),4) + NL + NL;}
   if (UsePips) {
     sComment = sComment + "SWAP Value (Pip)   = " + DoubleToStr(valueswap,2) + NL;
   } else {
     sComment = sComment + "SWAP Value (USD)   = " + DoubleToStr(valueswap,2) + NL;
   }
   if(UseSwap){
          sComment = sComment + "SWAP Enabled" + NL;
       } else {
          sComment = sComment + "SWAP Disabled" + NL;
       }
   if (UsePips) {
     sComment = NL + sComment + "Net Value (Pip)      = " + DoubleToStr(totalPips+valueswap,2) + NL;
   } else {
     sComment = NL + sComment + "Net Value (USD)      = " + DoubleToStr(totalProfits+valueswap,2) + NL;
   }
   //sComment = sComment + "Account Leverage 1:" + AccountLeverage() + NL;
   sComment = sComment + NL + sp;

   eSubject = "Hedge Profit:" + DoubleToStr(totalProfits+valueswap,2) ;
   eBody    = "HedgeEA Report GBPJPY/CHFJPY" + NL + sComment + "AccountBalance =" + AccountBalance( ) + NL + "AccountNumber = " +  AccountNumber( ) + NL + "Profit  = " +  AccountProfit( ) + NL
   + "Balance = " +  AccountBalance( ) + NL  + "Equity  = " +  AccountEquity( ) + NL
   + "FreeMargin  = " +  AccountFreeMargin( ) + NL  + "FreeMargin  = " +  AccountLeverage( )  + NL;
   Comment(sComment);
}	  

double CorrelationIND(string Symbol1,string Symbol2,int CorrelationShift=0){
   double Correlation[],DiffBuffer1[],DiffBuffer2[],PowDiff1[],PowDiff2[];
   ArrayResize(Correlation,cPeriod*2);ArrayResize(DiffBuffer1,cPeriod*2);
   ArrayResize(DiffBuffer2,cPeriod*2);ArrayResize(PowDiff1,cPeriod*2);ArrayResize(PowDiff2,cPeriod*2);
   for( int shift=cPeriod+1; shift>=0; shift--){
      DiffBuffer1[shift]=iClose(Symbol1,0,shift)-iMA(Symbol1,0,cPeriod,0,MODE_SMA,PRICE_CLOSE,shift);
      DiffBuffer2[shift]=iClose(Symbol2,0,shift)-iMA(Symbol2,0,cPeriod,0,MODE_SMA,PRICE_CLOSE,shift);
      PowDiff1[shift]=MathPow(DiffBuffer1[shift],2);
      PowDiff2[shift]=MathPow(DiffBuffer2[shift],2);
      double u=0,l=0,s=0;
      for( int i = cPeriod-1 ;i >= 0 ;i--){
         u += DiffBuffer1[shift+i]*DiffBuffer2[shift+i];
         l += PowDiff1[shift+i];
         s += PowDiff2[shift+i];
      }
      if(l*s >0)Correlation[shift]=u/MathSqrt(l*s);
   }   
   return(Correlation[CorrelationShift]);
   return(-1); 
}

// added MM v3
double LotSize()
{
     double lotMM = MathCeil(AccountFreeMargin() *  Risk / 1000) / AccountLeverage() / 2;
	  
	  if(AccountIsMicro==false)                          //normal account
	  {
	     if(lotMM < 0.1)                    lotMM = 0.1;
	     if((lotMM >= 0.1) && (lotMM < 0.2)) lotMM = 0.2;
	     if((lotMM >= 0.2) && (lotMM < 0.3)) lotMM = 0.3;
	     if((lotMM >= 0.3) && (lotMM < 0.4)) lotMM = 0.4;
	     if((lotMM >= 0.4) && (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 = 0.01; 
	     if((lotMM >= 0.01) && (lotMM < 0.02)) lotMM = 0.02;
	     if((lotMM >= 0.02) && (lotMM < 0.03)) lotMM = 0.03;
	     if((lotMM >= 0.03) && (lotMM < 0.04)) lotMM = 0.04;
	     if((lotMM >= 0.05) && (lotMM < 0.06)) lotMM = 0.05; 
	     if((lotMM >= 0.06) && (lotMM < 0.07)) lotMM = 0.06; 
	     if((lotMM >= 0.07) && (lotMM < 0.08)) lotMM = 0.08; 
	     if((lotMM >= 0.08) && (lotMM < 0.09)) lotMM = 0.09;
	     if((lotMM >= 0.09) && (lotMM < 0.10)) lotMM = 0.1;  
	     if((lotMM >= 0.1) && (lotMM < 0.2)) lotMM = 0.2;
	     if((lotMM >= 0.2) && (lotMM < 0.3)) lotMM = 0.3;
	     if((lotMM >= 0.3) && (lotMM < 0.4)) lotMM = 0.4;
	     if((lotMM >= 0.4) && (lotMM < 1))   lotMM = 0.5; 	   
	     if(lotMM >= 1.0)                  lotMM = MathCeil(lotMM);
	     if(lotMM >= 100)                  lotMM = 100;
	  }
  
//	  Print(lotMM);
	  
	  return (lotMM);
}

 
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
   
{
  
  Correlation= CorrelationIND(Symbol1,Symbol2,0);

//added Bollinger Filter

//  Bands=iCustom(Bollinger_Symbol,Bollinger_Period,"Bands",20,0,2,0,0,0);                // Old Bollinger
  
    BandsLower = iBands(Bollinger_Symbol,Bollinger_TF,Bollinger_Period,Bollinger_Dev,0,0,2,0);          // Lower  Bollinger
    BandsUpper = iBands(Bollinger_Symbol,Bollinger_TF,Bollinger_Period,Bollinger_Dev,0,0,1,0);          // Upper  Bollinger
    Bands = (BandsLower + BandsUpper) / 2;                                                              // Middle Bollinger

//  if(ScanOpenTrades()==0) CloseSignal=false; Order1=0; Order2=0; 
//  if(ScanOpenTrades()==2) Order1=1; Order2=1;
   
     TotalProfit();
     SwapProfit();

if (UseAutoRatio) {

     Ratio = PipCost(Symbol1) / PipCost(Symbol2);
     
     }


   ChartComment();

   if (UseSwap) {
     if (UsePips) {
         totalProfits = totalPips + valueswap;
     } else {
         totalProfits = totalProfits + valueswap;
     }
     }

   if (AutoProfit) if (totalProfits > 0 && MarketInfo(Bollinger_Symbol,MODE_ASK) > BandsUpper) CloseSignal = true;
      
    

   if (!StopManageAcc)
   {
      if(ScanOpenTrades() > 0 && !CloseSignal && (ProfitTarget>0 || MaxLoss>0))
      {
        if(ProfitTarget > 0 && totalProfits>=ProfitTarget) CloseSignal=true;
        if(MaxLoss > 0 && totalProfits <= -MaxLoss) CloseSignal=true;
 
      }   
   }
   else 
   { if (ScanOpenTrades() > 0) CloseSignal=true;}    
   
   if( CloseSignal ) OpenOrdClose();

// Prepare Comment line for the trades

     if(Symbol1isLong) {
     comment = Symbol1 + "_L/"; 
     } else {
     comment = Symbol1 + "_S/";
     }
     if(Symbol2isLong) {
     comment = comment + "L_" + Symbol2;
     } else {
     comment = comment +"S_" + Symbol2;
     }
     
     comment = comment + " " + GenerateComment(eaname, Magic);
     
// Micro or Mini

double AccountSize;

     if(AccountIsMicro)  {
     
     AccountSize=2;
     
     } else {
     
     AccountSize=1;
     
     }        

// added MM statement


double OrderLots1,OrderLots2;


     if(MoneyManagement) {
     
     OrderLots1 = NormalizeDouble(LotSize(),AccountSize); //Adjust the lot size
     OrderLots2 = NormalizeDouble(LotSize() * Ratio,AccountSize); // change 2 to 1 for mini account
     
     } else {
     
     OrderLots1 = Lots;
     OrderLots2 = NormalizeDouble(Lots * Ratio,2); //change 2 to 1 for mini account
   
     }
      
     
// Added signal1 that will store correlation logic if used 
     
     if(UseCorrelation) {
        if(Correlation < MaxCorrelation && Correlation > MinCorrelation) {
            signal1 = true;
        } else {
            signal1 = false;
        }
     }
      
     
// Added signal2 that will store bollinger logic if used 
     
     if(UseBollinger) {
        if(MarketInfo(Bollinger_Symbol,MODE_ASK) < Bands) {
            signal2 = true;
        } else {
            signal2 = false;
        }
     }     
     
     
// Long/Short   
     
     if((Order1==0 || Order2==0) && Symbol1isLong && !Symbol2isLong && !StopManageAcc && signal1 && signal2 && Autotrade){
    
      CloseSignal=false;
           
      if (Order1==0) {
      OrderSend(Symbol1,OP_BUY,OrderLots1,MarketInfo(Symbol1,MODE_ASK),3,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order1=1;}
      }
      if (Order2==0) {
      OrderSend(Symbol2,OP_SELL,OrderLots2,MarketInfo(Symbol2,MODE_BID),3,0,0,comment,Magic,0,Red);
      if (GetLastError()==0) {Order2=1;}
      }
      }
      
// Short/Long   
     
     if((Order1==0 || Order2==0) && !Symbol1isLong && Symbol2isLong && !StopManageAcc && signal1 && signal2 && Autotrade){
    
      CloseSignal=false;
      
      if (Order1==0) {
      OrderSend(Symbol1,OP_SELL,OrderLots1,MarketInfo(Symbol1,MODE_BID),3,0,0,comment,Magic,0,Red);
      if (GetLastError()==0) {Order1=1;}
      }
      if (Order2==0) {
      OrderSend(Symbol2,OP_BUY,OrderLots2,MarketInfo(Symbol2,MODE_ASK),3,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order2=1;}
      }
      }
  

// Short/Short


     if((Order1==0 || Order2==0) && !Symbol1isLong && !Symbol2isLong && !StopManageAcc && signal1 && signal2 && Autotrade){
    
      CloseSignal=false;
      
      if (Order1==0) {
      OrderSend(Symbol1,OP_SELL,OrderLots1,MarketInfo(Symbol1,MODE_BID),3,0,0,comment,Magic,0,Red);
      if (GetLastError()==0) {Order1=1;}
      }
      if (Order2==0) {
      OrderSend(Symbol2,OP_SELL,OrderLots2,MarketInfo(Symbol2,MODE_BID),3,0,0,comment,Magic,0,Red);
      if (GetLastError()==0) {Order2=1;}
      }
      }
      
      
      
// Long/Long

     if((Order1==0 || Order2==0) && Symbol1isLong && Symbol2isLong && !StopManageAcc && signal1  && signal2 && Autotrade){
    
      CloseSignal=false;
      
      if (Order1==0) {
      OrderSend(Symbol1,OP_BUY,OrderLots1,MarketInfo(Symbol1,MODE_ASK),3,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order1=1;}
      }
      if (Order2==0) {
      OrderSend(Symbol2,OP_BUY,OrderLots2,MarketInfo(Symbol2,MODE_ASK),3,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order2=1;}
      }
      }
              
 return(0);
}//int start
//+------------------------------------------------------------------+







Sample





Analysis



Market Information Used:

Series array that contains close prices for each bar


Indicator Curves created:


Indicators Used:

Moving average indicator
Bollinger bands indicator


Custom Indicators Used:

Order Management characteristics:
Checks for the total of open orders

It Closes Orders by itself
It automatically opens orders when conditions are reached

Other Features:

It sends emails