Mira cómo descargar robots gratis
¡Búscanos en Facebook!
Pon "Me gusta" y sigue las noticias
¿Es interesante este script?
Deje un enlace a él, ¡qué los demás también lo valoren!
¿Le ha gustado el script?
Evalúe su trabajo en el terminal MetaTrader 5
Asesores Expertos

MACD Sample - Asesor Experto para MetaTrader 5

Publicado por:
MetaQuotes
Visualizaciones:
4976
Ranking:
(51)
Publicado:
2014.06.09 13:21
Actualizado:
2016.11.22 07:33
macd_sample.mq5 (17.98 KB) ver
¿Necesita un robot o indicador basado en este código? Solicítelo en la bolsa freelance Pasar a la bolsa

El asesor MACD Sample está incluido dentro del suministro estándar del terminal de cliente MetaTrader 5 y supone un ejemplo de asesor que comercia con la ayuda del indicador MACD.

El archivo del asesor MACD Sample.mq5 se encuentra en la carpeta: "catálogo_de_datos_del_terminal\MQL5\Experts\Examples\MACD\". Este asesor supone un claro ejemplo del uso del enfoque orientado a objetos a la hora de desarrollar los asesores.

Vamos a echar un vistazo con más detalle a la estructura de este asesor y su principio de funcionamiento.


1. Propiedades del asesor

1.1. Propiedades del asesor

//+------------------------------------------------------------------+
//|                                                  MACD Sample.mq5 |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2009-2013, MetaQuotes Software Corp."
#property link        "https://www.mql5.com"
#property version     "5.20"
#property description "It is important to make sure that the expert works with a normal"
#property description "chart and the user did not make any mistakes setting input"
#property description "variables (Lots, TakeProfit, TrailingStop) in our case,"
#property description "we check TakeProfit on a chart of more than 2*trend_period bars"

Las primeras 5 líneas contienen los comentarios, las siguientes 7 establecen las propiedades del programa MQL5 (copyright, link, version, description) con la ayuda de las directivas del procesador #property.

Al iniciar el asesor, se mostrarán en la pestaña "General":

Asesor MACD Sample

Figura 1. Parámetros generales del asesor MACD Sample

1.2. Archivos contenidos

A continuación, con ayuda de la directiva #include continuamos con la indicación al compilador sobre la necesidad de incluir los archivos que contengan las clases comerciales de la Biblioteca estándar:

  • Trade.mqh (CTrade - es la clase para la realización de operaciones comerciales);
  • SymbolInfo.mqh (CSymbolInfo - es la clase para trabajar con las propiedades del instrumento comercial);
  • PositionInfo.mqh (CPositionInfo - es la clase para trabajar con las propiedades de una posición abierta);
  • AccountInfo.mqh (CAccountInfo - es la clase para trabajar con las propiedades de la cuenta comercial).
//--- archivos contenidos 
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\AccountInfo.mqh>

Los ejemplares de las clases correspondientes, en lo sucesivo se utilizan como variables-miembros de la clase CExpert (apartado 3).

1.3. Parámetros de entrada

Después de esto se indican los tipos, denominaciones, valores por defecto y comentarios cuyas funciones se muestran en la fig. 2.

//--- parámetros de entrada del asesor
input double InpLots          =0.1; // Lots
input int    InpTakeProfit    =50;  // Take Profit (in pips)
input int    InpTrailingStop  =30;  // Trailing Stop Level (in pips)
input int    InpMACDOpenLevel =3;   // MACD open level (in pips)
input int    InpMACDCloseLevel=2;   // MACD close level (in pips)
input int    InpMATrendPeriod =26;  // MA trend period

Preste atención al hecho de que las denominaciones de los parámetros de entrada tienen el prefijo "Inp". También debemos destacar que las variables globales tienen el prefijo "Ext". Semejante enfoque respecto a la denominación de las variables simplifica el trabajo al usar una gran cantidad de variables diferentes.

InpLots - es el volumen comercial, los parámetros InpTakeProfit y InpTrailingStop determinan los niveles de Take Profit y Trailing Stop,

El texto indicado en los comentarios en la línea del parámetro de entrada, junto a los valores por defecto, se muestra en la pentaña "Parámetros", en lugar de la denominación del parámetro de entrada:

Figura 2. Parámetros de entrada del asesor MACD Sample

Figura 2. Parámetros de entrada del asesor MACD Sample


1.4. Variables globales

Después de esto se anuncia la variable global ExtTimeOut, que se usará para controlar el tiempo de ejecución de las operaciones comerciales.

int ExtTimeOut=10; // tiempo (en segundos) entre operaciones comerciales

Tras anunciar la clase CSampleExpert en la línea 76 se anuncia otra variable global: ExtExpert - es un ejemplar de la clase CSampleExpert:

//--- variable global ExtExpert
CSampleExpert ExtExpert;

El objeto ExtExpert (ejemplar de la clase CSampleExpert) contiene la base lógica de la estrategia comercial (apartado 3).


2. Funciones de procesamiento de eventos

Funciones de procesamiento de eventos

2.1. Función de inicialización OnInit()

La función OnInit() se llama una vez, al iniciar por primera vez el asesor. Al procesar el evento OnInit() normalmente se realiza la preparación del asesor para el trabajo: se comprueba la corrección de los parámetros de entrada, se inicializan los indicadores, las variables, etc. En caso de errores críticos que hagan inútil cualquier trabajo posterior, se usa la salida de la función con el código de retorno INIT_FAILED.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//--- inicialización y creación de todos los objetos necesarios
   if(!ExtExpert.Init())
      return(INIT_FAILED);
//--- la inicialización ha tenido éxito
   return(INIT_SUCCEEDED);
  }

En este caso se invoca el método Init() del objeto ExtExpert, que retorna true o false, dependiendo del éxito a la hora de preparar todos los objetos necesarios para el funcionamiento (más información en el apartado 3.4). En caso de error se realiza la salida de la función OnInit() con el código de retorno INIT_FAILED este es el método correcto de finalizar el trabajo con el asesor/indicador en caso de que la inicialización no tenga éxito.


2.2. Función OnTick()

La función OnTick() se invoca cada vez que se reciba una nueva cotización según el símbolo del gráfico en el que se haya iniciado el asesor.

//+------------------------------------------------------------------+
//| Expert new tick handling function                                |
//+------------------------------------------------------------------+
void OnTick(void)
  {
   static datetime limit_time=0; // almacena la última hora de llamada + timeout
//--- no lleva a cabo el trabajo, si no ha pasado el tiempo indicado
   if(TimeCurrent()>=limit_time)
     {
      //--- comprobación de datos
      if(Bars(Symbol(),Period())>2*InpMATrendPeriod)
        {
         //--- tras la llamada del método Processing() aumentamos el valor limit_time en ExtTimeOut 
         if(ExtExpert.Processing())
            limit_time=TimeCurrent()+ExtTimeOut;
        }
     }
  }

En el desarrollo del evento OnTick() está implementado un mecanismo de llamada periódica del método ExtExpert.Processing(), que se utiliza para el análisis del mercado y el comportamiento de las operaciones comerciales al cumplirse las condiciones comerciales.

El intervalo de tiempo entre llamadas se establece con el valor del parámetro de entrada ExtTimeOut.


2.3. Función de desinicialización OnDeInit()

La función de desinicialización OnDeInit() se llama al eliminarse el asesor del gráfico. Si en el proceso de funcionamiento el programa distribuye objetos gráficos, estos pueden ser quitados del gráfico.

En este ejemplo, no tenemos la función de desinicialización, por lo que no se produce acción alguna.


3. Clase CSampleExpert

3.1. Clase CSampleExpert

//+------------------------------------------------------------------+
//| Clase del asesor MACD Sample                                      |
//+------------------------------------------------------------------+
class CSampleExpert
  {
protected: 
   //--- los protected variables-miembros de clase están disponibles dentro de los métodos de clase 
   double            m_adjusted_point;             // multiplicador de cotizaciones de 3/5 dígitos
   CTrade            m_trade;                      // ejemplar de clase CTrade
   CSymbolInfo       m_symbol;                     // ejemplar de clase CSymbolInfo
   CPositionInfo     m_position;                   // ejemplar de clase CPositionInfo
   CAccountInfo      m_account;                    // ejemplar de clase CAccountInfo
   //--- handles de las cotizaciones
   int               m_handle_macd;                // handle del indicador MACD
   int               m_handle_ema;                 // handle del indicador Moving Average
   //--- búfers de indicador
   double            m_buff_MACD_main[];           // búfer de la línea principal del indicador MACD
   double            m_buff_MACD_signal[];         // búfer de la línea de señal del indicador MACD
   double            m_buff_EMA[];                 // búfer del indicador EMA
   //--- valores actuales de los indicadores
   double            m_macd_current;
   double            m_macd_previous;
   double            m_signal_current;
   double            m_signal_previous;
   double            m_ema_current;
   double            m_ema_previous;
   //--- niveles (en puntos estándar)
   double            m_macd_open_level;
   double            m_macd_close_level;
   double            m_traling_stop;
   double            m_take_profit;

public: 
   //--- constructor
                     CSampleExpert(void);
   //--- destructor
                     ~CSampleExpert(void);
   //--- los métodos public están accesibles desde fuera, pueden ser llamados desde fuera de la clase 
   //--- método de inicialización
   bool              Init(void);
   //--- método de desinicialización
   void              Deinit(void);
   //--- método de procesamiento
   bool              Processing(void);
protected: 
   //--- los métodos protected están accesibles dentro de los métodos de clase 
   bool              InitCheckParameters(const int digits_adjust);
   bool              InitIndicators(void);
   bool              LongClosed(void);
   bool              ShortClosed(void);
   bool              LongModified(void);
   bool              ShortModified(void);
   bool              LongOpened(void);
   bool              ShortOpened(void);
  };

La clase del asesor contiene la declaración de las variables (miembros de clase) y funciones (métodos de clase).

Para que se pueda trabajar más cómodamente, todas las variables-miembros de la clase contienen el prefijo "m_" (member), que indica que la variable dada es miembro de la clase. Antes de declarar la variable o el método, se indica su tipo (o el retorno del valor para las funciones).

La visibilidad de las variables y los métodos-miembros se establece con ayuda de los modificadores de acceso. En la clase CSampleExpert se utilizan los modificadores protected y public. Todas las variables y métodos declarados en la sección public, son públicos y accesibles desde fuera. La clase CSampleExpert tiene 5 métodos de ese tipo:

  1. CSampleExpert(void) - es el constructor  (se llama automáticamente al crear un ejemplar de clase);
  2. ~CSampleExpert(void) - es el desctructor (se llama automáticamente al eliminar un ejemplar de clase);
  3. bool Init(void) - es el método de inicialización en el que se realiza la preparación de todos los datos necesarios para el trabajo;
  4. void Deinit(void) - es el método de desinicialización;
  5. bool Processing(void) - es el método de procesamiento.

Las variables-miembros de la clase CSampleExpert que sean anunciadas con el modificador de acceso protected, sólo estarán accesibles dentro de los métodos de la clase CSampleExpert (y sus sucesores).

  1. double           m_adjusted_point - es una variable-multiplicador para trabajar correctamente con cotizaciones de 3/5 dígitos;
  2. CTrade          m_trade - es un ejemplar de clase СTrade;
  3. CSymbolInfo  m_symbol - es un ejemplar de clase CSymbolInfo;
  4. CPositionInfo  m_position - es un ejemplar de clase СPositionInfo;
  5. CAccountInfo  m_account - es un ejemplar de clase CAccountInfo;
  6. int                 m_handle_macd - es la variable para almacenar el valor del handle del indicador MACD.
  7. int                 m_handle_ema - es la variable para almacenar el valor del handle del indicador EMA;
  8. double           m_buff_MACD_main[] - es una matriz dinámica de valores del tipo double, se utiliza para solicitar los valores de la línea principal del indicador MACD;
  9. double           m_buff_MACD_signal[] - es una matriz dinámica de valores del tipo double, se utiliza para solicitar los valores de la línea de señal del indicador MACD;
  10. double           m_buff_EMA[] - es una matriz dinámica de valores del tipo double, se utiliza para solicitar los valores del indicador EMA;
  11. double           m_macd_current - se usa para guardar el valor actual de la línea principal del indicador MACD;
  12. double           m_macd_previous - se usa para guardar el valor anterior de la línea principal del indicador MACD;
  13. double           m_signal_current - se usa para guardar el valor actual de la línea de señal del indicador MACD;
  14. double           m_signal_previous - se usa para guardar el valor anterior de la línea señal del indicador MACD;
  15. double           m_ema_current - se usa para guardar el valor actual del indicador EMA;
  16. double           m_ema_previous se usa para guardar el valor anterior del indicador EMA;
  17. double           m_macd_open_level,
  18. double           m_macd_close_level,
  19. double           m_traling_stop,
  20. double           m_take_profit - se usa para guardar los valores de los niveles de precio (establecidos en los parámetros de entrada) teniendo en cuenta el multiplicador m_adjusted_point.

Métodos de clase CSampleExpert, declarados con el modificador de acceso protected:

  1. bool  InitCheckParameters(const int digits_adjust) - comprueba la corrección de los parámetros de entrada y la inicialización de los parámetros de funcionamiento del experto;
  2. bool  InitIndicators(void) - inicialización (creación) de los indicadores MACD y Moving Average;
  3. bool  LongClosed(void) - retorna true (y cierra la posición larga abierta) al cumplirse las condiciones de cierre de una posición larga;
  4. bool  ShortClosed(void) - retorna true (y cierra la posición corta abierta) al cumplirse las condiciones de cierre de una posición corta;
  5. bool  LongModified(void) - retorna true (y modifica el precio Stop Loss) al cumplirse las condiciones de cambio de nivel Stop Loss de una posición larga abierta;
  6. bool  ShortModified(void) - retorna true (y modifica el precio Stop Loss) al cumplirse las condiciones de cambio de nivel Stop Loss de una posición corta abierta;
  7. bool  LongOpened(void) - retorna true (y abre una posición larga) al cumplirse las condiciones de apertura de una posición larga;
  8. bool  ShortOpened(void) - retorna true (y abre una posición corta) al cumplirse las condiciones de apertura de una posición corta.


3.2. Constructor de clase CSampleExpert

//+------------------------------------------------------------------+
//| Constructor de clase CSampleExpert                                 |
//+------------------------------------------------------------------+
CSampleExpert::CSampleExpert(void) : m_adjusted_point(0),
                                     m_handle_macd(INVALID_HANDLE),
                                     m_handle_ema(INVALID_HANDLE),
                                     m_macd_current(0),
                                     m_macd_previous(0),
                                     m_signal_current(0),
                                     m_signal_previous(0),
                                     m_ema_current(0),
                                     m_ema_previous(0),
                                     m_macd_open_level(0),
                                     m_macd_close_level(0),
                                     m_traling_stop(0),
                                     m_take_profit(0)
  {
   ArraySetAsSeries(m_buff_MACD_main,true);
   ArraySetAsSeries(m_buff_MACD_signal,true);
   ArraySetAsSeries(m_buff_EMA,true);
  }

El constructor de clase se invoca de manera automática al crear un objeto-ejemplar de clase. Al llamarlo se establecen los valores por defecto (entre paréntesis) para las variables-miembros y se establece la dirección de indexación como en las series temporales para las matrices m_buff_MACD_main[], m_buff_MACD_signal[], m_buff_EMA[].


3.3. Destructor de clase CSampleExpert

//+------------------------------------------------------------------+
//| Destructor de clase CSampleExpert                                  |
//+------------------------------------------------------------------+
CSampleExpert::~CSampleExpert(void)
  {
  }

El destructor de clase CSampleExpert no contiene código.


3.4. Método Init de clase CSampleExpert

//+------------------------------------------------------------------+
//| Inicialización y comprobación de la corrección de los parámteros de entrada         |
//+------------------------------------------------------------------+
bool CSampleExpert::Init(void)
  {
//--- establecer las propiedades generales
   m_symbol.Name(Symbol());              // instrumento
   m_trade.SetExpertMagicNumber(12345);  // magic
//--- cálculo de las cotizaciones de 3/5 dígitos
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;
//--- establecer los valores de los niveles, teniendo en cuenta el multiplicador m_adjusted_point
   m_macd_open_level =InpMACDOpenLevel*m_adjusted_point;
   m_macd_close_level=InpMACDCloseLevel*m_adjusted_point;
   m_traling_stop    =InpTrailingStop*m_adjusted_point;
   m_take_profit     =InpTakeProfit*m_adjusted_point;
//--- establecer el deslizamiento en 3 puntos
   m_trade.SetDeviationInPoints(3*digits_adjust);
//---
   if(!InitCheckParameters(digits_adjust))
      return(false);
   if(!InitIndicators())
      return(false);
//--- finalizado con éxito
   return(true);
  }

En el método Init() se lleva a cabo la inicialización de las variables de miembros-clase y se comprueba la corrección de los parámetros de entrada.

Al invocar el método Name() del objeto m_symbol (ejemplar de clase CSymbolInfo) se establece la denominación del instrumento en el que se inicia el asesor, después se invoca el método SetExpertMagicNumber(), que establece el valor del identificador del experto (magic) para el objeto m_trade (se utilizará al efectuar operaciones comerciales). Tras esto, con ayuda del método Digits() se solicita la cantidad de dígitos después de la coma del símbolo, y en caso necesario, la corrección de los valores de nivel.

A continuación se invoca el método SetDeviationInPoints() del objeto m_trade, en el que se establece la magnitud del deslizamiento permisible al efectuar operaciones comerciales.


3.5. Método InitCheckParameters de clase CSampleExpert

//+------------------------------------------------------------------+
//| Checking for input parameters                                    |
//+------------------------------------------------------------------+
bool CSampleExpert::InitCheckParameters(const int digits_adjust)
  {
//--- comprobando la corrección del nivel Take Profit
   if(InpTakeProfit*digits_adjust<m_symbol.StopsLevel())
     {
      printf("Take Profit must be greater than %d",m_symbol.StopsLevel());
      return(false);
     }
//--- comprobando la corrección del nivel Trailing Stop
   if(InpTrailingStop*digits_adjust<m_symbol.StopsLevel())
     {
      printf("Trailing Stop must be greater than %d",m_symbol.StopsLevel());
      return(false);
     }
//--- comprobando la corrección del volumen comercial
   if(InpLots<m_symbol.LotsMin() || InpLots>m_symbol.LotsMax())
     {
      printf("Lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
      return(false);
     }
   if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10)
     {
      printf("Lots amount is not corresponding with lot step %f",m_symbol.LotsStep());
      return(false);
     }
//--- mostramos una advertencia si Take Profit<=Trailing Stop
   if(InpTakeProfit<=InpTrailingStop)
      printf("Warning: Trailing Stop must be less than Take Profit");
//--- finalizado con éxito
   return(true);
  }

En el método InitCheckParameters() se comprueba la corrección de los parámetros de entrada del asesor. Si algún parámetro tiene un valor inadmisible, entonces se muestra el mensaje correspondiente, y la función retorna false.


3.6. Método InitIndicators() de clase CSampleExpert

//+------------------------------------------------------------------+
//| Método de inicialización de indicadores                                  |
//+------------------------------------------------------------------+
bool CSampleExpert::InitIndicators(void)
  {
//--- creación del indicador MACD
   if(m_handle_macd==INVALID_HANDLE)
      if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE)
        {
         printf("Error creating MACD indicator");
         return(false);
        }
//--- creación del indicador EMA
   if(m_handle_ema==INVALID_HANDLE)
      if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE)
        {
         printf("Error creating EMA indicator");
         return(false);
        }
//--- finalizado con éxito
   return(true);
  }

En el método InitIndicators() se comprueban los valores iniciales de las variables m_handle_macd y m_handle_ema (deben ser iguales a INVALID_HANDLE, ya que están inicializadas en el constructor) y se crean los indicadores técnicos MACD y Moving Average (con ayuda de las funciones iMACD y iMA). Si se finaliza con éxito, la función retorna true, y los handles de los indicadores se almacenan en los miembros de la clase m_handle_macd y m_handle_ema.

Los handles de los indicadores creados después serán utilizados para comprobar la cantidad de datos calculados (BarsCalculated) y obtener los valores numéricos (CopyBuffer) de los datos de los indicadores en el método Processing().


3.7. Método LongClosed() de clase CSampleExpert

//+------------------------------------------------------------------+
//| Comprobación de las condiciones de cierre de una posición larga                        |
//+------------------------------------------------------------------+
bool CSampleExpert::LongClosed(void)
  {
   bool res=false;
//--- ¿Hay que cerrar una posición?
   if(m_macd_current>0)
      if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous)
         if(m_macd_current>m_macd_close_level)
           {
            //--- cierre de posición
            if(m_trade.PositionClose(Symbol()))
               printf("Long position by %s to be closed",Symbol());
            else
               printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment());
            res=true;
           }
//--- retornamos el resultado
   return(res);
  }

El método LongClosed() retorna true (y cierra la posición larga abierta) al cumplirse las condiciones de cierre de una posición larga:

  1. m_macd_current>0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por encima de la línea de cero);
  2. m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal desde arriba hacia abajo.
  3. m_macd_current>m_macd_close_level - el valor actual de la línea principal del indicador MACD es mayor que m_macd_close_level.


3.8. Método ShortClosed() de clase CSampleExpert

//+------------------------------------------------------------------+
//| Comprobación de las condiciones de cierre de una posición corta                       |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortClosed(void)
  {
   bool res=false;
//--- ¿hay que cerrar la posición?
   if(m_macd_current<0)
      if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous)
         if(MathAbs(m_macd_current)>m_macd_close_level)
           {
            //--- cierre de posición
            if(m_trade.PositionClose(Symbol()))
               printf("Short position by %s to be closed",Symbol());
            else
               printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment());
            res=true;
           }
//--- retornamos resultado
   return(res);
  }

El método ShortClosed() retorna true (y cierra la posición corta abierta) al cumplir las condiciones de cierre de una posición corta:

  1. m_macd_current<0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por debajo de la línea cero).
  2. m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal de abajo hacia arriba.
  3. MathAbs(m_macd_current)>m_macd_close_level - el valor actual de la línea principal del indicador MACD según el módulo es mayor a m_macd_close_level.


3.9. Método LongModified() de clase CSampleExpert

//+------------------------------------------------------------------+
//| Comprobación de las condiciones de modificación de la posición larga                     |
//+------------------------------------------------------------------+
bool CSampleExpert::LongModified(void)
  {
   bool res=false;
//--- comprobación de la necesidad de Trailing Stop 
   if(InpTrailingStop>0)
     {
      if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop)
        {
         double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits());
         double tp=m_position.TakeProfit();
         if(m_position.StopLoss()<sl || m_position.StopLoss()==0.0)
           {
            //--- modificación de parámetros de la posición Stop Loss y Take Profit
            if(m_trade.PositionModify(Symbol(),sl,tp))
               printf("Long position by %s to be modified",Symbol());
            else
              {
               printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment());
               printf("Modify parameters : SL=%f,TP=%f",sl,tp);
              }
            res=true;
           }
        }
     }
//--- retornamos resultado
   return(res);
  }

El método LongModified() retorna true (y cambia el valor del parámetro de la posición Stop Loss) al cumplir las condiciones de la modificación de la posición larga. Si el valor del parámetro de entrada es InpTrailingStop>0, entonces se realiza la comprobación sobre el paso del precio por los puntos InpTrailingStop desde el precio de apertura en dirección a la posición. A continuación se calcula el nuevo valor del nivel Stop Loss y se modifica el parámetro Stop Loss de la posición abierta.


3.10. Método ShortModified de clase CSampleExpert

//+------------------------------------------------------------------+
//| Comprobación de las condiciones de modificación de la posición corta                    |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortModified(void)
  {
   bool   res=false;
//--- comprobación de la necesidad de trailing stop
   if(InpTrailingStop>0)
     {
      if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop))
        {
         double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits());
         double tp=m_position.TakeProfit();
         if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0)
           {
            //--- modificación de los parámetros de la posición Stop Loss y Take Profit
            if(m_trade.PositionModify(Symbol(),sl,tp))
               printf("Short position by %s to be modified",Symbol());
            else
              {
               printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment());
               printf("Modify parameters : SL=%f,TP=%f",sl,tp);
              }
            res=true;
           }
        }
     }
//--- retornamos resultado
   return(res);
  }

El método ShotModified() retorna true (y cambia el valor del parámetro de la posición Stop Loss) al cumplir las condiciones de modificación de la posición corta. Si el valor del parámetro de entrada es InpTrailingStop>0, entonces se realiza la comprobación sobre el paso del precio por los puntos InpTrailingStop desde el precio de apertura en dirección a la posición. A continuación se calcula el nuevo valor del nivel Stop Loss y se modifica el parámetro Stop Loss de la posición abierta.


3.11. Método LongOpened() de clase CSampleExpert

//+------------------------------------------------------------------+
//| Check for long position opening                                  |
//+------------------------------------------------------------------+
bool CSampleExpert::LongOpened(void)
  {
   bool res=false;
//--- comprobación de las condiciones de apertura de una posición larga
   if(m_macd_current<0)
      if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous)
         if(MathAbs(m_macd_current)>(m_macd_open_level) && m_ema_current>m_ema_previous)
           {
            double price=m_symbol.Ask();
            double tp   =m_symbol.Bid()+m_take_profit;
            //--- comprobación de la presencia de margen libre
            if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0)
               printf("We have no money. Free Margin = %f",m_account.FreeMargin());
            else
              {
               //--- apertura de posición larga
               if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp))
                  printf("Position by %s to be opened",Symbol());
               else
                 {
                  printf("Error opening BUY position by %s : '%s'",Symbol(),m_trade.ResultComment());
                  printf("Open parameters : price=%f,TP=%f",price,tp);
                 }
              }
            res=true;
           }
//--- retornamos resultado
   return(res);
  }

El método LongOpened() retorna true (y abre una posición larga) en caso de que se cumplan las condiciones para la apertura de posición en la compra:

  1. m_macd_current<0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por debajo de la línea del cero);
  2. m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal de abajo hacia arriba;
  3. MathAbs(m_macd_current)>m_macd_open_level - el valor actual de la línea principal del indicador MACD según el módulo es mayor que m_macd_open_level;
  4. m_ema_current>m_ema_previous - ema crece.

Al cumplirse todas las condiciones se comprueba que haya margen suficiente (se usa el método FreeMarginCheck() de clase CAccountInfo de la Biblioteca estándar) y se abre una posición larga con ayuda del método PositionOpen() de clase CTrade.


3.12. Método ShortOpened de clase CSampleExpert

//+------------------------------------------------------------------+
//| Check for short position opening                                 |
//+------------------------------------------------------------------+
bool CSampleExpert::ShortOpened(void)
  {
   bool res=false;
//--- comprobación de las condiciones de apertura de posición corta
   if(m_macd_current>0)
      if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous)
         if(m_macd_current>(m_macd_open_level) && m_ema_current<m_ema_previous)
           {
            double price=m_symbol.Bid();
            double tp   =m_symbol.Ask()-m_take_profit;
            //--- comprobamos que haya margen suficiente
            if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_SELL,InpLots,price)<0.0)
               printf("We have no money. Free Margin = %f",m_account.FreeMargin());
            else
              {
               //--- apertura de una posición corta
               if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,InpLots,price,0.0,tp))
                  printf("Position by %s to be opened",Symbol());
               else
                 {
                  printf("Error opening SELL position by %s : '%s'",Symbol(),m_trade.ResultComment());
                  printf("Open parameters : price=%f,TP=%f",price,tp);
                 }
              }
            res=true;
           }
//--- retornamos resultado
   return(res);
  }

El método ShortOpened() retorna true (y abra una posición corta) en caso de que se cumplan las condiciones de apertura de posición para la venta:

  1. m_macd_current>0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por encima de la línea de cero);
  2. m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal de arriba hacia abajo;
  3. m_macd_current>m_macd_open_level - el valor actual de la línea principal del indicador MACD es mayor que m_macd_open_level;
  4. m_ema_current<m_ema_previous - ema cae.

Cuando se cumplen todas las condiciones se comprueba la presencia de margen suficiente de medios (se usa el método FreeMarginCheck() de clase CAccountInfo de la Biblioteca estándar) y se abre una posición corta con ayuda del método PositionOpen() de clase CTrade.


3.13 Método Processing() de clase CSampleExpert

//+------------------------------------------------------------------+
//| main function returns true if any position processed             |
//+------------------------------------------------------------------+
bool CSampleExpert::Processing(void)
  {
//--- actualización de cotizaciones
   if(!m_symbol.RefreshRates())
      return(false);
//--- actualización de los valores del indicador
   if(BarsCalculated(m_handle_macd)<2 || BarsCalculated(m_handle_ema)<2)
      return(false);
   if(CopyBuffer(m_handle_macd,0,0,2,m_buff_MACD_main)  !=2 ||
      CopyBuffer(m_handle_macd,1,0,2,m_buff_MACD_signal)!=2 ||
      CopyBuffer(m_handle_ema,0,0,2,m_buff_EMA)         !=2)
      return(false);
//--- para simplificar el trabajo con los indicadores y la velocidad de acceso
//--- los valores actuales de los indicadores se almacenan en las variables internas (miembros de clase)
   m_macd_current   =m_buff_MACD_main[0];
   m_macd_previous  =m_buff_MACD_main[1];
   m_signal_current =m_buff_MACD_signal[0];
   m_signal_previous=m_buff_MACD_signal[1];
   m_ema_current    =m_buff_EMA[0];
   m_ema_previous   =m_buff_EMA[1];
//--- es importante entrar correctamente en el mercado, pero es aún más importante salir correctamente
//--- primero comprobamos si hay alguna posición abierta
   if(m_position.Select(Symbol()))
     {
      if(m_position.PositionType()==POSITION_TYPE_BUY)
        {
         //--- si es necesario, intentamos cerrar o modificar la posición larga
         if(LongClosed())
            return(true);
         if(LongModified())
            return(true);
        }
      else
        {
         //--- si es necesario, intentamos cerrar o modificar la posición corta
         if(ShortClosed())
            return(true);
         if(ShortModified())
            return(true);
        }
     }
//--- no hay posiciones abiertas
   else
     {
      //--- comprobamos las condiciones y si es necesario abrimos una posición larga
      if(LongOpened())
         return(true);
      //--- comprobamos las condiciones y si es necesario abrimos una posición corta
      if(ShortOpened())
         return(true);
     }
//--- salimos sin procesar las posiciones
    return(false);
  }

El método Processing() de clase CSampleExpert es el método principal del asesor. La llamada del método Processing() se lleva a cabo durante el procesamiento del evento OnTick(), además se realiza el control del intervalo de tiempo (no inferior a los segundos de ExtTimeOut) entre las llamadas consecutivas de este método (apartado 2.2).

Con la llamada del método RefreshRates() de clase CSymbolInfo se lleva a cabo la actualización de las cotizaciones. Con la ayuda de la función BarsCalculated() se solicita la cantidad de barras para las que se han calculado los indicadores MACD y Moving Average (apartado 3.6.), si hay menos de 2 barras, entonces se produce la salida de la función y se retorna el valor false.

A continuación, con la llamada de la función CopyBuffer se lleva a cabo la solicitud de los dos últimos valores de los indicadores técnicos (de las líneas principal y de señal de MACD y los valores de Moving Average), si, además, la cantidad de datos copiados es inferior a dos, entonces se produce la salida de la función. Después, los valores de los indicadores de las matrices m_buff_MACD_main[], m_buff_MACD_signal[] y m_buff_EMA[] son copiados en las variables m_macd_current, m_macd_previous, m_signal_current, m_signal_previous, m_ema_current y m_ema_previous.

El siguiente paso es trabajar con la posición, este trabajo se lleva a cabo con la ayuda de la clase CPositionInfo de la Biblioteca estándar. Si la llamada del método Select() ha retornado true, esto significa que en el momento presente hay una posición abierta, su tipo se determina con la ayuda del método PositionType(). Después se realiza el trabajo correspondiente al tipo de posición abierta.


4. Simulación con datos históricos

Los mejores parámetros se pueden encontrar con ayuda del simulador de estrategias del terminal MetaTrader 5.

En la figura 3 se muestran los resultados de la simulación del asesor durante el año 2013 con los parámetros por defecto.

Figura 3. Resultados de la simulación con datos históricos del asesor MACD Sample

Figura 3. Resultados de la simulación con datos históricos del asesor MACD Sample

Conclusiones

El asesor MACD Sample, disponible en el terminal de cliente MetaTrader 5, supone un ejemplo del uso del enfoque orientado a objetos aplicado al desarrollo de asesores.


Traducción del ruso realizada por MetaQuotes Ltd
Artículo original: https://www.mql5.com/ru/code/2154

LOWEST_LOW_VALUE LOWEST_LOW_VALUE

El indicador muestra el valor mínimo del precio durante el periodo establecido en los parámetros de entrada.

HIGHEST_HIGH_VALUE HIGHEST_HIGH_VALUE

El indicador muestra el valor máximo del precio durante el periodo establecido en los parámetros de entrada.

HIGHEST_HIGH_VALUE_HTF HIGHEST_HIGH_VALUE_HTF

El indicador muestra el valor máximo del precio durante el periodo establecido en los parámetros de entrada del indicador, teniendo en cuenta el marco temporal en el que se lleva a cabo la búsqueda.

LOWEST_LOW_VALUE_HTF LOWEST_LOW_VALUE_HTF

El indicador muestra el valor mínimo del precio durante el periodo establecido en los parámetros de entrada del indicador, teniendo en cuenta el marco temporal en el que se lleva a cabo la búsqueda.