Fundamentos de la codificación de un asesor experto de cobertura

chayutra sriboonruang | 14 marzo, 2016


Introducción

Voy a dar una idea de un sencillo asesor experto de cobertura. La gran nota sobre los fundamentos de los asesores expertos de cobertura:

  • Cobertura (finanzas) (de la wikipedia, la enciclopedia libre)

    (Redirigido desde Hedging (cobertura contra riesgos))

    En las finanzas, una cobertura es una inversión que se realiza específicamente para reducir o cancelar el riesgo de otra inversión. La cobertura contra riesgos es una estrategia diseñada para minimizar la exposición a un riesgo del negocio no deseado, al tiempo que permite a dicho negocio obtener beneficios de una actividad de inversión. Por lo general, el inversor de riesgo controlado invierte en un valor bursátil que él cree que tiene un precio inferior en relación con su valor justo (por ejemplo, un préstamo hipotecario que él está realizando) y lo combina con una venta a corto plazo de un valor o valores bursátiles relacionados. De este modo, el inversor de riesgo controlado no se preocupa de si el mercado en su conjunto sube o baja, solo de si el valor bursátil infravalorado aumenta de valor con respecto a la cobertura. Holbrook Working, un pionero en la teoría de las coberturas, llamó a esta estrategia "especulación en la base, "[1] donde la base es la diferencia entre el valor teórico de la cobertura y su valor real (o entre el punto y los precios futuros en el tiempo de Working).

    Algunos formas de asumir riesgos son inherentes a cualquier actividad empresarial. Algunos riesgos se consideran "naturales" de un negocio concreto, como el riesgo de aumento o disminución de los precios del petróleo, algo natural en las empresas de extracción y refinado de crudo. Otros tipos de riesgos son riesgos no deseados, pero no pueden evitarse sin una cobertura. Alguien que tenga una tienda, por ejemplo, puede hacerse cargo de los riesgos naturales como el riesgo de competencia, de productos de poca calidad o no populares, etc. El riesgo del inventario del tendero que es destruido por un incendio no es deseado, pero sin embargo puede ser cubierto por un contrato de seguro contra incendios. No todas las coberturas son instrumentos financieros: un productor que exporta a otro país, por ejemplo, puede cubrir su riesgo de divisa cuando vende vinculando sus gastos con la divisa deseada.
    puede leer más aquí

  • Todas las cosas que necesitamos del servidor deben ser llamadas por la función MarketInfo (símbolo string, tipo int). Esta función nos permite llamar a cualquier dato más allá de los datos que aparecen en la ventana del gráfico activa. Esto también nos permite enviar cualquier tipo de orden de cualquier símbolo más allá del símbolo que es mostrado activamente en la ventana del gráfico activa. Y esto nos puede permitir hacer una cobertura de 2 símbolos fácilmente. Gracias a dios y a los miembros del equipo de MT4, esto ayuda mucho.

  • Algo necesario en las coberturas es la correlación entre los 2 símbolos de monitorización que pueden encontrarse con algunas funciones pequeñas que se mostrarán a continuación.

    La correlación, en el mundo financiero, es la medición estadística de la relación entre dos valores bursátiles. El coeficiente de correlación varía entre -1 y +1. Una correlación de +1 implica que los dos pares de divisas se moverán en la misma dirección el 100 % del tiempo. Una correlación de -1 implica que los dos pares de divisas se moverán en dirección opuesta el 100 % del tiempo. Una correlación cero implica que la relación entre los pares de divisas es completamente aleatoria. Puede leer más aquí


Todo lo anterior son cosas simples que los inversores de riesgo que usan asesores expertos en MT4 necesitan saber. Ahora podemos empezar a realizar una cobertura para un asesor experto.



Creación paso a paso del código de una cobertura para un asesor experto

Paso 1: Los parámetros de entrada

Antes de comenzar a escribir el asesor experto de cobertura, necesitamos elegir 2 símbolos correlacionados, es decir:

En este artículo elegiré mi propio par de cobertura favorito que es el EURJPY y GBPJPY. Siempre se mueve de la misma forma, más fácilmente para establecer el tipo de orden de cobertura. Vamos a comenzar. Para comenzar a crear el asesor experto de cobertura, vamos a conocer las variables de entrada siguientes.

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

Paso 2: La declaración de la variable

A continuación se muestran las variables usadas en este asesor experto y solo explicaré la variable necesaria para comprender cómo funciona el asesor experto.


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

Paso 3: Obtener todos los parámetros estáticos necesarios

Ahora vamos a especificar algunos valores estáticos que serán declarados en la parte 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); 
  }

Paso 4: Las funciones útiles

Antes de entrar en la parte divertida estamos esperando la función "start()", vamos a comenzar con las funciones usadas en este asesor experto. Pero, por favor, recuerde que todas las funciones quedarán fuera de la función start().


1. La función de correlación

Primero, necesitamos comenzar con las funciones de cálculo de la correlación. Las funciones siguientes fueron aplicadas por un hombre que dio el indicador de correlación gratuito (igorad2004@list.ru) y yo los modifiqué para facilitar el uso en este asesor experto. No necesitaremos llamar más al valor de correlación desde fuera del indicador. ¿Buena 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)); 
  } 
//+------------------------------------------------------------------+

La variable CorPeriod será externa como variable de entrada para permitirnos hacer el ajuste. Cuando queremos calcular la correlación entre 2 símbolos, llamamos a la función Cor(string base,string hedge) de esta forma Cor(EURJPY,GBPJPY). Es fácil, ¿verdad?


2. La función "enviar la cobertura"

Creo que es más fácil gestionar cómo podemos enviar las órdenes de cobertura creando la función SendH siguiente.

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

Puede leer más sobre la función OrderSend aquí.

Esta función ErrorDescription(GetLastError()) anterior permite que nuestro asesor experto nos diga cuál es el error que se ha producido cuando estaba operando la función de trading. Para usarla, necesitamos incluir el archivo "stdlib.mqh" introduciendo un código como este:

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

Y para usarla, tan solo llamamos a la función "ErrorDescription()" como mostramos anteriormente.


3. La función "cerrar la cobertura"

Aparte de enviar las órdenes, también necesitamos una función para cerrar todas las órdenes de cobertura cuando estas llegan al beneficio que esperamos. Y aquí está:

//+------------------------------------------------------------------+
//|  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 función solo cerrará las órdenes con el mismo número mágico, lo que significa que no hará que las órdenes de cobertura interfieran con otros números mágicos. No es algo de lo que tengamos que preocuparnos. Antes de usar esa función de cierre, necesitamos definir "cuánto tenemos ahora" usando la función siguiente.


4. Encontrar la función de beneficio 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); 
  } 
//+------------------------------------------------------------------+


Al igual que con la función de cierre, para conocer el beneficio de la cobertura, necesitamos controlar solo las órdenes con el mismo número mágico para cerrarlas correctamente. Para usarlas, introducimos un código como este:

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

Todos los valores del beneficio se calculan en USD. De la línea anterior, cuando el beneficio general de las órdenes con el número mágico 318 es superior a 100 dólares, estas se cerrarán. Eso es todo. Para abrir las órdenes de cobertura necesitamos saber que no hay ninguna orden con el mismo símbolo y número mágico flotante en el momento que necesitamos enviar la cobertura. Esto puede ser definido por esta función.



5. Obtener la cantidad de posiciones 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); 
 
  } 
//+------------------------------------------------------------------+

Puede usarse de esta forma:

ExistPositions("GBPJPY",318)

Esta función nos devolverá "cuántas órdenes de GBPJPY con el número mágico 318 son flotantes" en el momento. Una función más para definir el tipo de orden flotante.


6. Encontrar el tipo de orden de la posición específica existente

//+------------------------------------------------------------------+  
//| 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 función devuelve el valor entero del tipo de orden para el símbolo y el número mágico especificados que son flotantes en el momento. Si la orden flotante de GBPJPY es OP-BUY, el valor devuelto es "0". Esta función no solo trabaja junto con la función de trading. También trabaja con una función para mostrar el estado actual de la cobertura. Esta función se llama "OP2Str".



7. Mostrar el estado del trading

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

No hay mucho que decir. Creo que ya se ve cómo funciona.


8. Cerrar todos los tipos específicos de órdenes

Una función más para cerrar cualquier orden individual directamente, en caso de error, cuando se envía o se cierra la 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); 
  }

Es decir, CloseScrap("GBPJPY",OP_BUY,318) : esta cerrará solo la flotante larga "GBPJPY" que tiene el número mágico 318. Es fácil. Una última función que hay que saber.



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


Nada de especial, esta función sirve para mostrar el estado booleano de algunos parámetros como el valor BlockOpening. Cuando establecemos en ella el valor verdadero, esta función devolverá "Yes" en nuestra pantalla. Devolverá "No" cuando lo establecemos el valor falso. Esas son todas las funciones que necesitamos. Ahora vamos a disfrutar codificando el proceso de cobertura.


Paso 5: El núcleo del asesor experto

Empiece con esto primero:

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

Luego especifique el rango de correlación.

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;

Luego defina la forma de cobertura (esto es solo un ejemplo), en este artículo seleccionaré el estilo de trading por el valor del swap, luego solo operaré de forma que pueda ganar el swap cada día.

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

Ahora es el momento de enviar la 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).";
      }
  }

Luego las cerramos cuando alcancen el beneficio esperado

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

Y algo más divertido: La parte ShowStatus.

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

Terminamos con el final de todo asesor experto.

 return(0);
}


Paso 6: Recopilándolo todo

Aquí puede ver qué aspecto tiene myHedge.mq4.

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

Conclusión

Este es solo un ejemplo de un sencillo asesor experto de cobertura. Necesitamos modificarlo para que se adapte a nuestro propio estilo de cobertura. Estoy seguro que hay por ahí muchos estilos de cobertura. Y, por favor, recuerde que este tipo de asesores expertos no pueden probarse en el probador de estrategias debido a su propio límite. Necesita probarlo en tiempo real. A continuación se muestra el resultado del ejemplo de un asesor experto de cobertura.


Y la función ShowStatus será así:

Espero que disfrute con mi artículo y espero realmente que le ayude a crear su propio asesor experto de cobertura.