Русский 中文 Español Deutsch 日本語 Português
The Basic of Coding A Hedge Expert Advisor

The Basic of Coding A Hedge Expert Advisor

MetaTrader 4Examples | 9 July 2007, 12:27
21 093 7
chayutra sriboonruang
chayutra sriboonruang

Introduction

I'm going to give an idea of a simple hedge expert advisor. The Big Note Of Hedging EA Basic:

  • Hedge (finance) (From Wikipedia, the free encyclopedia)

    (Redirected from Hedging)

    In finance, a hedge is an investment that is taken out specifically to reduce or cancel out the risk in another investment. Hedging is a strategy designed to minimize exposure to an unwanted business risk, while still allowing the business to profit from an investment activity. Typically, a hedger might invest in a security that he believes is under-priced relative to its "fair value" (for example a mortgage loan that he is then making), and combine this with a short sale of a related security or securities. Thus the hedger doesn't care whether the market as a whole goes up or down in value, only whether the under-priced security appreciates relative to the hedge. Holbrook Working, a pioneer in hedging theory, called this strategy "speculation in the basis, "[1] where the basis is the difference between the hedge's theoretical value and its actual value (or between spot and futures prices in Working's time).

    Some form of risk taking is inherent to any business activity. Some risks are considered to be "natural" to specific businesses, such as the risk of oil prices increasing or decreasing is natural to oil drilling and refining firms. Other forms of risk are not wanted, but cannot be avoided without hedging. Someone who has a shop, for example, can take care of natural risks such as the risk of competition, of poor or unpopular products, and so on. The risk of the shopkeeper's inventory being destroyed by fire is unwanted, however, and can be hedged via a fire insurance contract. Not all hedges are financial instruments: a producer that exports to another country, for example, may hedge its currency risk when selling by linking its expenses to the desired currency.
    read more here

  • All the things we need from the server must be called by the MarketInfo(string symbol, int type) function. This function allow us to call any data beyond the data that appearing on the active chart window. This also allow us to send any kind of order of any symbol beyond the symbol that actively shown in the active chart window. And this can let us hedge the 2 symbol easily. Thanks God and MT4 team members, it helps so much.

  • One thing necessary in hedging is The Correlation between the 2 monitoring symbols which can find out with some small functions that will be shown below.

    Correlation, in the financial world, is the statistical measure of the relationship between two securities. The correlation coefficient ranges between -1 and +1. A correlation of +1 implies that the two currency pairs will move in the same direction 100% of the time. A correlation of -1 implies the two currency pairs will move in the opposite direction 100% of the time. A correlation of zero implies that the relationship between the currency pairs is completely random.read more here


All above are the simple things the Forex hedgers using MT4 Expert Advisor need to know. Now we can start making a hedge EA.



Step by Step to Code the Hedge EA

Step 1 : The Input Parameters

First before start writing the Hedge EA, we need to choose 2 correlate symbols, i.e.:

  • GBPUSD & EURUSD that always move the same way;
  • EURUSD & USDCHF that always move the opposite way;
  • * etc.

In this article, I will choose my very own favorite hedge pair that is EURJPY & GBPJPY. It always moves the same way, easier to set the hedging order type. Now let's get started. To start making a Hedge EA, let's get known the input variables below.

// this is to block the order sending function but 
// not to block the close function.
extern bool BlockOpening = false; 
 
extern string BaseSymbol = "EURJPY";//the 1st symbol 
 
extern string H_Symbol = "GBPJPY";//the 2nd symbol 
 
extern bool MoveSameWay = true;//they move the same way or not 
 
extern int CorPeriod = 5;//your favorite correlation period 
 
extern double BaseLotSize = 1.5;//1st symbol lotsize 
 
extern double H_LotsSize = 1.0;//2nd symbol lotsize 
 
extern double ExpectProfit$ = 137;//your expect profit in USD 
//your acceptable loss in USD in case any error occurred 
extern double AcceptableLoss$ = -77; 
 
extern string ExpectCor = "______";//your expect correlation to hedge 
//this is the upper expect cor value and has to be greater than "And" 
extern double Between = 1.05; 
 
extern double And = 0.9;//this is the lower expect cor level 
 
extern string MISC = "______";//some thing more 
 
extern int MagicNo = 318;//your favorite magic number 
 
extern bool ShowStatus = true;//to show the present hedging status 
//to play sound when SendH and CloseH function done 
extern bool PlayAudio = false;

Step 2 : The Variable Declaration


Following is the variables used in this EA and I will only explain the variable necessary to understand how the EA works.

int BSP       // the spread of base symbol 
 
    , HSP      // the spread of hedge symbol 
 
    , gsp 
 
    , BOP = -1 // base symbol order type 
 
    , HOP = -1 // hedge symbol order type 
 
    , up = 0 
 
    , Hcnt = 0 
 
    , u = 0 
 
    , d = 0 
 
    , day = 0 
 
    , sent=0 
 
    , firstopen 
 
    , expire; 
 
double Lot 
 
       , BaseOpen // base symbol order open price 
 
       , HOpen    // hedge symbol order open price 
 
       , BPt      // base symbol Point value 
 
       , HPt      // hedge symbol Point value 
 
       , BSwapL   // base symbol swap long value 
 
       , BSwapS   // base symbol swap short value 
 
       , HSwapL   // hedge symbol swap long value 
 
       , HSwapS;  // hedge symbol swap short value 
 
 
bool SResult = false, BResult = false, H1.profitswap, 
     H2.profitswap, H3.profitswap; 
 
bool SwapMode = true, allmeetcor = false, BlockOpen = false, 
     buy,sell,cleared = false; 
 
string H1.string = "", H2.string = "", H3.string = "", 
       OrdComment = "", candletxt,tdstxt = "";

Step 3 : Get All Necessary Static Parameters


Now let's specify some static values that will be declared in the init() part.

//+------------------------------------------------------------------+ 
//| 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); 
    BSwapL = MarketInfo(BaseSymbol,MODE_SWAPLONG); 
    BSwapS = MarketInfo(BaseSymbol,MODE_SWAPSHORT);
    HSwapL = MarketInfo(H_Symbol,MODE_SWAPLONG); 
    HSwapS = MarketInfo(H_Symbol,MODE_SWAPSHORT); 
//---- 
    return(0); 
  }

Step 4 : The Useful Functions


Before we get into the funniest part we are waiting for, the "start()" function, let us begin with the functions used in this EA. But, please note that all functions will stay outside the start() function.


1. The Correlation Function

First we need to start with the correlation calculation functions. The functions below are applied from a man giving away the free correlation indicator (igorad2004@list.ru) and I modified them to easier use in this EA, this we will not need to call the correlation value from the outside indicator any more. Good idea?

//+------------------------------------------------------------------+ 
//|  CORRELATION                                                     |
//+------------------------------------------------------------------+ 
double symboldif(string symbol, int shift) 
  { 
    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)); 
  }
//+------------------------------------------------------------------+
//|  The real correlation function to call is here.                  |
//+------------------------------------------------------------------+
double Cor(string base, string hedge) 
  { 
    double u1=0,l1=0,s1=0; 
    for(int i = CorPeriod - 1; i >= 0; i--) 
      { 
        u1 += u(symboldif(base, i), symboldif(hedge, i)); 
        l1 += powdif(symboldif(base, i)); 
        s1 += powdif(symboldif(hedge, i)); 
      } 
    if(l1*s1 > 0) 
        return(u1 / MathSqrt(l1*s1)); 
  } 
//+------------------------------------------------------------------+

The CorPeriod variable will be extern as an input variable to allow us to adjust it. When you want to calculate the correlation between 2 symbols, just call the Cor(string base,string hedge) function like this Cor(EURJPY,GBPJPY). It's easy, isn't it?


2. The Send Hedge Function

I think it's easier to manage how we can send the hedge orders by creating a SendH function below.

//+------------------------------------------------------------------+
//| 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); 
      } 
  } 
//+------------------------------------------------------------------+

You can read more about the OrderSend function here.

This ErrorDescription(GetLastError()) function above lets our EA tell us what error occurred when the trading function was working for us. To use it, we need to include the "stdlib.mqh" file by placing the code like this:

//+------------------------------------------------------------------+ 
//|                                                     MyHedge.mq4  | 
//|                                                         myHedge  | 
//|                                     http://dailyh.blogspot.com/  | 
//+------------------------------------------------------------------+ 
#property copyright "myHedge" 
#property link "http://dailyh.blogspot.com/" 
#include <stdlib.mqh>
//+------------------------------------------------------------------+

And to use it, just call the "ErrorDescription() " function like shown above.


3. The Close Hedge Function

Beyond sending the orders, we also need a function to close all hedging orders when they reach our expected profit. And here you go:

//+------------------------------------------------------------------+
//|  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)
     {
       return(true);
       if(PlayAudio)
         {
           PlaySound("ok.wav");
         }
     } 
   else 
       Print("CloseHedge Error: ", ErrorDescription(GetLastError())); 
   RefreshRates(); 
   // return(0); 
  } 
//+------------------------------------------------------------------+

This function will only close the orders with the same magic number, meaning that it will not interfere the hedge orders with other magic numbers. Not really a thing to worry about. Before using that close function, we need to define "how much we've got now" by using the function below.


4. The Finding The Total Profit 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); 
  } 
//+------------------------------------------------------------------+
Like with the close function, to know the hedge profit we need to monitor only the orders with the same magic number, to close them correctly. To use them, just code them like this:
if(TotalCurProfit(318) > 100) 
    CloseHedge(318);

All profit values are calculated in USD. From the line above, when overall profit of orders with magic number 318 is greater than $100 they will be closed. That's it. To open the hedge orders, we need to know that there's no any order with same symbol and magic number floating at the moment we need to send the hedge. This can be defined by this function.



5. Get The Amount Of Existing Positions
//+------------------------------------------------------------------+
//| EXISTING POSITIONS                                               |
//+------------------------------------------------------------------+
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); 
 
  } 
//+------------------------------------------------------------------+ 

It can be used like this:

ExistPositions("GBPJPY",318)

This function will return us "how many opening orders of GBPJPY with magic number of 318 are floating" at the moment. One more function to define the type of floating order.


6. Finding The Order Type Of Specific Existing Position
//+------------------------------------------------------------------+  
//| 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); 
  } 
//+------------------------------------------------------------------+

This function returns the integer value of the order type for the specified symbol and magic number that are floating at the moment. If the floating order of GBPJPY is OP_BUY, the returned value is "0". This function does not only work together with the trading function. It also works with a function to show the current hedging status. This function is called "OP2Str".



7. Showing The Trading Status

//+------------------------------------------------------------------+
//| Transform OP Value To string                                     |
//+------------------------------------------------------------------+ 
string OP2Str(int op) 
  { 
    switch(op) 
      { 
        case OP_BUY : return("BUY"); 
        case OP_SELL: return("SELL"); 
        default : return("~~"); 
      } 
  }
//+------------------------------------------------------------------+


Not very much to say, I think it shows how it works already.


8. Close All The Specific Type Of Orders

One more function to close any single order directly, in case of an error, when sending or closing the hedge.

//+------------------------------------------------------------------+
//| 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) 
           && amp; OrderMagicNumber() == magic 
           && OrderSymbol() == sym 
           && OrderType() == op) 
          { 
            if(OrderClose(OrderTicket() 
               , OrderLots() 
               , OrderClosePrice() 
               , MarketInfo(OrderSymbol(), MODE_SPREAD) 
               , CLR_NONE))
                BResult = true; 
          } 
      } 
    if(BResult)
      {
        return(true);
        if(PlayAudio)
          {
            PlaySound("ok.wav");
          }
      } 
    else 
        Print("CloseScrap Error: ", ErrorDescription(GetLastError())); 
    RefreshRates(); 
    // return(0); 
  }

i.e., CloseScrap("GBPJPY",OP_BUY,318) : this will close only floating long "GBPJPY" that has magic number of 318. It's easy. One last function to get to know.



9. Showing Any Boolean Status You Wish
//+------------------------------------------------------------------+
//| Translate bool to string                                         |
//+------------------------------------------------------------------+
string bool2str( bool boolval) 
  { 
    if(boolval == true) 
        return("Yes"); 
    if(boolval == false)
        return("No"); 
  }
//+------------------------------------------------------------------+
Nothing special, this function is to show the Boolean status of some parameters such as BlockOpening value. When you set it to true, this function will return "Yes" on your screen. It will return 'No" when you set it to false. That's all about the functions we need. Now let's enjoy coding the hedging process.


Step 5 : The Core Of The Expert Advisor

Start with this first:

//+------------------------------------------------------------------+ 
//| expert start function                                            | 
//+------------------------------------------------------------------+ 
int start() 
  {

Then specify the correlation range.

if(Cor(BaseSymbol, H_Symbol) > Between || 
   Cor(BaseSymbol, H_Symbol) < And) 
// Block opening when the correlation is out of 
// expected range. 
    BlockOpen = true; 
else 
    BlockOpen = false;
Next define the way to hedge (this is only an example), in this article I will select the trading style by the swap value, then I will only trade the way I can gain from the swap each day.

// if they move the same way we will open long & short 
if(MoveSameWay) 
  { 
    if(((BSwapL*BaseLotSize) + (HSwapS*H_LotSize)) > 0) 
      {  
        BOP = OP_BUY; 
        HOP = OP_SELL; 
      } 
    else 
        if(((BSwapS*BaseLotSize) + (HSwapL*H_LotSize)) > 0) 
          { 
            BOP = OP_SELL; 
            HOP = OP_BUY; 
          } 
  } // end MoveSameWay
// if the move the opposite way we will open short & short or long & long
else 
  { 
    if(((BSwapL*BaseLotSize) + (HSwapL*H_LotSize)) > 0) 
      { 
        BOP = OP_BUY; 
        HOP = OP_BUY; 
      } 
    else 
        if(((BSwapS*BaseLotSize) + (HSwapS*H_LotSize)) > 0) 
          { 
            BOP = OP_SELL; 
            HOP = OP_SELL; 
          } 
  }
Now it's time to send the hedge:
// if they meet the correlation range and 
// you're not blocking them
if(!BlockOpen && !BlockOpening)  
  { 
    if(BOP == OP_BUY) 
    // define the opening price    
        BaseOpen = MarketInfo(BaseSymbol, MODE_ASK); 
    else 
        BaseOpen = MarketInfo(BaseSymbol, MODE_BID); 
    if(HOP == OP_BUY)
        HOpen = MarketInfo(H_Symbol, MODE_ASK); 
    else 
        HOpen = MarketInfo(H_Symbol, MODE_BID); 
    // In case there is no any swap condition to gain 
    // from BOP & HOP will be -1.
    if(BOP >= 0 && HOP >= 0) 
      {
        if(ExistPositions(BaseSymbol, MagicNo) == 0 && 
           ExistPositions(H_Symbol, MagicNo) == 0) 
          { 
            SendH(BaseSymbol, BOP, BaseLotSize, BaseOpen, 
                  BSP, "COR : " +
                  DoubleToStr(Cor(BaseSymbol, H_Symbol), 2), 
                  MagicNo); 
            SendH(H_Symbol, HOP, H_LotsSize, HOpen, HSP, 
                  "COR : " +
                  DoubleToStr(Cor(BaseSymbol, H_Symbol), 2), 
                  MagicNo); 
          } 
        else // in case ping failed or requote 
          { 
            if(ExistPositions(BaseSymbol, MagicNo) == 1&&
               TotalCurProfit(MagicNo)>AcceptableLoss$) 
              { 
                CloseScrap(BaseSymbol, ExistOP(BaseSymbol, 
                           MagicNo), MagicNo); 
              } 
            else 
                if(ExistPositions(H_Symbol, MagicNo) == 1&&
                   TotalCurProfit(MagicNo) > AcceptableLoss$) 
                  { 
                    CloseScrap(H_Symbol, ExistOP(H_Symbol, 
                               MagicNo), MagicNo); 
                  } 
          } 
 
      }
    else // if one of BOP and HOP is less than 0
      {
        string swaptxt = "No Swap Condition To Gain From :" + 
                   "pls modify one or more input parameter(s).";
      }
  }

Then close them when they reach the expected profit

if((TotalCurProfit(MagicNo) > ExpectProfit$)
  {
    CloseHedge(MagicNo);
  }

And something funnier: The ShowStatus part.

if(ShowStatus)
  {
    Comment("\nCorrel: " + DoubleToStr(Cor(BaseSymbol
            , H_Symbol), 2)
            , "\nBlockOpen : " + bool2str(BlockOpen 
            || BlockOpening)
            , "\n" + swaptxt
            , "\n~~~~~~~"
            , "\nB/H [sp] : " + BaseSymbol + " [" 
            + BSP + "]" + " / " 
            + H_Symbol+" ["+HSP+"]"
            , "\nCurOp [Lots]: " 
            + OP2Str(ExistOP(BaseSymbol, MagicNo)) 
            + " [" + DoubleToStr(BaseLotSize, 2) + "]"
            + " ~ " + OP2Str(ExistOP(H_Symbol, MagicNo)) 
            + " [" 
            + DoubleToStr(H_LotsRatio*BaseLotSize, 2) + "]"
            , "\nCurPF [Expect]: $" 
            + DoubleToStr(TotalCurProfit(MagicNo), 2) 
            + " [$"+DoubleToStr(ExpectProfit$, 2) + "]");
  }
else 
    Comment("");

Finish with the end of every EA.

return(0);
}


Step 6 : Gathering Them All

Here you can see how myHedge.mq4 looks like.

//+------------------------------------------------------------------+
//|                                                      MyHedge.mq4 |
//|                                                          myHedge |
//|                                      http://dailyh.blogspot.com/ |
//+------------------------------------------------------------------+
#property copyright "myHedge"
#property link "http://dailyh.blogspot.com/"
//----
#include <stdlib.mqh>
// this is to block the order sending function but not to block the 
// close function.
extern bool BlockOpening = false;
extern string BaseSymbol = "EURJPY"; // the 1st symbol
extern string H_Symbol = "GBPJPY";   // the 2nd symbol
extern bool MoveSameWay = true; // they move the same way or not
extern int CorPeriod = 5; // your favorite correlation period
extern double BaseLotSize = 1.5; // 1st symbol lotsize
extern double H_LotSize = 1.0; // 2nd symbol lotsize
extern double ExpectProfit$ = 137; // your expect profit in USD
// your acceptable loss in USD in case any error occurred
extern double AcceptableLoss$ = -77; 
extern string ExpectCor = "______"; // your expect correlation to 
// hedge this is the upper expect cor value and has to be greater 
// than "And"
extern double Between = 1.05;
extern double And = 0.9; // this is the lower expect cor level
extern string MISC = "______"; // some thing more
extern int MagicNo = 318; // your favorite magic number
extern bool ShowStatus = true; // to show the present hedging status
// to play sound when SendH and CloseH function done
extern bool PlayAudio = false; 
//----
int BSP  // the spread of base symbol
    ,HSP // the spread of hedge symbol
    ,gsp
    ,BOP = -1 // base symbol order type
    ,HOP = -1 // hedge symbol order type
    ,up = 0
    ,Hcnt = 0
    ,u = 0
    ,d = 0
    ,day = 0
    ,sent = 0
    ,firstopen
    ,expire;
double Lot
       ,BaseOpen // base symbol order open price
       ,HOpen // hedge symbol order open price
       ,BPt // base symbol Point value
       ,HPt // hedge symbol Point value
       ,BSwapL // base symbol swap long value
       ,BSwapS // base symbol swap short value
       ,HSwapL // hedge symbol swap long value
       ,HSwapS; // hedge symbol swap short value
bool SResult = false, BResult = false, H1.profitswap, H2.profitswap, 
     H3.profitswap;
bool SwapMode = true, allmeetcor = false, BlockOpen = false, buy, 
     sell, cleared = false;
string H1.string = "", H2.string = "", H3.string = "", 
       OrdComment = "", candletxt,tdstxt = "";
//+------------------------------------------------------------------+
//| 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);
//----
   BSwapL = MarketInfo(BaseSymbol, MODE_SWAPLONG);
   BSwapS = MarketInfo(BaseSymbol, MODE_SWAPSHORT);
//----
   HSwapL = MarketInfo(H_Symbol, MODE_SWAPLONG);
   HSwapS = MarketInfo(H_Symbol, MODE_SWAPSHORT);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   if(Cor(BaseSymbol, H_Symbol) > Between || 
      Cor(BaseSymbol, H_Symbol) < And)
   // Block opening when the correlation is out of expected range.
       BlockOpen = true;
   else 
       BlockOpen = false;
//----
   if(MoveSameWay)
     {
       if((BSwapL*BaseLotSize) + (HSwapS*H_LotSize) > 0)
         {
           BOP = OP_BUY;
           HOP = OP_SELL;
         }
       else 
           if((BSwapS*BaseLotSize) + (HSwapL*H_LotSize) > 0)
             {
               BOP = OP_SELL;
               HOP = OP_BUY;
             }
     }
   else
     {
       if((BSwapL*BaseLotSize) + (HSwapL*H_LotSize) > 0)
         {
           BOP = OP_BUY;
           HOP = OP_BUY;
         }
       else 
           if((BSwapS*BaseLotSize) + (HSwapS*H_LotSize) > 0)
             {
               BOP = OP_SELL;
               HOP = OP_SELL;
             }
     }
   if(!BlockOpen && !BlockOpening)
     {
       if(BOP == OP_BUY) 
           BaseOpen = MarketInfo(BaseSymbol, MODE_ASK);
       else            
           BaseOpen = MarketInfo(BaseSymbol, MODE_BID);
       if(HOP == OP_BUY)
           HOpen = MarketInfo(H_Symbol, MODE_ASK);
       else
           HOpen = MarketInfo(H_Symbol, MODE_BID);
       // In case there is no any swap condition that we can gain from.
       if(BOP >= 0 && HOP >= 0) 
         {
           if(ExistPositions(BaseSymbol, MagicNo) == 0 && 
              ExistPositions(H_Symbol,MagicNo) == 0)
             {
               SendH(BaseSymbol, BOP, BaseLotSize, BaseOpen, BSP, 
                     "COR : " + DoubleToStr(Cor(BaseSymbol, H_Symbol), 
                     2), MagicNo);
               SendH(H_Symbol, HOP, H_LotSize, HOpen, HSP, "COR : " + 
                     DoubleToStr(Cor(BaseSymbol, H_Symbol), 2), MagicNo);
             }     
           else // in case ping failed or requote
             {
               if(ExistPositions(BaseSymbol, MagicNo) == 1 && 
                  TotalCurProfit(MagicNo) > AcceptableLoss$)
                 {
                   CloseScrap(BaseSymbol, ExistOP(BaseSymbol, 
                              MagicNo), MagicNo);
                 }
               else 
                   if(ExistPositions(H_Symbol, MagicNo) == 1 && 
                      TotalCurProfit(MagicNo) > AcceptableLoss$)
                     {
                       CloseScrap(H_Symbol, ExistOP(H_Symbol, 
                                  MagicNo), MagicNo);
                     }
             }
         }
       else
         {
           string swaptxt = "No Swap Condition To Gain From : pls " + 
                            "modify one or more input parameter(s).";
         }
     }
   if(TotalCurProfit(MagicNo) > ExpectProfit$)
     {
       CloseHedge(MagicNo);
     }
   if(ShowStatus)
     {
       Comment("\nCorrel: "+DoubleToStr(Cor(BaseSymbol, H_Symbol), 2)
               , "\nBlockOpen : " + bool2str(BlockOpen || BlockOpening)
               , "\n" + swaptxt
               , "\n~~~~~~~"
               , "\nB/H [sp] : " + BaseSymbol + " [" + BSP + "]" + 
                 " / " + H_Symbol + " [" + HSP + "]"
               , "\nCurOp [Lots]: " + OP2Str(ExistOP(BaseSymbol, 
                 MagicNo)) + " [" + DoubleToStr(BaseLotSize, 2) + "]"
                 + " ~ " + OP2Str(ExistOP(H_Symbol, MagicNo)) + " [" + 
                 DoubleToStr(H_LotSize, 2) + "]"
               , "\nCurPF [Expect]: $" + 
                 DoubleToStr(TotalCurProfit(MagicNo), 2) + " [$" + 
                 DoubleToStr(ExpectProfit$, 2) + "]");
     }
   else 
       Comment("");
   return(0);
  }
//+------------------------------------------------------------------+
//| CORRELATION                                                      |
//+------------------------------------------------------------------+
double symboldif(string symbol, int shift)
  {
   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)
  {  
   double u1 = 0, l1 = 0, s1 = 0;
   for(int i = CorPeriod - 1; i >= 0; i--)
     {
       u1 += u(symboldif(base, i), symboldif(hedge, i));
       l1 += powdif(symboldif(base, i));
       s1 += powdif(symboldif(hedge, i));
     }
   if(l1*s1 > 0) 
       return(u1 / MathSqrt(l1*s1));
  }
//+------------------------------------------------------------------+
//| 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);      
     }      
  }
//+------------------------------------------------------------------+
//| 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)
     {
       return(true);
       if(PlayAudio)
         {
           PlaySound("ok.wav");
         }
     }
   else 
       Print("CloseHedge Error: ", ErrorDescription(GetLastError()));
   RefreshRates();
//  return(0);
  }  
//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+
//| 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);
  }
//+------------------------------------------------------------------+
//| Transform OP Value To string                                     |
//+------------------------------------------------------------------+
string OP2Str(int op)
  {
   switch(op)
     {
       case OP_BUY : return("BUY");
       case OP_SELL: return("SELL");
       default     : return("~~");
     }
  }
//+------------------------------------------------------------------+
//| 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();
//  return(0);
  }  
//+------------------------------------------------------------------+
//| Translate bool to string                                         |
//+------------------------------------------------------------------+
string bool2str(bool boolval)
  {
   if(boolval == true) 
       return("Yes");
   if(boolval == false)
       return("No");
  }
//+------------------------------------------------------------------+

Conclusion

This is just an example of a simple hedge Expert Advisors. You need to modify it to fit your own hedging style. I am sure that there are many hedging styles out there. And please note that this kind of EA cannot be tested by the Strategy Tester due to its own limit. You need to test it live only. Below is the sample result of a hedge EA.


And the ShowStatus function will be like this:

Hope you enjoy my article and strongly hope that it helps you to create your own hedge EA.

Attached files |
myHedge.mq4 (13.75 KB)
Last comments | Go to discussion (7)
Lukasz Starczewski
Lukasz Starczewski | 8 Mar 2012 at 09:19
I get "No Swap Condition To Gain From : pls modify one or more input parameter(s)". What is causing that? How to make it work?
Silverthorn
Silverthorn | 10 May 2014 at 02:18
I am having a problem with sending the hedge using this method. The base symbol is opening OK but the Hedge is giving an Invalid Price error. Any ideas????
Daniel Castro
Daniel Castro | 6 May 2017 at 16:04
What is the point in having a code that is not backtestable?
s loo
s loo | 23 Mar 2020 at 12:54
Hi, I am studying this, but in this core function :  

double Cor(string base, string hedge) 
  { 
    double u1=0,l1=0,s1=0; 
    for(int i = CorPeriod - 1; i >= 0; i--) 
      { 
        u1 += u(symboldif(base, i), symboldif(hedge, i)); 
        l1 += powdif(symboldif(base, i)); 
        s1 += powdif(symboldif(hedge, i)); 
      } 
    if(l1*s1 > 0) 
        return(u1 / MathSqrt(l1*s1)); 
  } 


u1 / MathSqrt(l1*s1) , basically return , always return i mean , "1" ,

because MathSqrt(l1 * s1) = symoboldif(base, i) * symboldif(hedge, i) ...  

irinacfd
irinacfd | 5 Feb 2021 at 10:19
I wonder why the admin created an blog with MQL5 in the url that contains almost more mql4 code than mql5 code ...
Sending Trade Signal Via RSS Feed Sending Trade Signal Via RSS Feed
This is my idea how to send your trade signal as RSS FEEDS , a famous way to communicate with your community's members right now.
ZUP - Universal ZigZag with Pesavento Patterns. Part 1 ZUP - Universal ZigZag with Pesavento Patterns. Part 1
The article gives a short description of ideas underlying indicator ZUP - Universal ZigZag with Pesavento Patterns. The article also describes indicators of ZigZag embedded in ZUP.
Forex Trading ABC Forex Trading ABC
Working on financial markets represents, first of all, trade operations. We all, starting from the very childhood, have an intuitive idea of what is to buy and to sell. But Forex trading is still something special. This article deals with the ideas necessary to explain some terms. We will also consider the MQL 4 functions that correspond with those terms.
MQL4 Language for Newbies. Difficult Questions in Simple Phrases. MQL4 Language for Newbies. Difficult Questions in Simple Phrases.
This is the second article from the series "MQL4 Language for Newbies". Now we will examine more complex and advanced constructions of the language, learn new options and see, how they can be applied in everyday practice. You will get acquainted with a new cycle type 'while', new condition type 'switch', operators 'break' and 'continue'. Besides you will learn to write your own functions and work with multidimensional arrays. And for a dessert I have prepared an explanation about a preprocessor.