Вы находитесь на странице: 1из 16

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

MetaQuotes Software Corp. | 4 abril, 2014

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

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

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

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 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.Lo
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.Lo
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)
p y p p
{
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.Lo
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

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

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

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.

Вам также может понравиться