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

//v1.1 solve Closing Problem: bodshyipmonitor.

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

#include <stdlib.mqh>

//---- input parameters
extern string     eaname           = "MH-V1.3";                       // Expert Name and first part of comment line
extern int        Magic            = 111140;                          // Magic Number ( 0 - for All positions)
extern bool       Autotrade        = true;                          // Set to false to prevent an entry after an exit

extern string     Symbol1          = "USDCHF";
extern bool       Symbol1isLong    = true;                          // Set to true to put long orders on the second pair
extern double     Ratio1           = 1;
extern string     Symbol2          = "USDJPY";
extern bool       Symbol2isLong    = true;                          // Set to true to put long orders on the second pair
extern double     Ratio2           = 1;
extern string     Symbol3          = "EURUSD";
extern bool       Symbol3isLong    = true;                          // Set to true to put long orders on the second pair
extern double     Ratio3           = 1;
extern string     Symbol4          = "GBPUSD";
extern bool       Symbol4isLong    = true;                          // Set to true to put long orders on the second pair
extern double     Ratio4           = 1;
extern double     Slippage         = 3;    
extern string     Lotsizes         = "Set Ratio to 1 to use equal";
extern double     Lots             = 1;                           // Lots for first pair if MM is turned off
extern bool       UseAutoRatio     = true;
extern double     SMA_Value_for_Range = 200;
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.8; 
// extern double     MaxCorrelation   = 1.0;

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";
       bool       AccountIsMicro   = true;                          // Set true if you use a micro account
extern double     ProfitTarget     = 50;                            // Profit target in pips or U
       bool       UsePips          = false;
extern bool       MoneyManagement  = true;
extern double     Risk             = 20;                            // Risk
extern bool       AutoProfit       = true;                         // When the price of Bolliner pair passes the Upper Bollinger close all trades
extern double     AutoProfitRatio  = 1; 
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;
double OrderLots1,OrderLots2,OrderLots3,OrderLots4;
double AccountSize;
double Total_Lots;
int ticket1=0
   ,ticket2=0
   ,Symbol1SP
   ,Symbol2SP
   ,Order1=0
   ,Order2=0
   ,Order3=0
   ,Order4=0
   ,c1=0
   ,c2=0
   ,Symbol1OP
   ,Symbol2OP
   ,Symbol3OP
   ,Symbol4OP
   ,Symbol1Mode
   ,Symbol2Mode
   ,Symbol3Mode
   ,Symbol4Mode
   ,numords=0
   ;
string USD = "USD"; // Added so that PipCost could handle InterbankFx Mini accounts

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

         
   if(Symbol1isLong){
      Symbol1OP=OP_BUY;
      Symbol1Mode=MODE_ASK;
      } else {
      Symbol1OP=OP_SELL;
      Symbol1Mode=MODE_BID;
      }
   
   if(Symbol2isLong){
      Symbol2OP=OP_BUY;
      Symbol2Mode=MODE_ASK;
      } else {
      Symbol2OP=OP_SELL;
      Symbol2Mode=MODE_BID;
      }
      
   if(Symbol3isLong){
      Symbol3OP=OP_BUY;
      Symbol3Mode=MODE_ASK;
      } else {
      Symbol3OP=OP_SELL;
      Symbol3Mode=MODE_BID;
      }
      
   if(Symbol4isLong){
      Symbol4OP=OP_BUY;
      Symbol4Mode=MODE_ASK;
      } else {
      Symbol4OP=OP_SELL;
      Symbol4Mode=MODE_BID;
      }      
  
   if (StringLen(Symbol())== 7 )
    {
      Symbol1 = Symbol1 + "m";
      Symbol2 = Symbol2 + "m";
      Symbol3 = Symbol3 + "m";
      Symbol4 = Symbol4 + "m";
      USD = USD + "m";
    }
   
   if (MarketInfo(Symbol(),MODE_LOTSTEP) == 0.01)
   {
     AccountIsMicro = true;
   }
   else
   {
     AccountIsMicro = false;
   }
 
//CloseSignal=false;
//----
   return(0);
  }

// ---- Scan Open Trades
int ScanOpenTrades()
{   
           
   Order1=0;Order2=0;Order3=0;Order4=0;  
   int total = OrdersTotal();
   int numords = 0;
   for(int cnt=0; cnt<=total-1; cnt++)
   {
    OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
    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;
    if(OrderType()==Symbol3OP && OrderMagicNumber() == Magic && OrderSymbol()==Symbol3)Order3  += 1;
    if(OrderType()==Symbol4OP && OrderMagicNumber() == Magic && OrderSymbol()==Symbol4)Order4  += 1;
    
    }    
   }

   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));
            totalProfits += OrderProfit();
            break;
            
         case OP_SELL:
            totalPips += MathRound((OrderOpenPrice()-MarketInfo(OrderSymbol(),MODE_ASK))/MarketInfo(OrderSymbol(),MODE_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;
  //Add in by bodshyipmonitor@forex-tsd to show the lots. Will only show when there are no trades open. :)
  if (OrdersTotal()<1){
      sComment = sComment + "Total Lots :     = " + Total_Lots + NL;
      sComment = sComment + Symbol1+ " Lots :       = " + DoubleToStr(OrderLots1,AccountSize) + NL;
      sComment = sComment + Symbol2+ " Lots :       = " + DoubleToStr(OrderLots2,AccountSize) + NL;
      sComment = sComment + Symbol3+ " Lots :       = " + DoubleToStr(OrderLots3,AccountSize) + NL;
      sComment = sComment + Symbol4+ " Lots :       = " + DoubleToStr(OrderLots4,AccountSize) + NL;
      sComment = sComment + NL;
  }
   
   if (UsePips) {
     sComment = sComment + "Current Profit(Pip)= " + totalPips + NL;
   } else {
     sComment = sComment + "Current Profit(USD) = " + DoubleToStr(totalProfits,2) + NL + NL; 
   }
      sComment = NL + sComment + "Profit Target (USD)    = " + DoubleToStr(ProfitTarget,0) + NL;

   if(UseSwap){
   
           if (UsePips) {
                 sComment = sComment + "SWAP Value (Pip)   = " + DoubleToStr(valueswap,2) + NL;
           } else {
                 sComment = sComment + "SWAP Value (USD)   = " + DoubleToStr(valueswap,2) + 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 + NL + sp;

   eSubject = "MultiHedge Profit:" + DoubleToStr(totalProfits+valueswap,2);
   eBody    = "MultiHedgeEA Report" + NL + sComment;
   
   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); 
}


//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
   
{

// while(true){
//  Sleep(100);
//  RefreshRates();

  
   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) {

    double Symbol1_Range= (iMA(Symbol1,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_HIGH,0)-iMA(Symbol1,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_LOW,0))/MarketInfo(Symbol1,MODE_POINT);
    double Symbol2_Range= (iMA(Symbol2,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_HIGH,0)-iMA(Symbol2,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_LOW,0))/MarketInfo(Symbol2,MODE_POINT);
    double Symbol3_Range= (iMA(Symbol3,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_HIGH,0)-iMA(Symbol3,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_LOW,0))/MarketInfo(Symbol3,MODE_POINT);
    double Symbol4_Range= (iMA(Symbol4,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_HIGH,0)-iMA(Symbol4,0,SMA_Value_for_Range,0,MODE_SMA,PRICE_LOW,0))/MarketInfo(Symbol4,MODE_POINT);
         
    double TotalRange = Symbol1_Range + Symbol2_Range + Symbol3_Range + Symbol4_Range;
     
     Ratio1 = (1 / PipCost(Symbol1))* (Symbol1_Range / TotalRange) / MarketInfo(Symbol1,MODE_LOTSIZE); 
     Ratio2 = (1 / PipCost(Symbol2))* (Symbol2_Range / TotalRange) / MarketInfo(Symbol2,MODE_LOTSIZE); 
     Ratio3 = (1 / PipCost(Symbol3))* (Symbol3_Range / TotalRange) / MarketInfo(Symbol3,MODE_LOTSIZE); 
     Ratio4 = (1 / PipCost(Symbol4))* (Symbol4_Range / TotalRange) / MarketInfo(Symbol4,MODE_LOTSIZE); 
     
     }

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

   if (AutoProfit) ProfitTarget = NormalizeDouble(((OrderLots1 * PipCost(Symbol1) + OrderLots2 * PipCost(Symbol2) +OrderLots3*PipCost(Symbol3) + OrderLots4*PipCost(Symbol4) )/4) * Risk / AutoProfitRatio,0);
      
    

   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();
     
     
     if (Order1==0 && Order2==0 && Order3==0 && Order4==0) CloseSignal=false;

     comment = GenerateComment(eaname, Magic);
     
     if(AccountIsMicro)  {AccountSize=2;} else {AccountSize=1;}        

     if(MoneyManagement) {
      
       
       Total_Lots = AccountFreeMargin()*Risk*0.01 *AccountLeverage();
              
       // Print(Total_Lots);
       
       OrderLots1 = NormalizeDouble(Total_Lots * Ratio1,AccountSize);
       OrderLots2 = NormalizeDouble(Total_Lots * Ratio2,AccountSize);
       OrderLots3 = NormalizeDouble(Total_Lots * Ratio3,AccountSize);
       OrderLots4 = NormalizeDouble(Total_Lots * Ratio4,AccountSize);
           
     } else {
     
       OrderLots1 = NormalizeDouble(Lots * Ratio1,AccountSize);
       OrderLots2 = NormalizeDouble(Lots * Ratio2,AccountSize);
       OrderLots3 = NormalizeDouble(Lots * Ratio3,AccountSize);
       OrderLots4 = NormalizeDouble(Lots * Ratio4,AccountSize);
     
     }
     
     //Print(OrderLots1,"  ",OrderLots2,"  ",OrderLots3,"  ",OrderLots4);
     
     ChartComment();
     signal1 = true;
     signal2 = true;
     
     // * * * * * * * * * *  Placing Orders * * * * * * * * * * 
     
     if(!StopManageAcc && signal1 && signal2 && Autotrade && !CloseSignal){
    
      CloseSignal=false;
      
      // Order1
      
      if (Order1==0) {
      OrderSend(Symbol1,Symbol1OP,OrderLots1,MarketInfo(Symbol1,Symbol1Mode),Slippage,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order1=1;}
      }
            
      // Order2
      
      if (Order2==0) {
      OrderSend(Symbol2,Symbol2OP,OrderLots2,MarketInfo(Symbol2,Symbol2Mode),Slippage,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order2=1;}
      }
            
      // Order3
      
      if (Order3==0) {
      OrderSend(Symbol3,Symbol3OP,OrderLots3,MarketInfo(Symbol3,Symbol3Mode),Slippage,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order3=1;}
      }
            
      // Order4
      
      if (Order4==0) {
      OrderSend(Symbol4,Symbol4OP,OrderLots4,MarketInfo(Symbol4,Symbol4Mode),Slippage,0,0,comment,Magic,0,Blue);
      if (GetLastError()==0) {Order4=1;}
      }
      
      }
// } //Final Cycle
} // EA Close