Pon "Me gusta" y sigue las noticias
Deje un enlace a él, ¡qué los demás también lo valoren!
Evalúe su trabajo en el terminal MetaTrader 5
MACD Sample - Asesor Experto para MetaTrader 5
- Publicado por:
- MetaQuotes
- Visualizaciones:
- 4976
- Ranking:
- Publicado:
- 2014.06.09 13:21
- Actualizado:
- 2016.11.22 07:33
- ¿Necesita un robot o indicador basado en este código? Solicítelo en la bolsa freelance Pasar a la bolsa
El asesor MACD Sample está incluido dentro del suministro estándar del terminal de cliente MetaTrader 5 y supone un ejemplo de asesor que comercia con la ayuda del indicador MACD.
El archivo del asesor MACD Sample.mq5 se encuentra en la carpeta: "catálogo_de_datos_del_terminal\MQL5\Experts\Examples\MACD\". Este asesor supone un claro ejemplo del uso del enfoque orientado a objetos a la hora de desarrollar los asesores.
Vamos a echar un vistazo con más detalle a la estructura de este asesor y su principio de funcionamiento.
1. Propiedades del asesor
1.1. Propiedades del asesor
//+------------------------------------------------------------------+ //| MACD Sample.mq5 | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2009-2013, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "5.20" #property description "It is important to make sure that the expert works with a normal" #property description "chart and the user did not make any mistakes setting input" #property description "variables (Lots, TakeProfit, TrailingStop) in our case," #property description "we check TakeProfit on a chart of more than 2*trend_period bars"
Las primeras 5 líneas contienen los comentarios, las siguientes 7 establecen las propiedades del programa MQL5 (copyright, link, version, description) con la ayuda de las directivas del procesador #property.
Al iniciar el asesor, se mostrarán en la pestaña "General":
Figura 1. Parámetros generales del asesor MACD Sample
1.2. Archivos contenidos
A continuación, con ayuda de la directiva #include continuamos con la indicación al compilador sobre la necesidad de incluir los archivos que contengan las clases comerciales de la Biblioteca estándar:
- Trade.mqh (CTrade - es la clase para la realización de operaciones comerciales);
- SymbolInfo.mqh (CSymbolInfo - es la clase para trabajar con las propiedades del instrumento comercial);
- PositionInfo.mqh (CPositionInfo - es la clase para trabajar con las propiedades de una posición abierta);
- AccountInfo.mqh (CAccountInfo - es la clase para trabajar con las propiedades de la cuenta comercial).
//--- archivos contenidos #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\PositionInfo.mqh> #include <Trade\AccountInfo.mqh>
Los ejemplares de las clases correspondientes, en lo sucesivo se utilizan como variables-miembros de la clase CExpert (apartado 3).
1.3. Parámetros de entrada
Después de esto se indican los tipos, denominaciones, valores por defecto y comentarios cuyas funciones se muestran en la fig. 2.
//--- parámetros de entrada del asesor input double InpLots =0.1; // Lots input int InpTakeProfit =50; // Take Profit (in pips) input int InpTrailingStop =30; // Trailing Stop Level (in pips) input int InpMACDOpenLevel =3; // MACD open level (in pips) input int InpMACDCloseLevel=2; // MACD close level (in pips) input int InpMATrendPeriod =26; // MA trend period
Preste atención al hecho de que las denominaciones de los parámetros de entrada tienen el prefijo "Inp". También debemos destacar que las variables globales tienen el prefijo "Ext". Semejante enfoque respecto a la denominación de las variables simplifica el trabajo al usar una gran cantidad de variables diferentes.
InpLots - es el volumen comercial, los parámetros InpTakeProfit y InpTrailingStop determinan los niveles de Take Profit y Trailing Stop,
El texto indicado en los comentarios en la línea del parámetro de entrada, junto a los valores por defecto, se muestra en la pentaña "Parámetros", en lugar de la denominación del parámetro de entrada:
Figura 2. Parámetros de entrada del asesor MACD Sample
1.4. Variables globales
Después de esto se anuncia la variable global ExtTimeOut, que se usará para controlar el tiempo de ejecución de las operaciones comerciales.
int ExtTimeOut=10; // tiempo (en segundos) entre operaciones comerciales
Tras anunciar la clase CSampleExpert en la línea 76 se anuncia otra variable global: ExtExpert - es un ejemplar de la clase CSampleExpert:
//--- variable global ExtExpert
CSampleExpert ExtExpert;
El objeto ExtExpert (ejemplar de la clase CSampleExpert) contiene la base lógica de la estrategia comercial (apartado 3).
2. Funciones de procesamiento de eventos
Funciones de procesamiento de eventos
2.1. Función de inicialización OnInit()
La función OnInit() se llama una vez, al iniciar por primera vez el asesor. Al procesar el evento OnInit() normalmente se realiza la preparación del asesor para el trabajo: se comprueba la corrección de los parámetros de entrada, se inicializan los indicadores, las variables, etc. En caso de errores críticos que hagan inútil cualquier trabajo posterior, se usa la salida de la función con el código de retorno INIT_FAILED.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(void) { //--- inicialización y creación de todos los objetos necesarios if(!ExtExpert.Init()) return(INIT_FAILED); //--- la inicialización ha tenido éxito return(INIT_SUCCEEDED); }
En este caso se invoca el método Init() del objeto ExtExpert, que retorna true o false, dependiendo del éxito a la hora de preparar todos los objetos necesarios para el funcionamiento (más información en el apartado 3.4). En caso de error se realiza la salida de la función OnInit() con el código de retorno INIT_FAILED este es el método correcto de finalizar el trabajo con el asesor/indicador en caso de que la inicialización no tenga éxito.
2.2. Función OnTick()
La función OnTick() se invoca cada vez que se reciba una nueva cotización según el símbolo del gráfico en el que se haya iniciado el asesor.
//+------------------------------------------------------------------+ //| Expert new tick handling function | //+------------------------------------------------------------------+ void OnTick(void) { static datetime limit_time=0; // almacena la última hora de llamada + timeout //--- no lleva a cabo el trabajo, si no ha pasado el tiempo indicado if(TimeCurrent()>=limit_time) { //--- comprobación de datos if(Bars(Symbol(),Period())>2*InpMATrendPeriod) { //--- tras la llamada del método Processing() aumentamos el valor limit_time en ExtTimeOut if(ExtExpert.Processing()) limit_time=TimeCurrent()+ExtTimeOut; } } }
En el desarrollo del evento OnTick() está implementado un mecanismo de llamada periódica del método ExtExpert.Processing(), que se utiliza para el análisis del mercado y el comportamiento de las operaciones comerciales al cumplirse las condiciones comerciales.
El intervalo de tiempo entre llamadas se establece con el valor del parámetro de entrada ExtTimeOut.
2.3. Función de desinicialización OnDeInit()
La función de desinicialización OnDeInit() se llama al eliminarse el asesor del gráfico. Si en el proceso de funcionamiento el programa distribuye objetos gráficos, estos pueden ser quitados del gráfico.
En este ejemplo, no tenemos la función de desinicialización, por lo que no se produce acción alguna.
3. Clase CSampleExpert
3.1. Clase CSampleExpert
//+------------------------------------------------------------------+ //| Clase del asesor MACD Sample | //+------------------------------------------------------------------+ class CSampleExpert { protected: //--- los protected variables-miembros de clase están disponibles dentro de los métodos de clase double m_adjusted_point; // multiplicador de cotizaciones de 3/5 dígitos CTrade m_trade; // ejemplar de clase CTrade CSymbolInfo m_symbol; // ejemplar de clase CSymbolInfo CPositionInfo m_position; // ejemplar de clase CPositionInfo CAccountInfo m_account; // ejemplar de clase CAccountInfo //--- handles de las cotizaciones int m_handle_macd; // handle del indicador MACD int m_handle_ema; // handle del indicador Moving Average //--- búfers de indicador double m_buff_MACD_main[]; // búfer de la línea principal del indicador MACD double m_buff_MACD_signal[]; // búfer de la línea de señal del indicador MACD double m_buff_EMA[]; // búfer del indicador EMA //--- valores actuales de los indicadores double m_macd_current; double m_macd_previous; double m_signal_current; double m_signal_previous; double m_ema_current; double m_ema_previous; //--- niveles (en puntos estándar) double m_macd_open_level; double m_macd_close_level; double m_traling_stop; double m_take_profit; public: //--- constructor CSampleExpert(void); //--- destructor ~CSampleExpert(void); //--- los métodos public están accesibles desde fuera, pueden ser llamados desde fuera de la clase //--- método de inicialización bool Init(void); //--- método de desinicialización void Deinit(void); //--- método de procesamiento bool Processing(void); protected: //--- los métodos protected están accesibles dentro de los métodos de clase bool InitCheckParameters(const int digits_adjust); bool InitIndicators(void); bool LongClosed(void); bool ShortClosed(void); bool LongModified(void); bool ShortModified(void); bool LongOpened(void); bool ShortOpened(void); };
La clase del asesor contiene la declaración de las variables (miembros de clase) y funciones (métodos de clase).
Para que se pueda trabajar más cómodamente, todas las variables-miembros de la clase contienen el prefijo "m_" (member), que indica que la variable dada es miembro de la clase. Antes de declarar la variable o el método, se indica su tipo (o el retorno del valor para las funciones).
La visibilidad de las variables y los métodos-miembros se establece con ayuda de los modificadores de acceso. En la clase CSampleExpert se utilizan los modificadores protected y public. Todas las variables y métodos declarados en la sección public, son públicos y accesibles desde fuera. La clase CSampleExpert tiene 5 métodos de ese tipo:
- CSampleExpert(void) - es el constructor (se llama automáticamente al crear un ejemplar de clase);
- ~CSampleExpert(void) - es el desctructor (se llama automáticamente al eliminar un ejemplar de clase);
- bool Init(void) - es el método de inicialización en el que se realiza la preparación de todos los datos necesarios para el trabajo;
- void Deinit(void) - es el método de desinicialización;
- bool Processing(void) - es el método de procesamiento.
Las variables-miembros de la clase CSampleExpert que sean anunciadas con el modificador de acceso protected, sólo estarán accesibles dentro de los métodos de la clase CSampleExpert (y sus sucesores).
- double m_adjusted_point - es una variable-multiplicador para trabajar correctamente con cotizaciones de 3/5 dígitos;
- CTrade m_trade - es un ejemplar de clase СTrade;
- CSymbolInfo m_symbol - es un ejemplar de clase CSymbolInfo;
- CPositionInfo m_position - es un ejemplar de clase СPositionInfo;
- CAccountInfo m_account - es un ejemplar de clase CAccountInfo;
- int m_handle_macd - es la variable para almacenar el valor del handle del indicador MACD.
- int m_handle_ema - es la variable para almacenar el valor del handle del indicador EMA;
- double m_buff_MACD_main[] - es una matriz dinámica de valores del tipo double, se utiliza para solicitar los valores de la línea principal del indicador MACD;
- double m_buff_MACD_signal[] - es una matriz dinámica de valores del tipo double, se utiliza para solicitar los valores de la línea de señal del indicador MACD;
- double m_buff_EMA[] - es una matriz dinámica de valores del tipo double, se utiliza para solicitar los valores del indicador EMA;
- double m_macd_current - se usa para guardar el valor actual de la línea principal del indicador MACD;
- double m_macd_previous - se usa para guardar el valor anterior de la línea principal del indicador MACD;
- double m_signal_current - se usa para guardar el valor actual de la línea de señal del indicador MACD;
- double m_signal_previous - se usa para guardar el valor anterior de la línea señal del indicador MACD;
- double m_ema_current - se usa para guardar el valor actual del indicador EMA;
- double m_ema_previous se usa para guardar el valor anterior del indicador EMA;
- double m_macd_open_level,
- double m_macd_close_level,
- double m_traling_stop,
- double m_take_profit - se usa para guardar los valores de los niveles de precio (establecidos en los parámetros de entrada) teniendo en cuenta el multiplicador m_adjusted_point.
Métodos de clase CSampleExpert, declarados con el modificador de acceso protected:
- bool InitCheckParameters(const int digits_adjust) - comprueba la corrección de los parámetros de entrada y la inicialización de los parámetros de funcionamiento del experto;
- bool InitIndicators(void) - inicialización (creación) de los indicadores MACD y Moving Average;
- bool LongClosed(void) - retorna true (y cierra la posición larga abierta) al cumplirse las condiciones de cierre de una posición larga;
- bool ShortClosed(void) - retorna true (y cierra la posición corta abierta) al cumplirse las condiciones de cierre de una posición corta;
- bool LongModified(void) - retorna true (y modifica el precio Stop Loss) al cumplirse las condiciones de cambio de nivel Stop Loss de una posición larga abierta;
- bool ShortModified(void) - retorna true (y modifica el precio Stop Loss) al cumplirse las condiciones de cambio de nivel Stop Loss de una posición corta abierta;
- bool LongOpened(void) - retorna true (y abre una posición larga) al cumplirse las condiciones de apertura de una posición larga;
- bool ShortOpened(void) - retorna true (y abre una posición corta) al cumplirse las condiciones de apertura de una posición corta.
3.2. Constructor de clase CSampleExpert
//+------------------------------------------------------------------+ //| Constructor de clase CSampleExpert | //+------------------------------------------------------------------+ CSampleExpert::CSampleExpert(void) : m_adjusted_point(0), m_handle_macd(INVALID_HANDLE), m_handle_ema(INVALID_HANDLE), m_macd_current(0), m_macd_previous(0), m_signal_current(0), m_signal_previous(0), m_ema_current(0), m_ema_previous(0), m_macd_open_level(0), m_macd_close_level(0), m_traling_stop(0), m_take_profit(0) { ArraySetAsSeries(m_buff_MACD_main,true); ArraySetAsSeries(m_buff_MACD_signal,true); ArraySetAsSeries(m_buff_EMA,true); }
El constructor de clase se invoca de manera automática al crear un objeto-ejemplar de clase. Al llamarlo se establecen los valores por defecto (entre paréntesis) para las variables-miembros y se establece la dirección de indexación como en las series temporales para las matrices m_buff_MACD_main[], m_buff_MACD_signal[], m_buff_EMA[].
3.3. Destructor de clase CSampleExpert
//+------------------------------------------------------------------+ //| Destructor de clase CSampleExpert | //+------------------------------------------------------------------+ CSampleExpert::~CSampleExpert(void) { }
El destructor de clase CSampleExpert no contiene código.
3.4. Método Init de clase CSampleExpert
//+------------------------------------------------------------------+ //| Inicialización y comprobación de la corrección de los parámteros de entrada | //+------------------------------------------------------------------+ bool CSampleExpert::Init(void) { //--- establecer las propiedades generales m_symbol.Name(Symbol()); // instrumento m_trade.SetExpertMagicNumber(12345); // magic //--- cálculo de las cotizaciones de 3/5 dígitos int digits_adjust=1; if(m_symbol.Digits()==3 || m_symbol.Digits()==5) digits_adjust=10; m_adjusted_point=m_symbol.Point()*digits_adjust; //--- establecer los valores de los niveles, teniendo en cuenta el multiplicador m_adjusted_point m_macd_open_level =InpMACDOpenLevel*m_adjusted_point; m_macd_close_level=InpMACDCloseLevel*m_adjusted_point; m_traling_stop =InpTrailingStop*m_adjusted_point; m_take_profit =InpTakeProfit*m_adjusted_point; //--- establecer el deslizamiento en 3 puntos m_trade.SetDeviationInPoints(3*digits_adjust); //--- if(!InitCheckParameters(digits_adjust)) return(false); if(!InitIndicators()) return(false); //--- finalizado con éxito return(true); }
En el método Init() se lleva a cabo la inicialización de las variables de miembros-clase y se comprueba la corrección de los parámetros de entrada.
Al invocar el método Name() del objeto m_symbol (ejemplar de clase CSymbolInfo) se establece la denominación del instrumento en el que se inicia el asesor, después se invoca el método SetExpertMagicNumber(), que establece el valor del identificador del experto (magic) para el objeto m_trade (se utilizará al efectuar operaciones comerciales). Tras esto, con ayuda del método Digits() se solicita la cantidad de dígitos después de la coma del símbolo, y en caso necesario, la corrección de los valores de nivel.
A continuación se invoca el método SetDeviationInPoints() del objeto m_trade, en el que se establece la magnitud del deslizamiento permisible al efectuar operaciones comerciales.
3.5. Método InitCheckParameters de clase CSampleExpert
//+------------------------------------------------------------------+ //| Checking for input parameters | //+------------------------------------------------------------------+ bool CSampleExpert::InitCheckParameters(const int digits_adjust) { //--- comprobando la corrección del nivel Take Profit if(InpTakeProfit*digits_adjust<m_symbol.StopsLevel()) { printf("Take Profit must be greater than %d",m_symbol.StopsLevel()); return(false); } //--- comprobando la corrección del nivel Trailing Stop if(InpTrailingStop*digits_adjust<m_symbol.StopsLevel()) { printf("Trailing Stop must be greater than %d",m_symbol.StopsLevel()); return(false); } //--- comprobando la corrección del volumen comercial if(InpLots<m_symbol.LotsMin() || InpLots>m_symbol.LotsMax()) { printf("Lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10) { printf("Lots amount is not corresponding with lot step %f",m_symbol.LotsStep()); return(false); } //--- mostramos una advertencia si Take Profit<=Trailing Stop if(InpTakeProfit<=InpTrailingStop) printf("Warning: Trailing Stop must be less than Take Profit"); //--- finalizado con éxito return(true); }
En el método InitCheckParameters() se comprueba la corrección de los parámetros de entrada del asesor. Si algún parámetro tiene un valor inadmisible, entonces se muestra el mensaje correspondiente, y la función retorna false.
3.6. Método InitIndicators() de clase CSampleExpert
//+------------------------------------------------------------------+ //| Método de inicialización de indicadores | //+------------------------------------------------------------------+ bool CSampleExpert::InitIndicators(void) { //--- creación del indicador MACD if(m_handle_macd==INVALID_HANDLE) if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE) { printf("Error creating MACD indicator"); return(false); } //--- creación del indicador EMA if(m_handle_ema==INVALID_HANDLE) if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE) { printf("Error creating EMA indicator"); return(false); } //--- finalizado con éxito return(true); }
En el método InitIndicators() se comprueban los valores iniciales de las variables m_handle_macd y m_handle_ema (deben ser iguales a INVALID_HANDLE, ya que están inicializadas en el constructor) y se crean los indicadores técnicos MACD y Moving Average (con ayuda de las funciones iMACD y iMA). Si se finaliza con éxito, la función retorna true, y los handles de los indicadores se almacenan en los miembros de la clase m_handle_macd y m_handle_ema.
Los handles de los indicadores creados después serán utilizados para comprobar la cantidad de datos calculados (BarsCalculated) y obtener los valores numéricos (CopyBuffer) de los datos de los indicadores en el método Processing().
3.7. Método LongClosed() de clase CSampleExpert
//+------------------------------------------------------------------+ //| Comprobación de las condiciones de cierre de una posición larga | //+------------------------------------------------------------------+ bool CSampleExpert::LongClosed(void) { bool res=false; //--- ¿Hay que cerrar una posición? if(m_macd_current>0) if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous) if(m_macd_current>m_macd_close_level) { //--- cierre de posición if(m_trade.PositionClose(Symbol())) printf("Long position by %s to be closed",Symbol()); else printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment()); res=true; } //--- retornamos el resultado return(res); }
El método LongClosed() retorna true (y cierra la posición larga abierta) al cumplirse las condiciones de cierre de una posición larga:
- m_macd_current>0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por encima de la línea de cero);
- m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal desde arriba hacia abajo.
- m_macd_current>m_macd_close_level - el valor actual de la línea principal del indicador MACD es mayor que m_macd_close_level.
3.8. Método ShortClosed() de clase CSampleExpert
//+------------------------------------------------------------------+ //| Comprobación de las condiciones de cierre de una posición corta | //+------------------------------------------------------------------+ bool CSampleExpert::ShortClosed(void) { bool res=false; //--- ¿hay que cerrar la posición? if(m_macd_current<0) if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous) if(MathAbs(m_macd_current)>m_macd_close_level) { //--- cierre de posición if(m_trade.PositionClose(Symbol())) printf("Short position by %s to be closed",Symbol()); else printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment()); res=true; } //--- retornamos resultado return(res); }
El método ShortClosed() retorna true (y cierra la posición corta abierta) al cumplir las condiciones de cierre de una posición corta:
- m_macd_current<0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por debajo de la línea cero).
- m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal de abajo hacia arriba.
- MathAbs(m_macd_current)>m_macd_close_level - el valor actual de la línea principal del indicador MACD según el módulo es mayor a m_macd_close_level.
3.9. Método LongModified() de clase CSampleExpert
//+------------------------------------------------------------------+ //| Comprobación de las condiciones de modificación de la posición larga | //+------------------------------------------------------------------+ bool CSampleExpert::LongModified(void) { bool res=false; //--- comprobación de la necesidad de Trailing Stop if(InpTrailingStop>0) { if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop) { double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits()); double tp=m_position.TakeProfit(); if(m_position.StopLoss()<sl || m_position.StopLoss()==0.0) { //--- modificación de parámetros de la posición Stop Loss y Take Profit if(m_trade.PositionModify(Symbol(),sl,tp)) printf("Long position by %s to be modified",Symbol()); else { printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Modify parameters : SL=%f,TP=%f",sl,tp); } res=true; } } } //--- retornamos resultado return(res); }
El método LongModified() retorna true (y cambia el valor del parámetro de la posición Stop Loss) al cumplir las condiciones de la modificación de la posición larga. Si el valor del parámetro de entrada es InpTrailingStop>0, entonces se realiza la comprobación sobre el paso del precio por los puntos InpTrailingStop desde el precio de apertura en dirección a la posición. A continuación se calcula el nuevo valor del nivel Stop Loss y se modifica el parámetro Stop Loss de la posición abierta.
3.10. Método ShortModified de clase CSampleExpert
//+------------------------------------------------------------------+ //| Comprobación de las condiciones de modificación de la posición corta | //+------------------------------------------------------------------+ bool CSampleExpert::ShortModified(void) { bool res=false; //--- comprobación de la necesidad de trailing stop if(InpTrailingStop>0) { if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop)) { double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits()); double tp=m_position.TakeProfit(); if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0) { //--- modificación de los parámetros de la posición Stop Loss y Take Profit if(m_trade.PositionModify(Symbol(),sl,tp)) printf("Short position by %s to be modified",Symbol()); else { printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Modify parameters : SL=%f,TP=%f",sl,tp); } res=true; } } } //--- retornamos resultado return(res); }
El método ShotModified() retorna true (y cambia el valor del parámetro de la posición Stop Loss) al cumplir las condiciones de modificación de la posición corta. Si el valor del parámetro de entrada es InpTrailingStop>0, entonces se realiza la comprobación sobre el paso del precio por los puntos InpTrailingStop desde el precio de apertura en dirección a la posición. A continuación se calcula el nuevo valor del nivel Stop Loss y se modifica el parámetro Stop Loss de la posición abierta.
3.11. Método LongOpened() de clase CSampleExpert
//+------------------------------------------------------------------+ //| Check for long position opening | //+------------------------------------------------------------------+ bool CSampleExpert::LongOpened(void) { bool res=false; //--- comprobación de las condiciones de apertura de una posición larga if(m_macd_current<0) if(m_macd_current>m_signal_current && m_macd_previous<m_signal_previous) if(MathAbs(m_macd_current)>(m_macd_open_level) && m_ema_current>m_ema_previous) { double price=m_symbol.Ask(); double tp =m_symbol.Bid()+m_take_profit; //--- comprobación de la presencia de margen libre if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0) printf("We have no money. Free Margin = %f",m_account.FreeMargin()); else { //--- apertura de posición larga if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp)) printf("Position by %s to be opened",Symbol()); else { printf("Error opening BUY position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Open parameters : price=%f,TP=%f",price,tp); } } res=true; } //--- retornamos resultado return(res); }
El método LongOpened() retorna true (y abre una posición larga) en caso de que se cumplan las condiciones para la apertura de posición en la compra:
- m_macd_current<0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por debajo de la línea del cero);
- m_macd_current>m_signal_current && m_macd_previous<m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal de abajo hacia arriba;
- MathAbs(m_macd_current)>m_macd_open_level - el valor actual de la línea principal del indicador MACD según el módulo es mayor que m_macd_open_level;
- m_ema_current>m_ema_previous - ema crece.
Al cumplirse todas las condiciones se comprueba que haya margen suficiente (se usa el método FreeMarginCheck() de clase CAccountInfo de la Biblioteca estándar) y se abre una posición larga con ayuda del método PositionOpen() de clase CTrade.
3.12. Método ShortOpened de clase CSampleExpert
//+------------------------------------------------------------------+ //| Check for short position opening | //+------------------------------------------------------------------+ bool CSampleExpert::ShortOpened(void) { bool res=false; //--- comprobación de las condiciones de apertura de posición corta if(m_macd_current>0) if(m_macd_current<m_signal_current && m_macd_previous>m_signal_previous) if(m_macd_current>(m_macd_open_level) && m_ema_current<m_ema_previous) { double price=m_symbol.Bid(); double tp =m_symbol.Ask()-m_take_profit; //--- comprobamos que haya margen suficiente if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_SELL,InpLots,price)<0.0) printf("We have no money. Free Margin = %f",m_account.FreeMargin()); else { //--- apertura de una posición corta if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_SELL,InpLots,price,0.0,tp)) printf("Position by %s to be opened",Symbol()); else { printf("Error opening SELL position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Open parameters : price=%f,TP=%f",price,tp); } } res=true; } //--- retornamos resultado return(res); }
El método ShortOpened() retorna true (y abra una posición corta) en caso de que se cumplan las condiciones de apertura de posición para la venta:
- m_macd_current>0 - el valor actual de la línea principal del indicador MACD es positivo (el histograma MACD está por encima de la línea de cero);
- m_macd_current<m_signal_current && m_macd_previous>m_signal_previous - la línea principal del indicador MACD ha cruzado la línea de señal de arriba hacia abajo;
- m_macd_current>m_macd_open_level - el valor actual de la línea principal del indicador MACD es mayor que m_macd_open_level;
- m_ema_current<m_ema_previous - ema cae.
Cuando se cumplen todas las condiciones se comprueba la presencia de margen suficiente de medios (se usa el método FreeMarginCheck() de clase CAccountInfo de la Biblioteca estándar) y se abre una posición corta con ayuda del método PositionOpen() de clase CTrade.
3.13 Método Processing() de clase CSampleExpert
//+------------------------------------------------------------------+ //| main function returns true if any position processed | //+------------------------------------------------------------------+ bool CSampleExpert::Processing(void) { //--- actualización de cotizaciones if(!m_symbol.RefreshRates()) return(false); //--- actualización de los valores del indicador if(BarsCalculated(m_handle_macd)<2 || BarsCalculated(m_handle_ema)<2) return(false); if(CopyBuffer(m_handle_macd,0,0,2,m_buff_MACD_main) !=2 || CopyBuffer(m_handle_macd,1,0,2,m_buff_MACD_signal)!=2 || CopyBuffer(m_handle_ema,0,0,2,m_buff_EMA) !=2) return(false); //--- para simplificar el trabajo con los indicadores y la velocidad de acceso //--- los valores actuales de los indicadores se almacenan en las variables internas (miembros de clase) m_macd_current =m_buff_MACD_main[0]; m_macd_previous =m_buff_MACD_main[1]; m_signal_current =m_buff_MACD_signal[0]; m_signal_previous=m_buff_MACD_signal[1]; m_ema_current =m_buff_EMA[0]; m_ema_previous =m_buff_EMA[1]; //--- es importante entrar correctamente en el mercado, pero es aún más importante salir correctamente //--- primero comprobamos si hay alguna posición abierta if(m_position.Select(Symbol())) { if(m_position.PositionType()==POSITION_TYPE_BUY) { //--- si es necesario, intentamos cerrar o modificar la posición larga if(LongClosed()) return(true); if(LongModified()) return(true); } else { //--- si es necesario, intentamos cerrar o modificar la posición corta if(ShortClosed()) return(true); if(ShortModified()) return(true); } } //--- no hay posiciones abiertas else { //--- comprobamos las condiciones y si es necesario abrimos una posición larga if(LongOpened()) return(true); //--- comprobamos las condiciones y si es necesario abrimos una posición corta if(ShortOpened()) return(true); } //--- salimos sin procesar las posiciones return(false); }
El método Processing() de clase CSampleExpert es el método principal del asesor. La llamada del método Processing() se lleva a cabo durante el procesamiento del evento OnTick(), además se realiza el control del intervalo de tiempo (no inferior a los segundos de ExtTimeOut) entre las llamadas consecutivas de este método (apartado 2.2).
Con la llamada del método RefreshRates() de clase CSymbolInfo se lleva a cabo la actualización de las cotizaciones. Con la ayuda de la función BarsCalculated() se solicita la cantidad de barras para las que se han calculado los indicadores MACD y Moving Average (apartado 3.6.), si hay menos de 2 barras, entonces se produce la salida de la función y se retorna el valor false.
A continuación, con la llamada de la función CopyBuffer se lleva a cabo la solicitud de los dos últimos valores de los indicadores técnicos (de las líneas principal y de señal de MACD y los valores de Moving Average), si, además, la cantidad de datos copiados es inferior a dos, entonces se produce la salida de la función. Después, los valores de los indicadores de las matrices m_buff_MACD_main[], m_buff_MACD_signal[] y m_buff_EMA[] son copiados en las variables m_macd_current, m_macd_previous, m_signal_current, m_signal_previous, m_ema_current y m_ema_previous.
El siguiente paso es trabajar con la posición, este trabajo se lleva a cabo con la ayuda de la clase CPositionInfo de la Biblioteca estándar. Si la llamada del método Select() ha retornado true, esto significa que en el momento presente hay una posición abierta, su tipo se determina con la ayuda del método PositionType(). Después se realiza el trabajo correspondiente al tipo de posición abierta.
4. Simulación con datos históricos
Los mejores parámetros se pueden encontrar con ayuda del simulador de estrategias del terminal MetaTrader 5.
En la figura 3 se muestran los resultados de la simulación del asesor durante el año 2013 con los parámetros por defecto.
Figura 3. Resultados de la simulación con datos históricos del asesor MACD Sample
Conclusiones
El asesor MACD Sample, disponible en el terminal de cliente MetaTrader 5, supone un ejemplo del uso del enfoque orientado a objetos aplicado al desarrollo de asesores.
Traducción del ruso realizada por MetaQuotes Ltd
Artículo original: https://www.mql5.com/ru/code/2154
El indicador muestra el valor mínimo del precio durante el periodo establecido en los parámetros de entrada.
HIGHEST_HIGH_VALUEEl indicador muestra el valor máximo del precio durante el periodo establecido en los parámetros de entrada.
El indicador muestra el valor máximo del precio durante el periodo establecido en los parámetros de entrada del indicador, teniendo en cuenta el marco temporal en el que se lleva a cabo la búsqueda.
LOWEST_LOW_VALUE_HTFEl indicador muestra el valor mínimo del precio durante el periodo establecido en los parámetros de entrada del indicador, teniendo en cuenta el marco temporal en el que se lleva a cabo la búsqueda.