Descargar MetaTrader 5

Una breve guía de inicio rápido para principiantes

27 diciembre 2013, 07:18
Dmitriy Parfenovich
0
1 238

Introducción

¡Hola, apreciado lector! En este artículo intentaré explicarle y mostrarle cómo puede dominar, de forma fácil y rápida, los principios necesarios para crear asesores expertos, trabajar con indicadores, etc. Está destinado a principiantes y no se utilizarán ejemplos difíciles o complejos. Por tanto, el artículo puede que no sea muy inspirador o informativo para aquellos que ya saben cómo programar asesores expertos.

El asesor experto y su estructura

Un asesor experto es un programa escrito en lenguaje MQL que especifica las condiciones para realizar la transacción o mantenerse al margen.

Básicamente, la estructura de un asesor experto puede estar formada por un gran número de bloques, pero para que sea más fácil entenderlo voy a realizar un ejemplo muy sencillo generado por defecto en MetaEditor.

Todo el asesor experto puede dividirse visualmente en 4 partes, cada una de las cuales es responsable de una cierta parte del trabajo a realizar.

Los principales bloques de EA 
Figura 1. Los principales bloques de un asesor experto

  1. El bloque prámetros (block of parameters) contiene información para el terminal, permitiendo a este gestionar el asesor experto de forma adecuada. Los parámetros más habituales son la versión de asesor experto, el nombre del fabricante y una breve descripción.

  2. El bloque OnInit() obtiene el control una vez que el asesor experto es cargado en el terminal. Puede contener varios datos relacionados con la inicialización del asesor experto (declarando variables y matrices, obteniendo controladores de indicador, etc.). Es decir, este bloque no tiene ninguna función directamente asociada con el trading.

  3. El bloque OnDeinit() actúa de forma contraria al bloque OnInit(). Es llamada cuando el asesor experto completa su operación (apagado del asesor experto/terminal o inicialización sin éxito de un asesor experto). Una de las principales funciones de este bloque es la revocación de la asignación previa de memoria ocupada por el asesor experto cuando ya no es necesario. En otras palabras, describe los procesos de borrado de variables, matrices y controladores de indicador, etc.

  4. El bloque OnTick() es llamado cada vez que se recibe nueva información en el símbolo (par de divisas) desde el servidor. Especifica condiciones para realizar las transacciones y funciones de trading.

Ejemplo de un nuevo documento generado por defecto en MetaEditor
   Figura 2. Ejemplo de un nuevo documento generado por defecto en MetaEditor


Permítanme explicarlo usando el ejemplo anterior. Tenemos un código de un asesor experto "vacío", un tipo de plantilla de asesor experto que va a necesitar ser rellenada posteriormente.

Lo que podemos ver aquí es lo siguiente:

  • las primeras cinco líneas (líneas 1 a 5) representan comentarios que contienen el nombre del asesor experto (nombre del archivo), el nombre del fabricante y su sitio web. Puede escribir aquí cualquier cosa que desee. Este texto no se mostrará en ningún sitio e incluso puede obviarse. La información que contiene solo va dirigida al programador;

  • las siguientes 3 líneas (líneas 6 a 8) representan el bloque de parámetros. Esta información puede observarse al iniciar el asesor experto en el terminal;

  • va seguida por la función OnInit() (líneas 12 a 19). Este es el bloque OnInit(). Esta función no obtiene ningún parámetro pero devuelve (aunque puede que no) el código de inicialización;

  • la función OnDeinit (cost int reason) va a continuación (líneas 22 a 26). Este es el bloque OnDeinit(). Tiene un parámetro que especifica la causa del cierre del asesor experto.
    Si la inicialización del asesor experto no tiene éxito, esta función recibe un código relevante como parámetro.

  • la última función es OnTick() (líneas 30 a 34). Este fue el bloque OnTick() descrito anteriormente. Puede decirse que este bloque es el "cerebro" del asesor experto, ya que comprende todas las funciones encargadas de las transacciones.

Como dije antes, la estructura puede ser mucho más compleja y estar compuesta de una gran cantidad de bloques, al contrario de lo que ocurre con este sencillo ejemplo. Cuando crea que esto no es suficiente, puede añadir sus propios bloques,
 

Indicadores y cómo gestionarlos

Los indicadores son pequeños programas escritos en MQL que se muestran en el gráfico del precio o en una ventana separada bajo el gráfico del precio, y nos permiten realizar análisis técnicos del mercado.

Todos los indicadores pueden clasificarse en dos tipos: indicadores que siguen una tendencia y osciladores.

Los indicadores que siguen una tendencia son, por regla general, dibujados en el gráfico del precio y se usan para identificar la dirección de la tendencia, mientras que los osciladores se suelen mostrar bajo el gráfico del precio y sirven para identificar los puntos de entrada.

La mayoría de los indicadores tienen al menos un buffer (indicador buffer) que contiene sus datos de lectura en un momento determinado. Al igual que los asesores expertos, el indicador tiene su símbolo y período de tiempo en el que es calculado.

El buffer del indicador puede considerarse como una cola cuyo último elemento es un valor en ejecución.

Ejemplo del indicador media móvil
   Figura 3. Ejemplo del indicador media móvil

El buffer de indicador es una matriz donde el primer elemento (con índice 0) lleva datos en la vela más a la derecha y el siguiente elemento (con índice 1) lleva datos en la segunda vela a la derecha, etc. Tal disposición de elementos se llama series de tiempo.

Observe el ejemplo siguiente:

Asumamos que el par de divisas que tenemos es EUR/USD, el período de tiempo es 1 hora.
En primer lugar necesitamos añadir el indicador al asesor experto y obtener su controlador.

Handle es un puntero único para el indicador que nos permite utilizar ese indicador en cualquier lugar del programa.

int iMA_handle; 
iMA_handle=iMA("EURUSD",PERIOD_H1,10,0,MODE_SMA,PRICE_CLOSE);
Examinémoslo más detenidamente,

La primera línea define una variable que va a almacenar el controlador del indicador. La segunda línea llama al indicador (llamado aquí el indicador de media móvil), especifica sus parámetros y guarda el controlador en la variable para usarlo en el futuro.
Tras teclear "iMA(" en MetaEditor, aparecerá un mensaje de ayuda sobre esa línea mostrando los parámetros de llamada separados por comas.

Ejemplo del mensaje de ayuda para los parámetros del indicador media móvil
   Figura 4. Ejemplo del mensaje de ayuda para los parámetros del indicador media móvil

Podemos ver los siguientes parámetros listados de izquierda a derecha:

  1. el nombre del símbolo (aparece en negrita en el mensaje de ayuda) es un parámetro de texto de par de divisas (símbolo);
  2. período de tiempo;
  3. período del indicador (llamado aquí el período promedio);
  4. desplazamiento del gráfico en N barras hacia adelante/atrás. Un número positivo indica el desplazamiento del gráfico en N barras hacia adelante, mientras que un número negativo indica un desplazamiento del gráfico en N barras hacia atrás;
  5. método de promediación;
  6. precio aplicado o un controlador de un indicador diferente.

Hay un único conjunto de variables y sus correspondientes tipos para cada indicador. Si se encuentra con un indicador desconocido, puede siempre encontrar información sobre el mismo en la ayuda contextual. Por ejemplo, una vez que ha tecleado iMA y presionado F1, se abrirá una ventana de ayuda proporcionando información sobre ese indicador específico y una descripción detallada de todas sus propiedades.

Ejemplo de llamada a la ventana de ayuda para la descripción del indicador presionando F1
   Figura 5. Ejemplo de llamada a la ventana de ayuda para la descripción del indicador presionando F1

Después de escribir el código e iniciar el asesor experto en el terminal, veremos (una vez que aparece el asesor experto en la esquina superior derecha del gráfico de precio) que el indicador no se encuentra en el gráfico. Esto no es un error, estaba previsto. Para que aparezca necesitamos añadir otra línea:

ChartIndicatorAdd(ChartID(),0,iMA_handle);

Veamos ahora cómo funciona. Pase el cursor sobre el comando ChartIndicatorAdd y presione F1 para leer la información de ayuda sobre la finalidad del comando. Puede leerse que este comando:

Añade un indicador con el controlador especificado en la ventana de gráfico indicada.

El segundo parámetro, que es igual a cero, es el número de subventana. Las subventanas contienen, normalmente, osciladores bajo el gráfico del precio. ¿Se acuerda? Puede haber muchos. Para mostrar el indicador en la subventana, solo necesita especificar el número de subventana de forma que sea mayor que el número existente en 1, es decir, el número que sigue al último existente.

Habiendo cambiado el código de la siguiente forma:

ChartIndicatorAdd(ChartID(),1,iMA_handle);

nuestro indicador aparecerá en la subventana bajo el gráfico del precio.

Ahora es el momento de intentar conseguir algunos datos del indicador. Para ello, vamos a declarar una matriz dinámica, realizaremos un indexado de la matriz como series de tiempo por comodidad y copiaremos los valores del indicador en esta matriz.

double iMA_buf[];
ArraySetAsSeries(iMA_buf,true);
CopyBuffer(iMA_handle,0,0,3,iMA_buf);

El ejemplo anterior muestra que hemos declarado la matriz dinámica iMA_buf[] de tipo doble, ya que el indicador de media móvil se basa en precios y los precios tienen números fraccionarios.

La siguiente línea establece el indexado para la matriz, de forma que los elementos con menores índices almacenan valores más antiguos, mientras que los elementos con mayores índices almacenan valores más recientes. Este se utiliza por comodidad para evitar confusiones, ya que los buffers de indicador en todos los indicadores son indexados como series de tiempo.

La última línea sirve para copiar los valores del indicador en la matriz iMA_buf[]. Estos datos se encuentran ahora disponibles para ser usados. 

 

Órdenes, transacciones y posiciones

Comencemos con las órdenes.

  • Las órdenes son solicitudes de transacciones aceptadas por el servidor de transacciones. Si la solicitud no es válida, será rechazada.
    Para evitar la dificultad de rellenar la solicitud de transacción, mostraré más adelante cómo puede realizarse esto utilizando las librerías estándar y haciéndolo mucho más fácil
    Hay dos tipos de órdenes: de mercado (para ejecución inmediata) y pendientes.
Las órdenes de mercado representan instrucciones para vender o comprar una cierta cantidad de instrumentos financieros al precio actual de mercado.
Las órdenes pendientes representan instrucciones para ejecutar la transacción sujetas a ciertas condiciones. Las órdenes pendientes tienen un cierto período de caducidad que, una vez cumplido, supone su borrado.
  • Las transacciones representan los resultados de la ejecución de órdenes (instrucciones para ejecutar una transacción). Cada transacción se basa en una determinada orden, mientras que una orden puede dar como resultado múltiples transacciones. Por ejemplo, una orden para comprar 10 lotes puede ser cursada por la ejecución parcial de un determinado número de transacciones consecutivas. Las transacciones se almacenan siempre en el historial de transacciones y no pueden modificarse. El terminal muestra las transacciones en la pestaña "Historial".
  • Las posiciones representan el resultado de las órdenes en acción. Solo puede abrirse una posición, ya sea larga o corta, para cada símbolo.

Para dejarlo más claro, permítanme ilustrarlo con un ejemplo: abrimos una posición larga de 1 lote, es decir, cursamos una orden al precio actual de mercado (por ejemplo) y del tamaño de 1 lote. Si la solicitud es válida será enviada al servidor para ser procesada. Tan pronto como se complete su procesamiento, aparecerá una posición en la pestaña "Transacción" del terminal. Supongamos que decidimos abrir otra posición larga de tamaño 1 lote. Siguiendo el procesamiento de la orden, no veremos dos órdenes en la pestaña "Tab" sino una posición de tamaño igual a 2 lotes. Es decir, la posición es el resultado de la ejecución de un número de órdenes.

Vamos ahora a realizar un ejercicio práctico. Los siguientes campos de la estructura requieren ser rellenados para realizar una solicitud:

struct MqlTradeRequest
{
ENUM_TRADE_REQUEST_ACTIONS action; // Type of action
ulong magic; // Expert Advisor ID (magic number)
ulong order; // Order ticket
string symbol; // Trade instrument
double volume; // Requested trade size in lots
double price; // Price 
double stoplimit; // StopLimit level of the order
double sl; // Stop Loss level of the order
double tp; // Take Profit level of the order
ulong deviation; // Maximum allowed deviation from the requested price
ENUM_ORDER_TYPE type; // Order type
ENUM_ORDER_TYPE_FILLING type_filling; // Order type by execution
ENUM_ORDER_TYPE_TIME type_time; // Order type by duration
datetime expiration; // Order expiration time (for orders of the ORDER_TIME_SPECIFIED type)
string comment; // Comment to the order
};

Al haber varias órdenes, cada una de ellas tiene su propio conjunto de parámetros obligatorios. No voy a extenderme demasiado en este punto. El sitio web proporciona una gran cantidad de información al respecto. Si no se especifica o se incluye incorrectamente alguno de los parámetros obligatorios para un determinado tipo de orden, la solicitud será fallida.

Hemos visto aquí la estructura anterior para poder mostrar la dificultad que conlleva construirla.

Stop Loss y Take Profit

Stop Loss y Take Profit son órdenes especiales que se cursan como "medida de seguridad". Es decir, en caso de errores o de posiciones abiertas por un asesor experto y que muestran una pérdida, la orden Stop Limit puede limitar las pérdidas hasta un cierto nivel predefinido.

La orden Take Profit funciona de forma similar aunque, en este caso, solo limita el beneficio. Puede ser de ayuda para evitar tener que preocuparse por cerrar una posición. Se cerrará cuando se alcance un cierto nivel de precio. En otras palabras, estas órdenes representan nuestro "plan de seguros" en caso de que el mercado se vuelva en nuestra contra o queramos retirar beneficios.

Este tipo de órdenes no pueden ser cursadas por sí solas de forma independiente, ya que solo pueden modificar posiciones ya existentes.

Usar librerías estándar

Hemos llegado por fin a la librería estándar. Esta librería viene incluida en el terminal, de ahí el nombre "librería estándar". Comprende funciones que facilitan la programación de asesores expertos y llevar a cabo procesos complejos parcialmente, como por ejemplo la generación de solicitudes de transacciones.

Las solicitudes de transacciones (véase también clases de transacciones) se encuentran en el siguiente directorio: Include\Trade\, y pueden añadirse usando #include.

Ejemplo:

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>

Las clases anteriores pueden considerarse básicas, ya que la mayoría de asesores expertos pueden ser programados usando solo estas dos clases (librerías). Las llamo librerías:

  • La primera está pensada para su uso con órdenes cursadas y para modificar órdenes.
  • La segunda sirve para obtener información sobre posiciones existentes.

Algunas veces puede ser útil usar otra librería:
#include <Trade\OrderInfo.mqh>
Contiene funciones para trabajar con órdenes en caso de que, digamos, nuestra estrategia requiera el uso de órdenes pendientes.

¿Recuerda la estructura de la solicitud de transacción repleta de parámetros que requiere un cierto conocimiento para ser usada?

A continuación les mostraré un ejemplo de solicitud de transacción realizada usando una librería:

CTrade m_Trade;
m_Trade.Sell(lot,symbol_name,price,sl,tp,comment);

Aquí hay un total de 6 parámetros, donde solo uno de ellos es obligatorio (el tamaño de la orden, que es el primer parámetro).
Voy a especificar a continuación cada uno de ellos:

  • lot es el tamaño de la orden que se va a cursar;
  • symbol_name es el símbolo (par de divisas) al que se aplica la orden (si no se especifica ninguno se utiliza el símbolo actual del asesor experto);
  • price es el precio de apertura (ya que al ser esta la función para abrir una orden activa, su precio puede no estar especificado, en cuyo caso este se obtendrá automáticamente del gráfico de precio);
  • sl es el precio al que se cerrará la orden, siempre que el precio no esté a nuestro favor (puede omitirse si la estrategia no implica el uso de la orden Stop Loss);
  • tp es el precio al que se cerrará la orden, siempre que el precio siga la dirección requerida, es decir, que este dé beneficios (puede omitirse si la estrategia no implica el uso de la orden Take Profit);
  • comment es el comentario a la orden, por ejemplo especificando la razón por la que esta se ha cursado.

Hay varias formas de cerrar una posición:

  1. cerrar la posición completamente
    CPositionInfo m_Position;
    m_Position.Select(symbol_name);
    m_Trade.PositionClose(symbol_name);
  2. para cerrar la posición cursando una orden inversa del mismo tamaño
    CTrade m_Trade;
    m_Trade.Buy(lot,symbol_name,price,sl,tp,comment);
  3. usando un método más complejo por el que se busca entre todas las posiciones abiertas aquella que cumple los parámetros requeridos (símbolo, tipo, número mágico, identificador de posición, etc.) para ser cerrada.
    No voy a dar ningún ejemplo de lo anterior ya que resultaría de cierta dificultad para los principiantes.

Reuniéndolo todo

Es hora de poner en práctica los conocimientos adquiridos con un asesor experto.

//+------------------------------------------------------------------+
//|                                           fast-start-example.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>                                         //include the library for execution of trades
#include <Trade\PositionInfo.mqh>                                  //include the library for obtaining information on positions

int               iMA_handle;                              //variable for storing the indicator handle
double            iMA_buf[];                               //dynamic array for storing indicator values
double            Close_buf[];                             //dynamic array for storing the closing price of each bar

string            my_symbol;                               //variable for storing the symbol
ENUM_TIMEFRAMES   my_timeframe;                             //variable for storing the time frame

CTrade            m_Trade;                                 //structure for execution of trades
CPositionInfo     m_Position;                              //structure for obtaining information of positions
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   my_symbol=Symbol();                                      //save the current chart symbol for further operation of the EA on this very symbol
   my_timeframe=PERIOD_CURRENT;                              //save the current time frame of the chart for further operation of the EA on this very time frame
   iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE);  //apply the indicator and get its handle
   if(iMA_handle==INVALID_HANDLE)                            //check the availability of the indicator handle
   {
      Print("Failed to get the indicator handle");              //if the handle is not obtained, print the relevant error message into the log file
      return(-1);                                           //complete handling the error
   }
   ChartIndicatorAdd(ChartID(),0,iMA_handle);                  //add the indicator to the price chart
   ArraySetAsSeries(iMA_buf,true);                            //set iMA_buf array indexing as time series
   ArraySetAsSeries(Close_buf,true);                          //set Close_buf array indexing as time series
   return(0);                                               //return 0, initialization complete
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(iMA_handle);                             //deletes the indicator handle and deallocates the memory space it occupies
   ArrayFree(iMA_buf);                                      //free the dynamic array iMA_buf of data
   ArrayFree(Close_buf);                                    //free the dynamic array Close_buf of data
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int err1=0;                                             //variable for storing the results of working with the indicator buffer
   int err2=0;                                             //variable for storing the results of working with the price chart
   
   err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf);               //copy data from the indicator array into the dynamic array iMA_buf for further work with them
   err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf);    //copy the price chart data into the dynamic array Close_buf for further work with them
   if(err1<0 || err2<0)                                    //in case of errors
   {
      Print("Failed to copy data from the indicator buffer or price chart buffer");  //then print the relevant error message into the log file
      return;                                                               //and exit the function
   }

   if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0])   //if the indicator values were greater than the closing price and became smaller
     {
      if(m_Position.Select(my_symbol))                     //if the position for this symbol already exists
        {
         if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol);  //and this is a Sell position, then close it
         if(m_Position.PositionType()==POSITION_TYPE_BUY) return;                              //or else, if this is a Buy position, then exit
        }
      m_Trade.Buy(0.1,my_symbol);                          //if we got here, it means there is no position; then we open it
     }
   if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0])  //if the indicator values were less than the closing price and became greater
     {
      if(m_Position.Select(my_symbol))                     //if the position for this symbol already exists
        {
         if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol);   //and this is a Buy position, then close it
         if(m_Position.PositionType()==POSITION_TYPE_SELL) return;                             //or else, if this is a Sell position, then exit
        }
      m_Trade.Sell(0.1,my_symbol);                         //if we got here, it means there is no position; then we open it
     }
  }
//+------------------------------------------------------------------+

Vamos a probar nuestro asesor experto con los parámetros de la siguiente forma:

  • símbolo - EURUSD;
  • período - H1;
  • modo de transacción "solo precios de apertura". 

Como usamos los valores del indicador y los precios de cierre comenzando con la primera barra (la barra cero es una barra actual y activa), el gráfico no se volverá a representar. Esto significa que podemos usar el modo de transacción "solo precios de apertura". No afectará a la calidad de la prueba pero hará que se ejecute más rápido.

Y estos son los resultados de las pruebas usando los datos históricos. 

Nuestros resultados de las pruebas del Expert Advisor
   Figura 6. Nuestros resultados de las pruebas del asesor experto

Las reducciones no pueden pasar inadvertidas. Sin embargo, este artículo no tiene por objetivo programar un "super asesor experto" que pueda tener un gran potencial de generar beneficios con una mínima reducción sino, más bien, mostrar lo fácil que puede ser elaborar un asesor experto cuando disponemos de unos conocimientos básicos.
Tenemos un asesor experto de menos de un centenar de líneas de código.
 

Conclusión

Este artículo cubre los principios fundamentales que deben considerarse a la hora de programar un asesor experto. Hemos aprendido cómo usar la ayuda contextual de MetaEditor 5 para obtener información de varias funciones, la idea general de los conceptos de órdenes y posiciones, y finalmente hemos abordado el uso de las librerías estándar.


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

Archivos adjuntos |
Estrategias con órdenes Expert Advisor multiuso Estrategias con órdenes Expert Advisor multiuso

Este artículo se centra en torno a las estrategias que activamente usan órdenes pendientes, un metalenguaje que puede usarse para describir formalmente tales estrategias, así como en el uso de un Expert Advisor multiuso cuya operativa se basa en dichas descripciones.

Sistemas de trading simples usando indicadores semáforo Sistemas de trading simples usando indicadores semáforo

Si examinamos en profundidad cualquier sistema de trading complejo veremos que está basado en un conjunto de simples señales de trading. Por tanto, no es necesario que los programadores con menos experiencia comiencen a escribir complejos algorítmicos inmediatamente. Este artículo proporciona un ejemplo de un sistema de trading que utiliza indicadores semáforo para realizar las transacciones.

¿Cómo comprar robots en MetaTrader Market? ¿Cómo comprar robots en MetaTrader Market?

La compra de cualquier producto (ya sean robots, indicadores) en MetaTrader Market`е se lleva a cabo sólo desde las plataformas comerciales MetaTrader 4 y MetaTrader 5. En la página MQL5.com puede usted familiarizarse con la lista de productos y su descripción, pero igualmente con el botón "Comprar" se pondrá en marcha el terminal de cliente.

Cómo suscribirse a las Señales Comerciales Cómo suscribirse a las Señales Comerciales

Las "Señales" constituyen el trading social con MetaTrader 4 y MetaTrader 5. El servicio está directamente integrado en la plataforma comercial, y permite a cualquiera copiar fácilmente las operaciones comerciales de los traders profesionales. De los miles de proveedores, elija al que más le guste, suscríbase a él con tan solo unos clicks, y las operaciones comenzarán a copiarse a su cuenta al instante.