MQL5 Wizard: Cómo enseñar a un Asesor Experto a abrir las órdenes pendientes de cualquier precio
Introducción
Un Asesor Experto generado usando MQL5 Wizard sólo puede abrir órdenes pendientes a una distancia fija desde el precio actual. Esto significa que si la situación del mercado cambia (por ejemplo un cambio en la volatilidad del mercado), el Asesor Experto tendrá que ejecutarse otra vez con nuevos parámetros.
Esto no sería conveniente para muchos sistemas de trading. En la mayoría de los casos, el nivel de precios para órdenes pendientes está determinado de forma dinámica por un sistema de trading. Y la distancia del precio actual cambia constantemente. En este artículo, analizaremos cómo modificar un Asesor Experto generado mediante MQL5 Wizard para que pueda abrir órdenes pendientes para variar distancias del precio actual.
1. El mecanismo de apertura de órdenes pendientes en el Asesor Experto generado mediante MQL5 Wizard
Un Asesor Experto generado tendría en su encabezamiento aproximadamente el mismo código que el siguiente:
//+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ //--- inputs for expert input string Expert_Title="ExpertMySignalEnvelopes.mq5"; // Document name ulong Expert_MagicNumber =3915; // bool Expert_EveryTick =false; // //--- inputs for main signal input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100] input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100] input double Signal_PriceLevel =0.0; // Price level to execute a deal input double Signal_StopLevel =85.0; // Stop Loss level (in points) input double Signal_TakeLevel =195.0; // Take Profit level (in points) input int Signal_Expiration =0; // Expiration of pending orders (in bars) input int Signal_Envelopes_PeriodMA =13; // Envelopes(13,0,MODE_SMA,...) Period of averaging input int Signal_Envelopes_Shift =0; // Envelopes(13,0,MODE_SMA,...) Time shift input ENUM_MA_METHOD Signal_Envelopes_Method =MODE_SMA; // Envelopes(13,0,MODE_SMA,...) Method of averaging input ENUM_APPLIED_PRICE Signal_Envelopes_Applied =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series input double Signal_Envelopes_Deviation=0.2; // Envelopes(13,0,MODE_SMA,...) Deviation input double Signal_Envelopes_Weight =1.0; // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0] //--- inputs for money input double Money_FixLot_Percent =10.0; // Percent input double Money_FixLot_Lots =0.1; // Fixed volume //+------------------------------------------------------------------+
Tome nota del parámetro Signal_PriceLevel. De manera predeterminada, el Asesor Experto está generado con Signal_PriceLevel=0. Este parámetro define la distancia del precio actual. Si es igual a cero, se abrirá una orden al precio actual del mercado. Para abrir una orden pendiente, debe poner un valor distinto de cero para el parámetro Signal_PriceLevel , de hecho, Signal_PriceLevel puede ser negativo o positivo.
El valor de Signal_PriceLevel es generalmente un número bastante grande. A continuación, se muestra la diferencia entre valores negativos y positivos:
Signal_PriceLevel=-50:
Fig. 1. Signal_PriceLevel=-50
Signal_PriceLevel=50:
Fig. 2. Signal_PriceLevel=50
Así, si Signal_PriceLevel=-50, se abrirá una orden pendiente en el precio que es menos favorable que el precio actual, mientras que si Signal_PriceLevel=50, se abrirá una orden pendiente en el precio que es mejor que el precio actual.
Esta versión del Asesor Experto abre órdenes Sell Stop y Buy Stop.
2. ¿Dónde almacenamos los datos de la distancia del precio de apertura de una orden pendiente?
Echemos primero un vistazo a la siguiente figura y luego continuemos con los comentarios:
Fig. 3. Almacenamiento de los datos en la distancia del precio actual
Interpretación de la figura antes mencionada.
El Asesor Experto es el Asesor Experto generado mediante MQL5 Wizard.
- El objeto ExtExpert de la clase CExpert está declarado en el Asesor Experto a nivel global.
- Entonces, en la función OnInit() del Asesor Experto, declaramos un puntero al objeto de la señal de la clase CExpertSignal y el objeto de la señal se crea inmediatamente utilizando el new operador.
- Al estar en la función OnInit(), llamamos a la función InitSignal del objeto ExtExpert e iniciamos el objeto de señal.
- Al estar en la función OnInit(), llamamos la función PriceLevel del objeto de señal que consigue el parámetro Signal_PriceLevel.
Así, el parámetro Signal_PriceLevel donde la distancia del precio actual está almacenada y que fue declarada en el Asesor Experto se pasa al objeto de la señal de la clase CExpertSignal .
La clase CExpertSignal almacena el valor de la distancia del precio actual en la variable precio_variable_m declarada con el ámbito de la clase protegida:
class CExpertSignal : public CExpertBase { protected: //--- variables double m_base_price; // base price for detection of level of entering (and/or exit?) //--- variables for working with additional filters CArrayObj m_filters; // array of additional filters (maximum number of fileter is 64) //--- Adjusted parameters double m_weight; // "weight" of a signal in a combined filter int m_patterns_usage; // bit mask of using of the market models of signals int m_general; // index of the "main" signal (-1 - no) long m_ignore; // bit mask of "ignoring" the additional filter long m_invert; // bit mask of "inverting" the additional filter int m_threshold_open; // threshold value for opening int m_threshold_close;// threshold level for closing double m_price_level; // level of placing a pending orders relatively to the base price double m_stop_level; // level of placing of the "stop loss" order relatively to the open price double m_take_level; // level of placing of the "take profit" order relatively to the open price int m_expiration; // time of expiration of a pending order in bars
3. Estructura del Asesor Experto generado mediante MQL5 Wizard
El Asesor Experto consiste en varios bloques con funcionalidades diferentes.
Fig. 4. Estructura del Asesor Experto
Interpretación de la figura de arriba:
- El Asesor Experto es el Asesor Experto generado mediante MQL5 Wizard.
- CExpert es la clase base para la implementación de estrategias de trading.
- CExpertSignal es la clase base para la creación de generadores de señales de trading.
- filter0 ... filtern son generadores de señales de trading, los descendientes de la clase CExpertSignal. Cabe señalar que nuestro sistema de trading está basado en el generador de señal de trading del indicador de envoltura (Envelopes), pero las señales dentro del generador han sido modificadas. Hablaremos de esos cambios en el apartado 7.
4. Bloques del Asesor Experto para la modificación
Como pudo ver de la estructura del Asesor Experto generado mediante MQL5 Wizard, hay bloques de clase base. Las clases base forman parte de la librería estándar.
Las clases son de por sí, descendientes de otras clases base y que a su vez se componen de una o más clases base. Más abajo puede encontrar las pocas primeras líneas del código de dos clases - CExpert y CExpertSignal:
//+------------------------------------------------------------------+ //| Expert.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" #include "ExpertTrade.mqh" #include "ExpertSignal.mqh" #include "ExpertMoney.mqh" #include "ExpertTrailing.mqh" //+------------------------------------------------------------------+ . . . class CExpert : public CExpertBase
y
//+------------------------------------------------------------------+ //| ExpertSignal.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" . . . class CExpertSignal : public CExpertBase
Estoy totalmente en contra de cualquier modificación de las clases base:
- Cuando se actualiza MetaEditor, se invalidan todos los cambios que se hacen a las clases base y se restauran las mismas a su estado inicial.
- La herencia sería más apropiada en este caso. Pero entonces tendrá que modificar la librería estándar ENTERA.
En vez de eso, sería mejor modificar el bloque del Asesor Experto y de los módulos del generador de señal de trading, especialmente desde que nuestro sistema de trading tenga ya un módulo modificado en uso; el generador de señal de trading del indicador de envoltura.
Por lo tanto, eso esto arreglado: haremos cambios a los bloques del Asesor Experto y al bloque del generador de señal de trading.
5. La Lógica de la Implementación
El puntero se pasará del Asesor Experto al generador de señal de trading.
Para este fin,tenemos que declarar además una variable con el alcance protegido y escribir un método que almacena el puntero del Asesor Experto en la variable interna:
Fig. 5. La Lógica de la Implementación
6. Sistema de Trading
El período de tiempo del gráfico es D1. El indicador que se va a utilizar es Envelopes con el período promedio de 13 y el método de promedio exponencial. Los tipos de órdenes que el Asesor Experto puede abrir son Sell Stop y Buy Stop.
Si la barra anterior era a la alza, ponemos una orden Sell Stop. Si la barra anterior era a la baja, ponemos una orden Buy Stop. Es decir, esperamos por la retirada:
Fig. 6. Sistema de Trading
Para generar señales de trading como las requeridas por el sistema de trading, el módulo estándar de SignalEnvelopes.mqh del generador de señal de trading ha sido modificado.
Tenga en cuenta que aquí puede utilizar cualquier generador de señal de trading de la librería estándar.
7. Modificación del generador de señal de trading. Conseguir el precio de la barra
Así que, empecemos. Debo decir que prefiero guardar mis programas en MQL5 Storage.
La primera cosa que debemos hacer para comenzar modificando el generador de señal de trading es la creación de un espacio en blanco del fichero a incluir, eliminar todo y pegar el contenido del generador de señal estándar de trading del indicador de envoltura (Envolpes).
Por defecto el generador de señal de tradig debe estar localizado debajo de ...MQL5\Include\Expert\Signal. No sobrecargar la ... carpeta \Signal de la librería estándar con demasiado información, cree una nueva carpeta debajo de la carpeta ...\Expert y llámela MySignals:
Fig. 7. Creación de la carpeta MySignals
Luego, crearemos un archivo de inclusión que utiliza MQL5 Wizard.
En MetaEditor, seleccione "Nuevo" bajo el menú Archivo y a continuación seleccione "Incluir (*.mqh)".
Fig. 8. MQL5 Wizard. Creación de un archivo de inclusión
El nombre de nuestra clase de generador de señal será MySignalEnvelopes.
Y se ubicará en: Include\Expert\MySignals\MySignalEnvelopes. Lo vamos a especificar:
Fig. 9. MQL5 Wizard. Ubicación del archivo de inclusión
Después de que haga clic en "Finalizar", MQL5 Wizard generará una plantilla vacía.
El archivo generado de MySignalEnvelopes.mqh se debe entonces añadir a MQL5 Storage:
Fig. 10. MQL5 Storage. Agregar el archivo
Una vez añadido el archivo, debemos consignar los cambios a MQL5 Storage:
Fig. 11. MQL5 Storage. Consignar los cambios
Habiendo completado los pasos mencionados antes, podemos continuar modificando nuestro generador de señal de trading.
Dado que el generador está basado en el archivo \Include\Expert\Signal\SignalEnvelopes.mqh, copiamos el contenido entero del archivo y lo pegamos en el archivo del generador, dejando sólo el encabezamiento original:
//+------------------------------------------------------------------+ //| MySignalEnvelopes.mqh | //| Copyright © 2013, Vladimir Karputov | //| http://wmua.ru/slesar/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2013, Vladimir Karputov" #property link "http://wmua.ru/slesar/" #include <Expert\ExpertSignal.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of indicator 'Envelopes' | //| Type=SignalAdvanced | //| Name=Envelopes | //| ShortName=Envelopes | //| Class=CSignalEnvelopes | //| Page=signal_envelopes | //| Parameter=PeriodMA,int,45,Period of averaging | //| Parameter=Shift,int,0,Time shift | //| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | //| Parameter=Deviation,double,0.15,Deviation | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSignalEnvelopes. | //| Purpose: Class of generator of trade signals based on | //| the 'Envelopes' indicator. | //| Is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalEnvelopes : public CExpertSignal { protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator double m_limit_in; // threshold sensitivity of the 'rollback zone' double m_limit_out; // threshold sensitivity of the 'break through zone' //--- "weights" of market models (0-100) int m_pattern_0; // model 0 "price is near the necessary border of the envelope" int m_pattern_1; // model 1 "price crossed a border of the envelope" public: CSignalEnvelopes(void); ~CSignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } void LimitIn(double value) { m_limit_in=value; } void LimitOut(double value) { m_limit_out=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } void Pattern_1(int value) { m_pattern_1=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(0.15), m_limit_in(0.2), m_limit_out(0.2), m_pattern_0(90), m_pattern_1(70) { //--- initialization of protected data m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSignalEnvelopes::~CSignalEnvelopes(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertSignal::ValidationSettings()) return(false); //--- initial data checks if(m_ma_period<=0) { printf(__FUNCTION__+": period MA must be greater than 0"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- create and initialize MA indicator if(!InitMA(indicators)) return(false); //--- ok return(true); } //+------------------------------------------------------------------+ //| Initialize MA indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitMA(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- add object to collection if(!indicators.Add(GetPointer(m_env))) { printf(__FUNCTION__+": error adding object"); return(false); } //--- initialize object if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation)) { printf(__FUNCTION__+": error initializing object"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+
Ahora, vamos a trabajar en las modificaciones de algunas partes del código.
Para evitar la confusión, el código modificado será resaltado:
//+------------------------------------------------------------------+
//| MySignal.mqh |
//| Copyright © 2013, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
El código modificado es el código que debe copiar y pegar en el generador de señal de trading. Espero que resaltarlo le ayudará a comprender mejor el código.
Dado que estamos escribiendo nuestra propia clase del generador de señal de trading, su nombre debe ser diferente del nombre de la clase base. Por lo tanto reemplazamos CSignalEnvelopes con CMySignalEnvelopes en todo el código:
Fig. 12. Cambiar el nombre de la clase
Para asegurarse de que la clase del generador de señal de trading aparece en MQL5 Wizard bajo su nombre, cambie el nombre de la clase en el bloque de descripción
//| Title=Signals of indicator 'Envelopes' |
a
//| Title=Signals of indicator 'MySignalEnvelopes' |
Cambie el valor del período de MA
//| Parameter=PeriodMA,int,45,Period of averaging |
a 13 (esto es sólo mi sugerencia, puede poner cualquier valor que usted prefiera)
//| Parameter=PeriodMA,int,13,Period of averaging |
Además, también modificamos el parámetro de desviación
//| Parameter=Deviation,double,0.15,Deviation |
poniendo un valor más grande
//| Parameter=Deviation,double,1.15,Deviation |
Según nuestra lógica de implementación, debemos declarar una variable interna que almacenará el puntero a la señal principal.
Dado que esto debe ser una variable interna (dentro del alcance de la clase del generador de señal de trading solamente), se añadirá al bloque el siguiente código:
protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator //--- "weights" of market models (0-100) int m_pattern_0; // model 0 CExpertSignal *m_signal; // storing the pointer to the main signal
Tenga también en cuenta que borré las variables innecesarias del código.
El método para almacenar el puntero a la señal principal será declarado en otro bloque de código; "el método de establecer el puntero a la señal principal'. Aquí, también borré algunos métodos irrelevantes.
public: CMySignalEnvelopes(void); ~CMySignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); //--- method of setting the pointer to the main signal virtual bool InitSignal(CExpertSignal *signal=NULL);
Ahora especifiquemos algunos parámetros modificados en el constructor y borremos las variables que ya no se necesitan:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(1.15), m_pattern_0(50)
At this point, we can proceed to modifying the trading signal generation logic according to our trading system.
El bloque del código responsable de una señal de compra:
int CMySignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
será como se muestra a continuación, siguiendo los cambios necesarios:
int CMySignalEnvelopes::LongCondition(void) //---buy
{
int result=0;
int idx =StartIndex();
double open=Open(idx);
double close=Close(idx);
double prlevel;
if(IS_PATTERN_USAGE(0) && close<open)
{
prlevel=GetPriceLevelStopp(open,Open(0));
m_signal.PriceLevel(prlevel);
result=m_pattern_0;
}
//--- return the result
return(result);
}
El bloque del código responsable de una señal de venta:
int CMySignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
será como se muestra a continuación, siguiendo los cambios necesarios:
int CMySignalEnvelopes::ShortCondition(void) //---sell
{
int result =0;
int idx =StartIndex();
double open=Open(idx);
double close=Close(idx);
double prlevel;
if(IS_PATTERN_USAGE(0) && close>open)
{
prlevel=GetPriceLevelStopp(Open(0),open);
m_signal.PriceLevel(prlevel);
result=m_pattern_0;
}
//--- return the result
return(result);
}
8. Unos pocos comentarios sobre el bloque del código de Señal
Si se cumple la condición necesaria para una señal concreta, llamamos al método GetPriceLevelStopp que devuelve un número como "20" o "15"; el valor de la distancia del precio actual.
Esto es seguido por una llamada al método PriceLevel del objeto m_signal (que establece la distancia para determinar el nivel de precio de la orden pendiente). Debe recordarse que m_signal es el objeto de la clase CExpertSignal que almacena el puntero a la señal principal.
El código del método GetPriceLevelStopp se proporciona a continuación:
double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
{
double level;
double temp;
temp-=(price_0-min)/PriceLevelUnit();
level=NormalizeDouble(temp,0);
return(level);
}
Tenemos que declarar este método en el encabezado de la clase:
protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } double GetPriceLevelStopp(double price,double min); };
Otro método que necesitaremos es el método de pasar el puntero a la señal principal para la variable interna:
bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
{
m_signal=signal;
return(true);
}
Después de esto deberíamos crear un Asesor Experto en MQL5 Wizard e incluir en el mismo el módulo de señal "MySignalEnvelopes".
También debemos añadir la llamada del método InitSignal al código del Asesor Experto generado mediante MQL5 Wizard:
//--- Set filter parameters filter0.PeriodMA(Signal_Envelopes_PeriodMA); filter0.Shift(Signal_Envelopes_Shift); filter0.Method(Signal_Envelopes_Method); filter0.Applied(Signal_Envelopes_Applied); filter0.Deviation(Signal_Envelopes_Deviation); filter0.Weight(Signal_Envelopes_Weight); filter0.InitSignal(signal); //...
Para una mejor visualización del funcionamiento del Asesor Experto, he proporcionado un vídeo corto:
El código del Asesor Experto generado mediante MQL5 Wizard, así como el código del módulo de señal, están adjuntos al artículo.
Puede ver abajo, los resultados de la prueba del Asesor Experto. Se hizo la prueba para EURUSD y USDJPY con los siguientes parámetros: período de la prueba 2013.01.01 - 2013.09.01, período de tiempo - D1, nivel Stop Loss = 85, nivel Take Profit = 195.
Fig. 13. Prueba para EURUSD en D1
Fig. 14. Prueba para USDJPYD en D1
Conclusión
Hemos visto cómo podemos modificar el código del módulo de señal de trading para la implementación de la funcionalidad que nos permite configurar órdenes pendientes a cualquier distancia del precio actual: puede ser el precio de Cierre o de Apertura de la barra anterior o el valor del promedio móvil. Hay muchas opciones. Lo importante es que puede establecer cualquier precio de apertura para una orden pendiente.
El artículo ha demostrado cómo podemos acceder al puntero, y de ahí a los métodos de la clase CExpertSignal. Creo que este artículo será muy útil para los traders que operan con órdenes pendientes.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/723
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso