English Русский 中文 Español Deutsch 日本語
O básico de codificação de um Expert Advisor de cobertura

O básico de codificação de um Expert Advisor de cobertura

MetaTrader 4Exemplos | 22 fevereiro 2016, 10:06
1 970 0

Eu fornecerei uma ideia de um simples expert advisor de cobertura. A vantagem do EA básico de cobertura.

  • Cobertura (finanças) (Da Wikipédia, a enciclopédia livre)

    (Redirecionado de Cobertura)

    Em finanças, uma cobertura é um investimento que é retirado especificamente para reduzir ou anular o risco em outro investimento. Cobertura é uma estratégia projetada para minimizar a exposição a riscos indesejados do negócio, enquanto ainda permite que a empresa se beneficie de uma atividade de investimento. Normalmente, uma cobertura pode ser investida em um título que, acredita-se, estar subvalorizada em relação ao seu "valor justo" (por exemplo, um empréstimo hipotecário), e combina isso com uma venda a descoberto de um título ou títulos relacionados. Assim, o investidor não se importa se o mercado como um todo vai subir ou baixar o valor, ele se preocupa unicamente com o título subvalorizado. Holbrook Working, um pioneiro na teoria de cobertura, chamou essa estratégia de "especulação na base",[1] onde a base é a diferença entre o valor teórico de cobertura e seu valor real (ou entre os dois e os preços futuros do tempo de Working).

    Alguma forma de tomada de risco é inerente a qualquer atividade de negócios. Alguns riscos são considerados "naturais" em negócios específicos, assim como o risco do preço do petróleo aumentar ou baixar para empresas d perfuração ou refino de petróleo. Outras formas de risco não são desejadas, mas não podem ser evitadas sem cobertura. Alguém que tem uma loja, por exemplo, pode cuidar de riscos naturais tais como o risco de concorrência, de produtos ruins ou impopulares, e assim por diante. O risco de estoque do lojista ser destruído pelo fogo é indesejado, no entanto, pode ser coberto por um contrato de seguro de incêndio. Nem todas as coberturas são instrumentos financeiros: um produtor que exporta para outro país, por exemplo, pode cobrir seu risco de moeda ao vender ligando suas despesas com a moeda desejada.
    leia mais aqui

  • Todas as coisas que precisamos a partir do servidor devem ser chamadas pela função MarketInfo (símbolo string, tipo int). Esta função permite-nos chamar quaisquer dados além dos dados que aparecem na janela do gráfico ativo. Isso também nos permite enviar qualquer tipo de ordem de qualquer símbolo além do símbolo exibido ativamente na janela do gráfico ativo. E isso pode deixar-nos cobrir o símbolo 2 facilmente. Graças a Deus e aos membros da equipe MT4, isto ajuda muito.

  • Uma coisa necessária na cobertura é a correlação entre os 2 símbolos de monitoramento que podem encontrar-se com algumas pequenas funções que serão mostradas abaixo.

    Correlação, no mundo financeiro, é a medida estatística da relação entre dois títulos. O coeficiente de correlação varia entre -1 e +1. A correlação de +1 implica que os dois pares de moedas irão se mover no mesmo sentido 100% do tempo. A correlação de -1 implica que os dois pares de moedas irão se mover em posição oposta 100% do tempo. A correlação de zero implica que a relação entre os pares de moedas será completamente aleatória. leia mais aqui


Todo que está acima são coisas simples que quem faz cobertura no mercado Forex utilizando Expert Advisor MT4 precisa saber. Agora podemos começar a fazer um EA de cobertura.



Código do EA de cobertura passo a passo

Etapa 1: Os parâmetros de entrada

Em primeiro lugar, antes de começar a escrever o EA de cobertura, precisamos escolher 2 símbolos correlatos, ou seja:

  • GBPUSD e EURUSD que sempre se movem da mesma maneira;
  • EURUSD & USDCHF que sempre se movem de formas opostas;
  • * etc.

Neste artigo, escolherei meu próprio par de cobertura favorito que é EURJPY e GBPJPY. Ele sempre se move da mesma maneira,sendo assim, mais fácil definir o tipo de ordem de cobertura. Vamos começar. Para começar a fazer o EA de cobertura, vamos conhecer abaixo as variáveis de entrada.


// 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;

Etapa 2: A declaração da variável


A seguir estão as variáveis utilizadas neste EA e eu explicarei somente a variável necessária para entender como funciona o EA.


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 = "";

Etapa 3: Obtenha todos os parâmetros estáticos necessários


Agora vamos especificar alguns valores estáticos que serão declarados na parte do init().


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

Etapa 4: As Funções Úteis


Antes de entrar na parte mais engraçada, estamos aguardando a função "start ()", vamos começar com as funções utilizadas neste EA. Mas, por favor, observe que todas as funções vão ficar fora da função start().


1. A função de correlação

Primeiro, precisamos começar com as funções de cálculo de correlação. As funções a seguir são aplicadas por um homem fornecendo o indicador livre de correlação (igorad2004@list.ru) e eu os modifiquei para facilitar o uso neste EA, sendo assim, não será mais preciso chamar o valor de correlação do indicador de fora. Boa ideia?


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

A variável CorPeriod será externa como uma variável de entrada para permitir-nos configurá-la. Quando você quiser calcular a correlação entre 2 símbolos, basta chamar a função Cor(base da string, cobertura da string) como esta Cor (EURJPY, GBPJPY). É fácil, não é?


2. A função de envio de cobertura

Eu acho que é mais fácil gerenciar como podemos enviar as ordens de cobertura criando uma função SendH abaixo.


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

Você pode ler mais sobre a função OrderSend aqui.

Esta função ErrorDescription(GetLastError()) acima permite que nosso EA nos diga o erro que ocorreu quando a função de trading estava trabalhando para nós. Para usá-la, precisamos incluir o arquivo "stdlib.mqh" colocando o código da seguinte maneira:


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

E para usá-la, basta chamar a função "ErrorDescription()" como mostrado acima.


3. A função do fechamento da cobertura

Além de enviar as ordens, precisamos também de uma função para fechar todas as ordens de cobertura quando elas alcançam o lucro esperado. Lá vai:


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

Esta função só fechará as ordens com o mesmo número mágico, o que significa que não irá interferir nas ordens de cobertura com outros números mágicos. Não é uma coisa para se preocupar. Antes de usar essa função de fechamento, precisamos definir "o quanto nós temos agora", usando a função abaixo.


4. A função de encontrar o lucro total
//+------------------------------------------------------------------+
//|  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); 
  } 
//+------------------------------------------------------------------+


Como na função de fechamento, para saber o lucro da cobertura precisamos monitorar apenas as decisões com o mesmo número mágico, para fechá-las corretamente. Para usá-las, apenas configure os códigos da seguinte forma:

if(TotalCurProfit(318) > 100) 
    CloseHedge(318);

Todos os valores de lucro são calculados em USD. A partir da linha anterior, quando o lucro geral de ordens com o número mágico 318 for maior do que $100, elas serão fechadas. É isso. Para abrir as ordens de cobertura, precisamos saber que não há outra ordem com o mesmo símbolo e número mágico flutuando no momento que precisarmos enviar a cobertura. Isto pode ser definido por esta função.



5. Obter a quantidade de posições existentes
//+------------------------------------------------------------------+
//| 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); 
 
  } 
//+------------------------------------------------------------------+ 

Pode ser usado da seguinte forma:


ExistPositions("GBPJPY",318)

Esta função nos retornará "quantas ordens de abertura de GBPJPY com número mágico de 318 estão flutuando" no momento. Mais uma função para definir o tipo de ordem flutuante.


6. Encontrar o tipo de ordem de posição específicas existentes 
//+------------------------------------------------------------------+  
//| 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); 
  } 
//+------------------------------------------------------------------+

Esta função retorna o valor inteiro do tipo de ordem para o símbolo e o número mágico especificado que estão flutuando no momento. Se o número de flutuação do GBPJPY for OP_BUY, o valor de retorno é "0". Esta função não trabalha somente em conjunto com a função de trading. Ela também funciona com uma função para mostrar o estado atual da cobertura. Esta função chama-se "OP2Str".



7. Mostrando o estado do trading

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


Não há muito a dizer, acho que o nome já mostra como funciona.


8. Fechamento de todos os tipos específicos de ordens

Mais uma função para fechar qualquer ordem única diretamente, no caso de um erro, ao enviar ou fechar a cobertura.


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


CloseScrap("GBPJPY",OP_BUY,318) : isto irá fechar apenas o flutuação prolongada "GBPJPY" que possui o número mágico de 318. É fácil. Há mais uma função.



9. Mostrar qualquer estado booleano que você desejar
//+------------------------------------------------------------------+
//| Translate bool to string                                         |
//+------------------------------------------------------------------+
string bool2str( bool boolval) 
  { 
    if(boolval == true) 
        return("Yes"); 
    if(boolval == false)
        return("No"); 
  }
//+------------------------------------------------------------------+


Nada de especial, esta função mostrará o estado booleano de alguns parâmetros, tais como o valor BlockOpening. Quando você defini-la como verdadeira, esta função irá retornar "Sim" na tela. Ela irá retornar "Não" quando você defini-la como falsa. Isto é tudo sobre as funções que precisamos. Agora vamos aproveitar o processo de codificação da cobertura.


Etapa 5: O núcleo do Expert Advisor

Primeiramente, comece com isto:

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

Em seguida, especifique o intervalo de correlação.

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;


Depois, defina a forma da cobertura (este é apenas um exemplo), neste artigo vou selecionar o estilo de trading pelo valor de troca, então, só irei realizar o trade de maneira que eu posso ganhar com a troca todos os dias.

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


Agora é o momento de enviar a cobertura:


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


Em seguida, feche-os quando atingirem o lucro esperado


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

E algo mais engraçado: A parte de exibição do status.

    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("");

Finalize com o fim de cada EA.

 return(0);
}


Etapa 6: Reunir todos eles

Aqui você pode ver como o myHedge.mq4 parece.


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

Conclusão

Este é apenas um exemplo de uma Expert Advisors de cobertura simples. Você precisa modificá-lo para encaixar seu próprio estilo de cobertura. Estou certo de que existem muitos estilos de cobertura por aí. E, por favor, observe que este tipo de EA não pode ser testado pelo Strategy Tester devido seu próprio limite. Você precisa testá-lo apenas ao vivo. Abaixo está o resultado da amostra de uma EA de cobertura.


E a função ShowStatus será assim:


Espero que você aproveite meu artigo e que ele ajude-o a criar seu próprio EA de cobertura.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/1479

Arquivos anexados |
myHedge.mq4 (13.75 KB)
O envio do sinal de trade via feed RSS O envio do sinal de trade via feed RSS
Essa é minha ideia sobre como enviar sinal de trade como FEEDS RSS, um modo famoso de se comunicar com os membros da sua comunidade agora mesmo.
O mercado Forex pode ser previsto? Como criar uma estratégia de trading própria para este mercado? O mercado Forex pode ser previsto? Como criar uma estratégia de trading própria para este mercado?
Todo mundo que começa a trabalhar no Forex tenta responder estas questões. Mas nem todos encontram a resposta, mesmo depois de muitos anos de trabalho duro e pesquisas. Eu, pessoalmente, respondi esta questão, assim como muitas outras questões deste artigo. Como resultado dessas respostas, uma maneira de criar uma estratégia eficiente de trading foi determinada.
O que é Martingale? É sensato utilizá-lo? O que é Martingale? É sensato utilizá-lo?
Este artigo contém uma descrição detalhada do sistema Martingale, bem como cálculos matemáticos precisos necessários para responder a pergunta: "É sensato utilizar o sistema Martingale?"
Escolha automatizada de corretora para um funcionamento eficiente do Expert Advisors Escolha automatizada de corretora para um funcionamento eficiente do Expert Advisors
Não é segredo que, para um funcionamento eficaz do Expert Advisors, precisamos encontrar uma corretora adequada. Este artigo descreve um sistema de abordagem para esta busca. Você vai se familiarizar com o processo de criação de um programa com dll para trabalhar com diferentes terminais.