English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
MQL5 Wizard: Cómo crear un módulo de gestión de riesgo y dinero

MQL5 Wizard: Cómo crear un módulo de gestión de riesgo y dinero

MetaTrader 5Sistemas comerciales | 4 abril 2014, 11:43
1 598 0
MetaQuotes
MetaQuotes

Introducción

MetaTrader 5 proporciona una herramienta potente que le permite comprobar varios conceptos de trading. Se trata de la generación de Expert Advisors mediante MQL5 Wizard en función de estrategias de trading existentes.

Los Expert Advisors creados con MQL5 Wizard, se basan en cuatro pilares; cuatro clases base:

Figura 1. La estructura de la clase base CExpert

Figura 1. La estructura de la clase base CExpert

  1. La clase CExpert (o sus subclases) es el "motor" principal de un Expert Advisor. Una instancia de CExpert contiene una copia de cada clase: CExpertSignal, CExpertMoney y CExpertTrailing (o sus subclases):
  2. CExpertSignal es la base del generador de señales de trading. Una instancia de la clase derivada CExpertSignal, incluida en CExpert, proporciona un Expert Advisor con informaciones acerca de la posibilidad de entrar al mercado, los niveles de entrada y la colocación de las órdenes de protección, en función de unos algoritmos incorporados. El Expert Advisor decide si entra al mercado o no. Se describe la clase CExpertSignal y el modo de trabajar con ella con más detalle en el artículo "MQL5 Wizard: Cómo crear un módulo de señales de trading".
  3. La clase CExpertMoney es la base de los sistemas de gestión de dinero y de riesgo. Una instancia de la clase derivada CExpertMoney, incluida en CExpert, proporciona un Expert Advisor con informaciones acerca de los posibles volúmenes para la apertura de posiciones y la colocación de órdenes pendientes, en función de unos algoritmos incorporados. El Expert Advisor toma la decisión acerca del volumen.
  4. La clase CExpertTrailing es la base del sistema de soporte de las posiciones abiertas. Una instancia de la clase derivada CExpertTrailing, incluida en CExpert, proporciona un EA con informaciones acerca de modificar las órdenes de protección de la posición, en función de unos algoritmos incorporados. El Expert Advisor toma la decisión acerca de la modificación de órdenes. Se describirá la clase CExpertTrailing y el modo de trabajar con ella en un artículo aparte.

Además, los miembros de la clase CExpert son instancias de las siguientes clases:

  • CExpertTrade (para el trading)
  • CIndicators (para el control de los indicadores y las series temporales implicados en el funcionamiento del EA)
  • CSymbolInfo (para obtener informaciones acerca del instrumento)
  • CAccountInfo (para obtener informaciones acerca del estado de la cuenta de trading)
  • CPositionInfo (para obtener informaciones acerca de las posiciones)
  • COrderInfo (para obtener informaciones acerca de las órdenes pendientes)

De aquí en adelante, con "expert" nos referimos a una instancia de CExpert o de su subclase.

Se describirá la clase CExpert y el modo de trabajar con ella en un artículo aparte.


1. La clase base CExpertMoney

Como se ha mencionado anteriormente, la clase CExpertMoney es la base de los sistemas de gestión de dinero y de riesgo. Para comunicar con el "mundo exterior", la clase CExpertMoney dispone de una serie de métodos virtuales públicos:

Inicialización

 Descripción

virtual Init

La inicialización de la instancia de la clase proporciona la sincronización de los datos del módulo con los datos del EA.

Percent

Establecimiento del valor del parámetro "Porcentaje de riesgo"

virtual ValidationSettings

Validación de los parámetros establecidos

virtual InitIndicators

Creación e inicialización de todos los indicadores y series temporales que requiere el sistema de gestión de dinero y riesgo

Métodos para comprobar la necesidad de abrir/invertir/cerrar una posición

 

virtual CheckOpenLong

Determinar el volumen de apertura de una posición larga

virtual CheckOpenShort

Determinar el volumen de apertura de una posición corta

virtual CheckReverse

Determinar el volumen para invertir una posición

virtual CheckClose

Determinar la necesidad de cerrar una posición


Descripción de los métodos


1.1. Inicialización de los métodos

1.1.1 Init

Se llama al método Init() automáticamente justo después de añadir una instancia de clase al expert. Este método no requiere sobreescritura.

virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);

1.1.2 Percent

Se llama al método Percent() para configurar los parámetros correspondientes. Su valor puede estar entre 0.0 y 100.0 inclusive. El valor por defecto es 100.0. Este método no requiere sobreescritura.

void Percent(double percent);

1.1.3 ValidationSettings

Se llama al método ValidationSettings() a partir del expert justo después de configurar todos los parámetros. Si hay algún parámetro adicional de configuración, habrá que sobreescribir el método.

virtual bool ValidationSettings();

Si todas las opciones son válidas (se pueden usar), el método sobreescrito debe devolver true. Si por lo menos uno de los parámetros es incorrecto, debe devolver false (no puede seguir funcionando). El método sobreescrito debe llamar al método de la clase base con la comprobación del resultado.

La clase base CExpertMoney tiene el parámetro Percent, por lo que el método de la clase base, que lleva a cabo la validación del parámetro, devuelve true si el valor está dentro del rango permitido. De lo contrario, devuelve false.

1.1.4 InitIndicators

El método InitIndicators() implementa la creación e inicialización de todos los indicadores y series temporales indispensables. Se le llama desde el expert después de configurar todos los parámetros y confirmar que son correctos. Si el sistema de gestión de dinero usa por lo menos un indicador o serie temporal, habrá que sobreescribir el método.

virtual bool InitIndicators(CIndicators* indicators);

Hay que usar los métodos y/o series temporales con las clases adecuadas de la librería estándar. Se deben añadir los punteros de todos los indicadores y/o series temporales al conjunto de indicadores de un expert (un puntero que se le envía como un parámetro).

Si todas las operaciones con el indicador y/o serie temporal tienen éxito (su uso es viable), el método sobreescrito debe devolver true. Si falla al menos una operación con los indicadores y/o series temporales, el método tiene que devolver false (no puede seguir funcionando).

La clase base CExpertMoney no usa indicadores o series temporales, por tanto, el método de la clase base siempre devuelve true, sin llevar a cabo ninguna acción.

1.2. Métodos para determinar el volumen de una posición

1.2.1 CheckOpenLong

El método CheckOpenLong() calcula el volumen para la apertura de una posición larga. Se le llama mediante un expert para determinar el volumen necesario para la apertura de una posición larga. Si espera que se calcule el volumen de apertura de una posición larga mediante un algoritmo distinto al que está implementado en la clase base, habrá que sobreescribir el método.

\virtual double CheckOpenLong(double price, double sl);

El método tiene que implementar el algoritmo de cálculo del volumen para la apertura de una posición larga. El método tiene que devolver el volumen calculado.

La clase base CExpertMoney no dispone de un algoritmo incorporado para calcular el volumen de apertura de las posiciones largas. El método de la clase base devuelve siempre el mínimo volumen posible para un instrumento financiero.

1.2.2 CheckOpenShort

El método CheckOpenShort() calcula el volumen para la apertura de una posición corta. Se le llama mediante un expert para determinar el volumen necesario para la apertura de una posición corta. Si espera que se calcule el volumen de apertura de una posición corta mediante un algoritmo distinto al que está implementado en la clase base, habrá que sobreescribir el método. 

virtual double CheckOpenShort(double price, double sl);

El método tiene que implementar el algoritmo de cálculo del volumen para la apertura de una posición corta. El método tiene que devolver el volumen calculado.

La clase base CExpertMoney no dispone de un algoritmo incorporado para calcular el volumen de apertura de las posiciones cortas. El método de la clase base devuelve siempre el mínimo volumen posible para un instrumento financiero.

1.2.3 CheckReverse

El método CheckReverse() calcula el volumen para la inversión de una posición. Se le llama mediante un expert para determinar el volumen de la operación de trading para la inversión de la posición. Si espera que se calcule el volumen de inversión de una posición mediante un algoritmo distinto al que está implementado en la clase base (p. ej., inversión con volumen doble), habrá que sobreescribir el método. 

virtual double CheckReverse(CPositionInfo* position, double sl);

El método tiene que implementar el algoritmo para calcular el volumen de inversión de una posición, cuya información se puede conseguir mediante el puntero position. El método tiene que devolver el volumen calculado para la inversión de la posición.

La clase base CExpertMoney dispone del siguiente algoritmo para la inversión de la posición; para invertir la posición de modo que el resultado sea una posición opuesta con el mínimo volumen posible.

1.2.4 CheckClose

El método CheckClose() comprueba si es necesario cerrar una posición (en términos de gestión de dinero y gestión de riesgo) Se le llama mediante un expert para determinar si es necesario cerrar una posición. Si espera que se cierre una posición mediante un algoritmo distinto al que está implementado en la clase base (p. ej., cierre parcial), habrá que sobreescribir el método. 

virtual double CheckClose(CPositionInfo* position);

El método tiene que implementar el algoritmo para determinar si es necesario cerrar una posición, cuya información se puede conseguir mediante el puntero position. El método tiene que devolver el volumen calculado para el cierre de la posición.

La clase CExpertMoney dispone del siguiente algoritmo para determinar si es necesario cerrar una posición: si la pérdida actual de la posición es superior al porcentaje indicado del depósito, el método de la clase base sugiere cerrar la posición completamente.


2. Crear un sistema de gestión de dinero y riesgo

Ahora, tras haber repasado la estructura de la clase base CExpertMoney, puede empezar con la creación de su propio sistema de gestión de dinero y riesgo. De ahora en adelante, nos vamos a referir al sistema de gestión de dinero y riesgo como "administrador de dinero".

Como se ha mencionado anteriormente, la clase CExpertMoney es un conjunto de métodos virtuales públicos, cuyo uso permite al expert conocer el criterio del gestor del dinero acerca del volumen de entrada al mercado en una dirección u otra.

Por consiguiente, nuestro objetivo principal es crear nuestra propia clase de un administrador de dinero, derivándola de la clase CExpertMoney y sobreescribiendo los métodos virtuales correspondientes con la implementación de los algoritmos necesarios.

Nuestro segundo objetivo (de igual importancia) es hacer que nuestra clase sea "visible" para MQL5 Wizard. Pero lo primero es lo primero.

2.1. Creación de la clase del generador de señales de trading

Comencemos:

En primer lugar, creamos (por ejemplo, mediante el mismo MQL5 Wizard) un archivo de inclusión con la extensión mqh.

Seleccione "Nuevo" (Create) a partir del menú Archivo (o pulse la combinación del teclado Ctrl+N) y elija la creación de un archivo de inclusión:

Figura 2. Crear un archivo de inclusión mediante MQL5 Wizard

Figura 2. Crear un archivo de inclusión mediante MQL5 Wizard

Cabe señalar que, con el fin de que MQL5 Wizard pueda "reconocer" al archivo como un administrador de dinero, hay que crearlo en la carpeta Include\Expert\.

Para evitar conflictos con la librería estándar, creamos nuestra propia carpeta Include\Expert\Money\MyMoneys, en la cual creamos el archivo SampleMoney.mqh, especificando los siguientes parámetros en MQL5 Wizard:

Figura 3. Configuración de la ubicación del archivo de inclusión

Figura 3. Configuración de la ubicación del archivo de inclusión

Como resultado del funcionamiento de MQL5 Wizard obtenemos la siguiente estructura:

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
// #define MacrosHello   "Hello, world!"
// #define MacrosYear    2010
//+------------------------------------------------------------------+
//| DLL imports                                                      |
//+------------------------------------------------------------------+
// #import "user32.dll"
//   int      SendMessageA(int hWnd,int Msg,int wParam,int lParam);
// #import "my_expert.dll"
//   int      ExpertRecalculate(int wParam,int lParam);
// #import
//+------------------------------------------------------------------+
//| EX5 imports                                                      |
//+------------------------------------------------------------------+
// #import "stdlib.ex5"
//   string ErrorDescription(int error_code);
// #import
//+------------------------------------------------------------------+

Lo que viene a continuación es un trabajo "manual". Eliminamos las partes innecesarias y añadimos las que necesitamos; el archivo de inclusión ExpertMoney.mqh de la librería estándar con una descripción de clase vacía.

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management.                    |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
  };
//+------------------------------------------------------------------+

Ahora, es necesario elegir los algoritmos.

Como base para nuestro administrador de dinero optamos por el siguiente algoritmo: En condiciones "normales" se propone usar un volumen fijo predeterminado para la transacción. Pero si se cierra la posición anterior con pérdidas, se propone abrir una posición con el doble de volumen.

Recoja este planteamiento en su archivo.

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
  };
//+------------------------------------------------------------------+

Definimos una lista de ajustes para nuestro administrador de dinero. En realidad, no habrá ninguna lista. Todos los ajustes están incluidos en un solo parámetro que va a determinar el volumen de la transacción en condiciones "normales".

Se almacenará el parámetro en un miembro de datos protegido de la clase. Se implementará el acceso a estos ajustes mediante el método público correspondiente. En el constructor de la clase, se inicializa el parámetro con el valor por defecto. Para comprobar los parámetros, vamos a sobreescribir el método virtual ValidationSettings según la descripción de la clase base.

Vamos a incluir estos cambios en nuestro archivo:

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
protected:
   //--- setup parameters
   double            m_lots;   // deal volume for "normal" conditions

public:
                     CSampleMoney();
   //--- methods to set the parameters
   void              Lots(double lots) { m_lots=lots; }
  };
//+------------------------------------------------------------------+
//| Constructor CSampleMoney.                                        |
//| INPUT:  no.                                                      |
//| OUTPUT: no.                                                      |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
void CSampleMoney::CSampleMoney()
  {
//--- setting the default values
   m_lots=0.1;
  }
//+------------------------------------------------------------------+

Por otra parte, vamos a tratar de implementar el método ValidationSettings(). La cuestión es que la clase base ya tiene un parámetro de configuración, que también requiere verificación.

Por tanto, en el método sobreescrito ValidationSettings(), debemos llamar a ValidationSettings() de la clase base con la comprobación de los resultados de la ejecución.

Implementación del método ValidationSettings():

//+------------------------------------------------------------------+
//| Validation of the setup parameters.                              |
//| INPUT:  no.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSampleMoney::ValidationSettings()
  {
//--- Call the base class method
   if(!CExpertMoney::ValidationSettings()) return(false);
//--- Validation of parameters
   if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax())
     {
      printf(__FUNCTION__+": the deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
      return(false);
     }
   if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10)
     {
      printf(__FUNCTION__+": the volume of the deal must be multiple of %f",m_symbol.LotsStep());
      return(false);
     }
//--- Successful completion
   return(true);
  }

La configuración está lista, vamos a proceder ahora con el funcionamiento del administrador de dinero. Necesitamos un método que determine si la transacción anterior estaba en pérdidas y, si es necesario, definir su volumen. Lo declaramos en la descripción de la clase:

class CSampleMoney : public CExpertMoney
  {
protected:
   //--- Setup parameters
   double            m_lots;  // deal volume for "normal" conditions

public:
                    CSampleMoney();
   //--- Methods to set parameters
   void             Lots(double lots) { m_lots=lots; }
   //--- Methods to validate parameters
   virtual bool      ValidationSettings();

protected:
   double            CheckPrevLoss();
  };

Implementación del método:

//+------------------------------------------------------------------+
//| Defines whether the prev. deal was losing.                       |
//| INPUT:  no.                                                      |
//| OUTPUT: volume of the prev. deal if it's losing, otherwise 0.0   |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckPrevLoss()
  {
   double lot=0.0;
//--- Request the history of deals and orders
   HistorySelect(0,TimeCurrent());
//--- variables
   int       deals=HistoryDealsTotal();  // Total number of deals in the history
   CDealInfo deal;
//--- Find the previous deal
   for(int i=deals-1;i>=0;i--)
     {
      if(!deal.SelectByIndex(i))
        {
         printf(__FUNCTION__+": Error of deal selection by index");
         break;
        }
      //--- Check the symbol
      if(deal.Symbol()!=m_symbol.Name()) continue;
      //--- Check the profit
      if(deal.Profit()<0.0) lot=deal.Volume();
      break;
     }
//--- Return the volume
   return(lot);
  }

Vamos a examinar nuestros algoritmos otra vez, pero con más detalle (aunque ya están detallados).

Sin entrar en los matices, observamos que nuestro administrador de dinero propondrá incrementar el volumen de la transacción al recibir pérdidas en la transacción anterior. Si no ha habido pérdida en la transacción anterior, propondremos abrir una posición con un volumen fijo, definido mediante un parámetro determinado.

Para este propósito, sobreescribimos los métodos CheckOpenLong y CheckOpenShort, asignándoles la funcionalidad correspondiente

Descripción de la clase:

//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
protected:
   //--- Setup parameters
   double            m_lots;  // Deal volume for "normal" conditions

public:
                    CSampleMoney();
   //--- Methods to set the parameters
   void             Lots(double lots) { m_lots=lots; }
   //--- Methods to validate the parameters
   virtual bool      ValidationSettings();
   //--- Methods to define the volume
   virtual double    CheckOpenLong(double price,double sl);
   virtual double    CheckOpenShort(double price,double sl);

protected:
   double            CheckPrevLoss();
  };

Las implementaciones de CheckOpenLong y CheckOpenShort son idénticas virtualmente. Ambos métodos determinan la necesidad de incrementar el volumen llamando el método CheckPrevLoss implementado anteriormente.

A continuación, hay que tener en cuenta que no podemos incrementar el volumen de la operación de forma indefinida. Hay dos limitaciones al volumen de la posición:

  1. El volumen máximo para la transacción con el símbolo indicado en la configuración del servidor (SYMBOL_VOLUME_MAX).
  2. Disponibilidad de las cantidades necesarias de fondos libres del depósito.

Implementación de los métodos CheckOpenLong y CheckOpenShort:

//+------------------------------------------------------------------+
//| Defining the volume to open a long position.                     |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: not.                                                     |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenLong(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Ask();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }
//+------------------------------------------------------------------+
//| Defining the volume to open a short position.                    |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenShort(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Bid();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }

Así que hemos resuelto el primer problema. El código anterior es el "código fuente" de la clase del administrador de dinero que satisface las necesidades de nuestra tarea principal.


2.2. Creación de una descripción de la clase del administrador de dinero para MQL5 Wizard

Pasamos ahora a resolver el segundo problema. El generador de estrategias de trading MQL5 Wizard tiene que "reconocer" nuestro administrador de dinero.

Hemos finalizado la primera condición necesaria: hemos colocado el archivo donde lo va a "encontrar" MQL5 Wizard. Pero esto no es suficiente. MQL5 Wizard no solo debe "encontrar" el archivo, sino que también lo tiene que "reconocer". Para ello, tenemos que añadir al texto original el descriptor de clase para MQL5 Wizard.

Un descriptor de clase es un bloque de comentarios, elaborado de acuerdo con algunas reglas.

Veamos estas reglas.

1. El bloque de comentarios tiene que comenzar con las siguientes líneas:

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |

2. La siguiente línea es un descriptor de texto (lo que veremos en MQL5 Wizard al seleccionar la señal) con el formato "//| Title=<Text> |". Si el texto es demasiado largo para la línea, se puede añadir una línea más (pero no más) a continuación. 

En nuestro caso, tenemos lo siguiente:

//| Title=Trade with a doubling of lot after a loss                  |

3. Después, está la línea que indica el tipo de clase con el formato "//| Type=<Type> |". El campo <Type> debe tener el valor Money (además de los administradores de dinero, MQL5 Wizard reconoce otros tipos de clases).

Escribimos:

//| Type=Money                                                       |

4. La siguiente línea con el formato "//| Name=<Name> |" representa el nombre corto de la señal (la utiliza MQL5 Wizard para generar los nombres de las variables globales del expert).

Obtenemos lo siguiente:

//| Name=Sample                                                      |

5. El nombre de la clase es un elemento importante de la descripción. En la línea con el formato "//| Class=<ClassNameа> |", el parámetro <ClassName> debe corresponder al nombre de nuestra clase:

//| Class=CSampleMoney                                               |

6. No rellanamos esta línea, pero hay que tenerla en cuenta (este es el enlace a la sección de la documentación del lenguaje):

//| Page=                                                            |

7. También hay descripciones de los parámetros de configuración de la señal.

Este es un conjunto de líneas de código (el número de líneas es igual al número de parámetros).

El formato de cada línea es "//| Parameter=<NameOfMethod>,<TypeOfParameter>,<DefaultValue> |".

A continuación, tenemos nuestro conjunto de parámetros:

//| Parameter=Lots,double,0.1                                        |
//| Parameter=Percent,double,100.0                                   |

8. El bloque de comentarios debe finalizar con las siguientes líneas:

//+------------------------------------------------------------------+
// wizard description end

2-7 Tenemos que proporcionar más explicaciones a los elementos 2-7. Las secciones del descriptor de la clase contienen palabras clave (Title, Type, Name, Class, Page, Parameter). Desafortunadamente, MQL5 Wizard no puede interpretar, como parte de la descripción de la clase, todas las combinaciones posibles de caracteres.

Por tanto, para evitar errores innecesarios, se escribe con el siguiente formato:
[Slash][Slash][VerticalLine][Space]<Keyword>[EqualitySign]<Description>;

<Description> solo puede contener espacios para la palabra clave Title. Los párrafos 1 y 8 se deben copiar "tal cual".

El descriptor de la clase (primera línea) no debe estar más allá de la línea 20 del archivo.

Vamos a añadir el descriptor al código fuente.

//+------------------------------------------------------------------+
//|                                                  SampleMoney.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertMoney.mqh>
#include <Trade\DealInfo.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Trading with lot doubling after a loss                     |
//| Type=Money                                                       |
//| Name=Sample                                                      |
//| Class=CSampleMoney                                               |
//| Page=                                                            |
//| Parameter=Lots,double,0.1                                        |
//| Parameter=Percent,double,100.0                                   |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSampleMoney.                                              |
//| Purpose: Class for risk and money management                     |
//|             doubling the volume after a loss deal.               |
//|             It is derived from the CExpertMoney class.           |
//+------------------------------------------------------------------+
class CSampleMoney : public CExpertMoney
  {
protected:
   //--- Setup parameters
   double            m_lots;  // Deal volume for "normal" conditions

public:
                     CSampleMoney();
   //--- Methods to set the parameters
   void              Lots(double lots) { m_lots=lots; }
   //--- Methods to validate the parameters
   virtual bool      ValidationSettings();
   //--- Methods to define the volume
   virtual double    CheckOpenLong(double price,double sl);
   virtual double    CheckOpenShort(double price,double sl);

protected:
   double            CheckPrevLoss();
  };
//+------------------------------------------------------------------+
//| Constructor CSampleMoney.                                        |
//| INPUT:  no.                                                      |
//| OUTPUT: no.                                                      |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
void CSampleMoney::CSampleMoney()
  {
//--- Setting default values
   m_lots=0.1;
  }
//+------------------------------------------------------------------+
//| Validation of the setup parameters.                              |
//| INPUT:  no.                                                      |
//| OUTPUT: true if the settings are correct, otherwise false.       |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSampleMoney::ValidationSettings()
  {
//--- Call the base class method
   if(!CExpertMoney::ValidationSettings()) return(false);
//--- Validating the parameters
   if(m_lots<m_symbol.LotsMin() || m_lots>m_symbol.LotsMax())
     {
      printf(__FUNCTION__+": The deal volume must be in the range %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax());
      return(false);
     }
   if(MathAbs(m_lots/m_symbol.LotsStep()-MathRound(m_lots/m_symbol.LotsStep()))>1.0E-10)
     {
      printf(__FUNCTION__+": The deal volume must be multiple of  %f",m_symbol.LotsStep());
      return(false);
     }
//--- Successful completion
   return(true);
  }
//+------------------------------------------------------------------+
//| Defining the volume to open a long position.                     |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenLong(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Ask();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_BUY,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }
//+------------------------------------------------------------------+
//|Defining the volume to open a short position.                     |
//| INPUT:  no.                                                      |
//| OUTPUT: lot-if successful, 0.0 otherwise.                        |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckOpenShort(double price,double sl)
  {
   if(m_symbol==NULL) return(0.0);
//--- Select the lot size
   double lot=2*CheckPrevLoss();
   if(lot==0.0) lot=m_lots;
//--- Check the limits
   double maxvol=m_symbol.LotsMax();
   if(lot>maxvol) lot=maxvol;
//--- Check the margin requirements
   if(price==0.0) price=m_symbol.Bid();
   maxvol=m_account.MaxLotCheck(m_symbol.Name(),ORDER_TYPE_SELL,price,m_percent);
   if(lot>maxvol) lot=maxvol;
//--- Return the trade volume
   return(lot);
  }
//+------------------------------------------------------------------+
//| Defines whether the prev. deal was losing.                       |
//| INPUT:  no.                                                      |
//| OUTPUT: Volume of the prev. deal if it's losing, otherwise 0.0   |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
double CSampleMoney::CheckPrevLoss()
  {
   double lot=0.0;
//--- Request the history of deals and orders
   HistorySelect(0,TimeCurrent());
//--- variables
   int       deals=HistoryDealsTotal();  // Total number of deals in the history
   CDealInfo deal;
//--- Find the previous deal
   for(int i=deals-1;i>=0;i--)
     {
      if(!deal.SelectByIndex(i))
        {
         printf(__FUNCTION__+": Error of deal selection by index");
         break;
        }
      //--- Check the symbol
      if(deal.Symbol()!=m_symbol.Name()) continue;
      //---Check the profit
      if(deal.Profit()<0.0) lot=deal.Volume();
      break;
     }
//--- Return the volume
   return(lot);
  }
//+------------------------------------------------------------------+

Bueno, eso es todo. Ya se puede utilizar el administrador de dinero.

Para que el generador de estrategias de trading MQL5 Wizard pueda usar nuestro administrador de dinero, tenemos que reiniciar MetaEditor (MQL5 Wizard analiza la carpeta Include\Expert en el arranque solo).

Tras el reinicio de MetaEditor, se puede utilizar el administrador de dinero en MQL5 Wizard:

Figura 5. El administrador de dinero creado en MQL5 Wizard

Figura 5. El administrador de dinero creado en MQL5 Wizard

Ya están disponibles los parámetros de entrada especificados en la descripción de los parámetros del administrador de dinero:

Figura 6. Los parámetros de entrada del administrador de dinero creado en MQL5 Wizard

Figura 6. Los parámetros de entrada del administrador de dinero creado en MQL5 Wizard

Se pueden encontrar los mejores parámetros de entrada de la estrategia de trading implementada mediante el probador de estrategias del terminal de MetaTrader 5.

La figura 7 muestra los resultados de la prueba del Expert Advisor que opera en función de este sistema de gestión de dinero (EURUSD H1, período de prueba: 01.01.2010-05.01.2011).

Figura 7. Resultados de la prueba en el historial de la estrategia con el módulo de gestión de dinero con duplicación de volumen después de una pérdida

Figura 7. Resultados de la prueba en el historial de la estrategia con el módulo de gestión de dinero con duplicación de volumen después de una pérdida

Durante la creación del Expert Advisor, hemos utilizado el módulo de señales de trading implementado en el artículo "MQL5 Wizard: Cómo crear un módulo de señales de trading". Parámetros del Expert Advisor (PeriodMA=12, ShiftMA=0, MethodMA=MODE_EMA, AppliedMA=PRICE_CLOSE, Limit=-70, StopLoss=145, TakeProfit=430, Expiration=10, Lots=0.1, Percent=100).


Conclusión

El generador de estrategias de trading de MQL5 Wizard simplifica enormemente los procesos de pruebas de los conceptos de trading. El código del expert generado se basa en las clases de las estrategias de trading de la librería estándar, que se usan para crear determinadas clases de señales de trading, clases de gestión de dinero y riesgo y clases de soporte de posición. 

En este artículo se describe el modo de desarrollar un módulo de gestión de dinero y habilitarlo en MQL5 Wizard. Como ejemplo vamos a considerar un algoritmo de gestión de dinero, en el cual se determina el tamaño de la operación mediante los resultados de la transacción anterior. El artículo aborda también la descripción del formato de la clase creada para MQL5 Wizard.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/230

Archivos adjuntos |
samplemoney.mqh (7.15 KB)
MQL5 Wizard: Cómo crear un módulo de Trailing de posiciones abiertas MQL5 Wizard: Cómo crear un módulo de Trailing de posiciones abiertas
El generador de estrategias de trading de MQL5 Wizard simplifica enormemente los procesos de pruebas de los conceptos de trading. El artículo aborda la forma de escribir y conectar al generador de estrategias de trading de MQL5 Wizard su propia clase de gestión de posiciones abiertas moviendo el nivel de Stop Loss a una zona sin pérdidas cuando el precio va en la misma dirección que la posición, proporcionando una protección contra la disminución de sus beneficios durante el trading. También informa sobre la estructura y el formato de la descripción de la clase creada para MQL5 Wizard.
Las Tablas Electrónicas en MQL5 Las Tablas Electrónicas en MQL5
El artículo describe una clase de matrices dinámicas bidimensionales que contienen los diferentes tipos de datos en su primera dimensión. Es conveniente almacenar los datos en forma de tablas para poder resolver una gran variedad de problemas de disposición, almacenamiento y funcionamiento con información de diferentes clases. El código fuente de la clase que implementa la funcionalidad de trabajar con tablas está adjunto al artículo.
La implementación del modo multidivisa en MetaTrader 5 La implementación del modo multidivisa en MetaTrader 5
Durante mucho tiempo, la gente ha tenido un gran interés en el análisis multidivisa y el trading multidivisa. La oportunidad de implementar un modo multidivisa completo solo es posible con la versión pública de MetaTrader 5 y el lenguaje de programación MQL5. En este artículo, vamos a proponer un modo de análisis y procesamiento de todos los ticks recibidos para varios símbolos. Como ejemplo, vamos a ver el indicador RSI multidivisa del índice dólar USDx.
MQL5 Wizard: Cómo crear un módulo de señales de trading MQL5 Wizard: Cómo crear un módulo de señales de trading
En este artículo se explica el modo de escribir su propia clase de señales de trading con la implementación de señales en el cruce del precio con el promedio móvil y la manera de incluirla en el generador de estrategias de trading de MQL5 Wizard, también se describe la estructura y el formato de la clase generada para MQL5 Wizard.