MQL4 - automated forex trading   /  

Articles

ODL Securities

Articles  Trading Systems  What about Hedging Daily? To post a new article, please log in or register


This article is about
MetaTrader 4
Download MT 4 - 3.5 Mb

Mobile trading!
Buy a license and be mobile in your trading!

What about Hedging Daily?

Introduction

I am giving away an idea of hedging the GBP/JPY & EUR/JPY daily. Yes Daily. This idea popped up while I was trying to generate a trading system that plays on the daily scheme, opening the trade only once a day, collecting the profit only around $100 each day, and of course, all the things do automatically. At the first time, I only tried to trade with the TD-Sequential System, owned by Tom Demark. I tried trading it daily, actually it dose a good system, but somehow give me an unacceptable loss, then the idea of hedging the two correlated pairs came out. "Why don't hedge ?, then you will lose less than today or maybe you can gain, sounds grate ! ". Then i tested it manually with 1 month past history, and found a good profit maker sign. So...no need to wait for anything, just make it automatically trade for you and test it live for a couple of months or longer. Now let's start making it comes true.

Concept of Daily Hedge

Before we start the coding process, let's make a plan together. Including...
-> What will we use for signaling the daily trading trend? : This will give us the estimate today's direction of GBP/JPY and EUR/JPY (these two pairs are always 90% correlated) . In this case i still choose the TD-Sequential System, an easy TD-Sequential I've found in a forum, to give me the daily signal.

-> Which hedging pairs to hedge? : Just select your favorite pairs. Mine are GBP/JPY and EUR/JPY, with the reason above.

-> Which pair will be the base pair? & Which one will be the hedge pair? : This will make it easier to code the EA. I decided to mark the EUR/JPY as my base pair and hedge GBP/JPY. ("Why Base & Hedge?", that's because of the system is hedge by the daily trend.) For example, today the TD-Sequential signal out the UP trend of EUR/JPY, then I will BUY EUR/JPY and hedge by selling GBP/JPY. Or maybe you can make sure by mark the UP day only when both EUR/JPY and GBP/JPY are showing the TD-Sequential UP, then buy the base pair & sell the hedge pair.

-> What is the ... correlation ? : Of course, we need this factor, and you all know, it is an important factor of hedging system. In this case, I will only allow to hedge when the correlation of those two pairs is 0.9 or higher only. YES, please don't be astonished. Yes 0.9+ "WHY ?", I know every hedge professor suggests you to hedge when the correlation is low, but that is for a very very and very long - term . To me and my daily hedging system, hedging at high correlation is better. Please NOTE that, this is for my daily hedging system only. Because we need them to go the same way always, especially for today (our trading day), then we can get one positive and one negative always and then only collect the profit when they swing, even they were never swing in the profitable way, you still loss less than one way in negative trade.

O.K. Now let's start coding.

Daily Hedge Expert Advisor

In this part, I will separate it into 5 major parts, that is .

  1. The Input Parameters
  2. The Daily Trend Signal Function
  3. The Trade Function
  4. The Trading Process
  5. Showing The Hedging Status Function

And now let's begin with the input parameters.

1. Input Parameters

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~External Input Parameters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
extern bool BlockOpening=false;
extern bool ShowStatus=true;
 
extern string Auto_Lot_______________________="_______"; // Always Calculate The Lot Size Automatically
extern int PercentMaxRisk=25; // With Max Risk Of 25% by default
 
extern string How_Much_You_Xpect?____________ ="_______"; // The Getting Profit Part
extern double Daily_Percent_ROI=7.98; // How many daily %ROI you wish.
extern double AcceptableLoss_ROI=3.08; // daily Acceptable loss calculated in ROI scheme.
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Internal Input Parameters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
string BaseSymbol="GBPJPY";
string H_Symbol="EURJPY";
int CorPeriod_1=3; // just for checking that short-term
int CorPeriod_2=5; //& long-term Correlation are the same concederation level
bool AutoLot=true;
double H_B_LotsRatio=1.50; // always hedge those 2 pairs by 1:1.5 ratio
int MMBase=3;
 
string ExpectCorrelation______________= "______"; // the concederation level of their correlation.
double Between=1.05;
double And=0.9;
 
string TDSequential="______"; // my easy TD-Sequential signal
int cntFrom=1; // only refer the today signal by yesterday candle
int cntTo=3; // count back to the 3rd candle
 
bool ClearTradeDaily?=true; // always clear the yesterday hedge
 
string MISC___________________________= "______";
int MagicNo=317;
bool PlayAudio=false;
 
int BSP
,HSP
,gsp
,BOP=-1
,HOP=-1
,up=0
,Hcnt=0
,u=0
,d=0
,day=0
,sent=0
,cntm
,curm
;
double Lot
,BaseOpen
,HOpen
,BaseLots
,HLots
,BUM //Base Used Margin
,GBUM //Get BUM
,HUM //Hedge Used Margin
,GHUM //Get HUM
,TUM //Total Used Margin
,BPt
,HPt
,midpt3;
bool SResult=false,BResult=false;
bool allmeetcor=false,BlockOpen=false,cleared=false;
string candletxt,tdstxt="";
 
double Min_Lot;
double Max_Lot;
double lot_step;
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   BSP=MarketInfo(BaseSymbol,MODE_SPREAD);
   HSP=MarketInfo(H_Symbol,MODE_SPREAD);
 
   BPt=MarketInfo(BaseSymbol,MODE_POINT);
   HPt=MarketInfo(H_Symbol,MODE_POINT);
 
   lot_step=MarketInfo(BaseSymbol, MODE_LOTSTEP);
 
   Min_Lot=MarketInfo(BaseSymbol, MODE_MINLOT);
   if(Min_Lot<=0)Min_Lot=1*lot_step;
 
   Max_Lot=MarketInfo(BaseSymbol, MODE_MAXLOT);
 
   if(BSP>HSP)gsp=HSP;
   else gsp=BSP;
 
//----
   return(0);
  }

2. Daily Trend Signal Function


//+------------------------------------------------------------------+
//|TOM DEMARK SEQUENTIAL : Return +Value for UP & -Value for DOWN Sig|
//+------------------------------------------------------------------+
int DeMark(string sym,int s)
  {
   int i,pos=36,num=0,num1=0,Rnum,w,m;
 
   for(i=pos; i>=0; i--)
     {
      double midPt3=(iClose(sym,0,i+s+cntTo)+iOpen(sym,0,i+s+cntTo))/2;
 
      if(iClose(sym,0,i+s+cntFrom)<midPt3)
        { w++;m=0;num++; num1=0;
         Rnum=-1*num;
        }
      else
         if(iClose(sym,0,i+cntFrom)>midPt3)
           { m++;w=0;num1++;num=0;
            Rnum=num1;
           }
         else {num1=0;num =0;Rnum=0;}
 
     }
 
   return(Rnum);
  }
//+------------------------------------------------------------------+
//| CORRELATION : Calculate the correlation of the 2 pairs           |
//+------------------------------------------------------------------+
double symboldif(string symbol,int shift,int CorPeriod)
  {
   return(iClose(symbol,1440,shift)-iMA(symbol,1440,CorPeriod,0,MODE_SMA,PRICE_CLOSE,shift));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double powdif(double val)
  {
   return(MathPow(val,2));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double u(double val1,double val2)
  {
   return((val1*val2));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double Cor(string base,string hedge,int CorPeriod)
  { double u1=0,l1=0,s1=0;
   for(int i=CorPeriod-1 ;i >=0 ;i--)
     {
      u1 +=u(symboldif(base,i,CorPeriod),symboldif(hedge,i,CorPeriod));
      l1 +=powdif(symboldif(base,i,CorPeriod));
      s1 +=powdif(symboldif(hedge,i,CorPeriod));
     }
   if(l1*s1 >0) return(u1/MathSqrt(l1*s1));
  }



3. Trade Function


//+------------------------------------------------------------------+
//|  TOTAL PROFIT                                                    |
//+------------------------------------------------------------------+
double TotalCurProfit(int magic)
  {
   double MyCurrentProfit=0;
   for(int cnt=0;cnt < OrdersTotal();cnt++)
     {
      OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
      if (OrderMagicNumber()==magic)
        {
         MyCurrentProfit+= (OrderProfit()+OrderSwap());
        }
     }
   return(MyCurrentProfit);
  }
//+------------------------------------------------------------------+
//|  CLOSE HEDGE                                                     |
//+------------------------------------------------------------------+
bool CloseHedge(int magic)
  {
   //_______________________________________________________________________
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==magic)
        {
         if(OrderClose(OrderTicket()
         ,OrderLots()
         ,OrderClosePrice()
         ,MarketInfo(OrderSymbol(),MODE_SPREAD)
         ,CLR_NONE)
         )SResult=true;
        }
     }
   if(SResult||BResult){return(true);if(PlayAudio){PlaySound("ok.wav");}}
   else Print("CloseHedge Error: ",ErrorDescription(GetLastError()));
   //_______________________________________________________________________
   RefreshRates();
  }
//+------------------------------------------------------------------+
//| SEND HEDGE                                                       |
//+------------------------------------------------------------------+
bool SendH(string symbol,int op,double lots,double price,int sp,string comment,int magic)
  {
   if(OrderSend(symbol
   ,op
   ,lots
   ,price
   ,sp
   ,0
   ,0
   ,comment
   ,magic
   ,0
   ,CLR_NONE)
   >0)
     { return(true);
      if(PlayAudio)PlaySound("expert.wav");
     }
     else {Print(symbol,": "
        ,magic," : "
        ,ErrorDescription(GetLastError()));
      return(false);
     }
  }
//+------------------------------------------------------------------+
//|  EXISTING POSITION                                               |
//+------------------------------------------------------------------+
int ExistPositions(string symbol,int magic)
  {
   int NumPos=0;
   for(int i=0;i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)
      &&OrderSymbol()==symbol
      &&OrderMagicNumber()==magic
      )
      { NumPos++;}
     }
   return(NumPos);
  }
//+------------------------------------------------------------------+
//|  EXISTING OP POSITION                                            |
//+------------------------------------------------------------------+
int ExistOP(string symbol,int magic)
  {
   int NumPos=-1;
   for(int i=0;i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)
      &&OrderSymbol()==symbol
      &&OrderMagicNumber()==magic
      )
      { NumPos=OrderType();}
     }
   return(NumPos);
  }
//+------------------------------------------------------------------+
//| CLOSE SCRAP                                                      |
//+------------------------------------------------------------------+
bool CloseScrap(string sym,int op,int magic)
  {
   //_______________________________________________________________________
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)
      && OrderMagicNumber()==magic
      &&OrderSymbol()==sym
      &&OrderType()==op)
        {
         if(OrderClose(OrderTicket()
         ,OrderLots()
         ,OrderClosePrice()
         ,MarketInfo(OrderSymbol(),MODE_SPREAD)
         ,CLR_NONE)
         )BResult=true;
        }
     }
   if(SResult||BResult){return(true);if(PlayAudio){PlaySound("ok.wav");}}
   else Print("CloseScrap Error: ",ErrorDescription(GetLastError()));
   //_______________________________________________________________________
   RefreshRates();
  }
//+------------------------------------------------------------------+
//|  Transform OP Value To string                                    |
//+------------------------------------------------------------------+
string OP2Str(int op)
  {
   switch(op)
     {
      case OP_BUY : return("BUY");
      case OP_SELL: return("SELL");
      default : return("~~");
     }
  }
//+------------------------------------------------------------------+
//| ET ORDERTIME OF EXISTING POSITION                                |
//+------------------------------------------------------------------+
int GetTimeExistOP(string symbol,int magic)
  {
   int NumPos=-1;
   for(int i=0;i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)
      &&OrderSymbol()==symbol
      &&OrderMagicNumber()==magic
      )
      { NumPos=OrderOpenTime();}
     }
   return(NumPos);
  }
//+------------------------------------------------------------------+
//| Translate bool to string                                         |
//+------------------------------------------------------------------+
string bool2str( bool boolval)
  {
   if(boolval==true) return("Yes");
   if(boolval==false)return("No");
  }
//+------------------------------------------------------------------+
//|AUTO LOT                                                          |
//+------------------------------------------------------------------+
double Base(int MM)
  {
   switch(MM)
     {
      case 1: return(AccountBalance()); break;
      case 2: return(AccountEquity()); break;
      case 3: return(AccountFreeMargin());
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double Lots(string symbol, double risk)
  {
   if(risk > 100) risk=100;
   Lot=NormalizeDouble(Base(MMBase)*(risk/100)/AccountLeverage()/10.0, 2);
   Lot=NormalizeDouble(Lot/lot_step, 0)*lot_step;
   if(Lot < Min_Lot) Lot=Min_Lot;
   if(Lot > Max_Lot) Lot=Max_Lot;
   return(Lot);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double AutoBLots()
  {
   double z=1+H_B_LotsRatio
   ,BLot=Lots(BaseSymbol,PercentMaxRisk)/z;
 
   BLot=NormalizeDouble(BLot/lot_step, 0)*lot_step;
   if(BLot < Min_Lot) BLot=Min_Lot;
   if(BLot > Max_Lot) BLot=Max_Lot;
 
   return(BLot);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double AutoHLots()
  {
   double HLot=AutoBLots()*H_B_LotsRatio;
 
   HLot=NormalizeDouble(HLot/lot_step, 0)*lot_step;
   if(HLot < Min_Lot) HLot=Min_Lot;
   if(HLot > Max_Lot) HLot=Max_Lot;
 
   return(HLot);
  }




4. Trading Process

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   midpt3=(iClose(BaseSymbol,1440,3)+iOpen(BaseSymbol,1440,3))/2;

  
int hb=FileOpen("B317.csv", FILE_CSV|FILE_READ) // Get the latest Used Margin
   ,
hh=FileOpen("H317.csv", FILE_CSV|FILE_READ); // for calculating the %ROI

   if(hb>0)
     {
      GBUM=StrToDouble(FileReadString(hb));
      
FileClose(hb);
    
}

   if(hh>0)
     {
      GHUM=StrToDouble(FileReadString(hh));
      
FileClose(hh);
    
}

   TUM=GBUM+GHUM;
    
{
      if(Period()==1440) // only allow to atatch on D1 timeframe
        {
         //----
         if(day!=Day()) // the new day has come
           { sent=0;cleared=false;
            
if(ExistPositions(BaseSymbol,MagicNo)==1&&ExistPositions(H_Symbol,MagicNo)==1)
              { //if the hedge exist.
               if(Day()!= TimeDay(GetTimeExistOP(BaseSymbol,MagicNo))
&&
Day()!=TimeDay(GetTimeExistOP(H_Symbol,MagicNo)))
                  //the order-time is not the same as today
                 {
                  if(ClearTradeDaily? && (TotalCurProfit(MagicNo)/TUM)*100>AcceptableLoss_ROI)
                     //allow to clear hedge daily and in acceptable loss
                    {
                     if(CloseHedge(MagicNo)){cleared=true;BUM=0;HUM=0;} //cleared.
                    }
                  else //in case the Demark's signal has changed
                     if((DeMark(BaseSymbol,0)>0&&DeMark(H_Symbol,0)>0&&DeMark(BaseSymbol,1)<0&&
DeMark(H_Symbol,1)<0)
                     ||
(DeMark(BaseSymbol,0)<0&&DeMark(H_Symbol,0)<0&&DeMark(BaseSymbol,1)>0&&
DeMark(H_Symbol,1)>0)
                     )
                       {
                        if(CloseHedge(MagicNo)){cleared=true;BUM=0;HUM=0;} //cleared.
                       }
                 }
              }
            else // in case there was any acident occure during clearing the hedge.
              {
               if(ExistPositions(BaseSymbol,MagicNo)>=1&&Day()!= TimeDay(GetTimeExistOP(BaseSymbol,MagicNo)))
                 {
                  if(ExistOP(BaseSymbol,MagicNo)==OP_SELL){CloseScrap(BaseSymbol,OP_SELL,MagicNo);
{
cleared=true;BUM=0;HUM=0;}}
                  if(ExistOP(BaseSymbol,MagicNo)==OP_BUY ){CloseScrap(BaseSymbol,OP_BUY,MagicNo);
{cleared=true;BUM=0;HUM=0;}}
                 }
               else
                  if(ExistPositions(H_Symbol,MagicNo)>=1&&Day()!= TimeDay(GetTimeExistOP(H_Symbol,MagicNo)))
                    {
                     if(ExistOP(H_Symbol,MagicNo)==OP_BUY) {CloseScrap(H_Symbol,OP_BUY,MagicNo);
{
cleared=true;BUM=0;HUM=0;}}
                     if(ExistOP(H_Symbol,MagicNo)==OP_SELL){CloseScrap(H_Symbol,OP_SELL,MagicNo);
{cleared=true;BUM=0;HUM=0;}}
                    }
              }
            // block opening if the correlation are not in allowed level.
            if(( Cor(BaseSymbol,H_Symbol,CorPeriod_1)>Between
            ||
Cor(BaseSymbol,H_Symbol,CorPeriod_1)<And
            )
            ||
( Cor(BaseSymbol,H_Symbol,CorPeriod_2)>Between
            ||
Cor(BaseSymbol,H_Symbol,CorPeriod_2)<And
            )
            )
               BlockOpen=true;
            
else BlockOpen=false;

            
day=Day(); // the new day process finished
           }
         else // The intra-day tick comes.
            if(TimeCurrent()>Time[0]&&ExistPositions(BaseSymbol,MagicNo)+ExistPositions(H_Symbol,MagicNo)>1)
              { // there are the hedge exist
               if((!cleared&&(TotalCurProfit(MagicNo)/TUM)*100>AcceptableLoss_ROI&&
Day()!= TimeDay(GetTimeExistOP(BaseSymbol,MagicNo)))
               ||
((TotalCurProfit(MagicNo)/TUM)*100>Daily_Percent_ROI)
               )
               {CloseHedge(MagicNo);BlockOpen=true;BUM=0;HUM=0;} // closed hedge when rich daily expected ROI.
              }
         //~~~~~~~

         double BMid=(MarketInfo(BaseSymbol,MODE_ASK)+MarketInfo(BaseSymbol,MODE_BID))/2
         ,
HMid=(MarketInfo(H_Symbol,MODE_ASK)+MarketInfo(H_Symbol,MODE_BID))/2
         ,
BLS,HLS
         ,
BLST,HLST;

        
BLS=AutoBLots(); // auto calculate the hedge lots
         HLS=AutoHLots();

        
//~~~~~~~

           {
            if(MathAbs((BMid-iOpen(BaseSymbol,1440,0)))<=BPt*gsp&&
MathAbs
(HMid-iOpen(H_Symbol,PERIOD_D1,0))<=HPt*gsp)
               // only open trade when the prices are both near each daily open
              {
               int handleB=FileOpen("B"+DoubleToStr(317,0)+".csv", FILE_CSV|FILE_WRITE, ';')
               ,
handleH=FileOpen("H"+DoubleToStr(317,0)+".csv", FILE_CSV|FILE_WRITE, ';')
               ;
// prepair to write the used margin to the files to recallable

               if(DeMark(BaseSymbol,0)>0&&DeMark(H_Symbol,0)>0
               &&
iClose(BaseSymbol,1440,1)>midpt3
              )// Demark signaled the UP TREND
                 {
                  up=1;
                  
BaseOpen=MarketInfo(BaseSymbol,MODE_ASK); // Buy Base Symbol
                  HOpen =MarketInfo(H_Symbol,MODE_BID); // Sell Hedge Symbol

                  if(MathAbs((BaseOpen-iOpen(MarketInfo(BaseSymbol,MODE_BID),1440,0)))<=BPt*gsp
                  &&
MathAbs(MarketInfo(H_Symbol,MODE_BID)-iOpen(H_Symbol,PERIOD_D1,0))<=HPt*gsp
                 )// if they both near daily open
                    {
                     if(!BlockOpen && !BlockOpening) // not both Manual blocking and Correlation blocking
                       {
                        if(ExistPositions(BaseSymbol,MagicNo)!=0 && ExistOP(BaseSymbol,MagicNo)==OP_SELL)
                          { // there's one (or more) old base order exist
                           CloseScrap(BaseSymbol,OP_SELL,MagicN