En este artículo intentaré explicarle y mostrarle cómo puede dominar, de forma fácil y rápida, los principios necesarios para crear Expert Advisors, 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 Expert Advisors.
El Expert Advisor y su estructura
Un Expert Advisor (EA) 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 Expert Advisor 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 EA puede dividirse visualmente en 4 partes, cada una de las cuales es responsable de una cierta parte del trabajo a realizar.
Permítanme explicarlo usando el ejemplo anterior. Tenemos un código de un Expert Advisor "vacío", un tipo de plantilla de Expert Advisor 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 EA (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 parámetro. Esta información puede observarse al iniciar el EA 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 EA.
Si la inicialización del EA 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 EA, 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 permite 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 EA, 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.
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 EA y obtener su controlador.
Examinémoslo más detenidamente,
La primera línea define una variables 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.
Después de escribir el código e iniciar el EA en el terminal, veremos (una vez que aparece el EA 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:
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? Pueden 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:
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.
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.
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:
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 hace 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 Expert Advisor 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 que 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 Expert Advisors 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: IncludeTrade y pueden añadirse usando #include.
Ejemplo:
Las clases anteriores pueden considerarse básicas, ya que la mayoría de Expert Advisors 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:
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 requieren un cierto conocimiento para ser usada?
A continuación les mostraré un ejemplo de solicitud de transacción realizada usando una librería:
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:
Reuniéndolo todo
Es hora de poner en práctica los conocimientos adquiridos con un Expert Advisor.
//+------------------------------------------------------------------+
//| 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"
//+------------------------------------------------------------------+
//| Función de inicialización del Expert |
//+------------------------------------------------------------------+
#include <TradeTrade.mqh> //incluye la librería para ejecutar las transacciones
#include <TradePositionInfo.mqh> //Incluye la librería para obtener información sobre las posiciones
int iMA_handle; //variable para almacenar el controlador del indicador
double iMA_buf[]; //matriz dinámica para almacenar los valores del indicador
double Close_buf[]; //matriz dinámica para almacenar el precio de cierre de cada barra
string my_symbol; //variable para almacenar el símbolo
ENUM_TIMEFRAMES my_timeframe; //variable para almacenar el período de tiempo
CTrade m_Trade; //estructura para la ejecución de las transacciones
CPositionInfo m_Position; //estructura para información sobre las posiciones
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
my_symbol=Symbol(); //guarda el símbolo del gráfico actual para operaciones posteriores del Expert Advisor en este símbolo
my_timeframe=PERIOD_CURRENT; //guarda el período actual del gráfico para operaciones posteriores del Expert Advisor en este símbolo
iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE); //aplica el indicador y obtiene su controlador
if(iMA_handle==INVALID_HANDLE) //comprueba la disponibilidad del controlador del indicador
{
Print("No hubo éxito al obtener el controlador del indicador" ); //si no se obtiene el controlador, escribe el mensaje de error en el archivo de registro
return(-1); //completa el control de error
}
ChartIndicatorAdd(ChartID(),0,iMA_handle); //añade el indicador al gráfico de precio
ArraySetAsSeries(iMA_buf,true); //establece el indexado de la matriz iMA_buf como series de tiempo
ArraySetAsSeries(Close_buf,true); //establece el indexado de la matriz Close_buf como series de tiempo
return(0); //return 0, initialization complete
}
//+------------------------------------------------------------------+
//| Función de deinicialización del Expert |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
IndicatorRelease(iMA_handle); //borra el controlador del indicador y elimina la signación del espacio de memoria que este ocupa
ArrayFree(iMA_buf); //libera la matriz dinámica iMA_buf de los datos
ArrayFree(Close_buf); //libera la matriz dinámica Close_buf de los datos
}
//+------------------------------------------------------------------+
//| Función tick del Expert |
//+------------------------------------------------------------------+
void OnTick()
{
int err1=0; //variable para almacenar los resultados del trabajo con el buffer del indicador
int err2=0; //variable para almacenar los resultados del trabajo con el gráfico de precio
err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf) ; //copia datos de la matriz del indiador en la matriz dinámica iMA_buf para trabajar con ellos posteriormente
err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf); //copia los datos del gráfico de precio en la matriz dinámica Close_buf para trabajar con ellos posteriormente
if(err1<0 || err2<0) //en caso de errores
{
Print("No hubo éxito al copiar los datos del indicador o del gráfico de precio" ); //escribe el mensaje de error en el archivo de registro
return; //y sale de la función
}
if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0]) //si los valores del indicador fueran mayores que el precio de cierre y se hicieran menores
{
if(m_Position.Select(my_symbol)) //si ya existe la posición para este símbolo
{
if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol) ; //y esta es una posición Sell, y por tanto la cierra
if(m_Position.PositionType()==POSITION_TYPE_BUY) return; //de lo contrario, si esta es una posición Buy entonces debe salir
}
m_Trade.Buy(0.1,my_symbol); //si hemos llegado hasta aquí significa que no hay posición, y por tanto la abrimos
}
if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0]) //si los valores del indicador fueran menores que el precio de cierre y se hicieran mayores
{
if(m_Position.Select(my_symbol)) //si existe la posición para este símbolo
{
if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol); //y esta es una posición Buy, y por tanto la cierra
if(m_Position.PositionType()==POSITION_TYPE_SELL) return; //de lo contrario, si esta es una posición Sell entonces debe salir
}
m_Trade.Sell(0.1,my_symbol); //si hemos llegado hasta aquí significa que no hay posición, y por tanto la abrimos
}
}
//+------------------------------------------------------------------+
Vamos a probar nuestro Expert Advisor con los parámetros de la siguiente forma:
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.
Las reducciones no pueden pasar inadvertidas. Sin embargo, este artículo no tiene por objetivo programar un "super Expert Advisor" 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 Expert Advisor cuando disponemos de unos conocimientos básicos.
Tenemos un Expert Advisor 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 Expert Advisor. 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.
El Expert Advisor y su estructura
Un Expert Advisor (EA) 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 Expert Advisor 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 EA puede dividirse visualmente en 4 partes, cada una de las cuales es responsable de una cierta parte del trabajo a realizar.

Figura 1. Los principales bloques de EA

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 Expert Advisor "vacío", un tipo de plantilla de Expert Advisor 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 EA (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 parámetro. Esta información puede observarse al iniciar el EA 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 EA.
Si la inicialización del EA 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 EA, 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 permite 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 EA, 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.
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 EA y obtener su controlador.
Examinémoslo más detenidamente,
La primera línea define una variables 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.

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

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 EA en el terminal, veremos (una vez que aparece el EA 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:
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? Pueden 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:
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.
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.
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:
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 hace 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 Expert Advisor 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 que 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 Expert Advisors 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: IncludeTrade y pueden añadirse usando #include.
Ejemplo:
Las clases anteriores pueden considerarse básicas, ya que la mayoría de Expert Advisors 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:
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 requieren un cierto conocimiento para ser usada?
A continuación les mostraré un ejemplo de solicitud de transacción realizada usando una librería:
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:
Reuniéndolo todo
Es hora de poner en práctica los conocimientos adquiridos con un Expert Advisor.
//+------------------------------------------------------------------+
//| 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"
//+------------------------------------------------------------------+
//| Función de inicialización del Expert |
//+------------------------------------------------------------------+
#include <TradeTrade.mqh> //incluye la librería para ejecutar las transacciones
#include <TradePositionInfo.mqh> //Incluye la librería para obtener información sobre las posiciones
int iMA_handle; //variable para almacenar el controlador del indicador
double iMA_buf[]; //matriz dinámica para almacenar los valores del indicador
double Close_buf[]; //matriz dinámica para almacenar el precio de cierre de cada barra
string my_symbol; //variable para almacenar el símbolo
ENUM_TIMEFRAMES my_timeframe; //variable para almacenar el período de tiempo
CTrade m_Trade; //estructura para la ejecución de las transacciones
CPositionInfo m_Position; //estructura para información sobre las posiciones
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
my_symbol=Symbol(); //guarda el símbolo del gráfico actual para operaciones posteriores del Expert Advisor en este símbolo
my_timeframe=PERIOD_CURRENT; //guarda el período actual del gráfico para operaciones posteriores del Expert Advisor en este símbolo
iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE); //aplica el indicador y obtiene su controlador
if(iMA_handle==INVALID_HANDLE) //comprueba la disponibilidad del controlador del indicador
{
Print("No hubo éxito al obtener el controlador del indicador" ); //si no se obtiene el controlador, escribe el mensaje de error en el archivo de registro
return(-1); //completa el control de error
}
ChartIndicatorAdd(ChartID(),0,iMA_handle); //añade el indicador al gráfico de precio
ArraySetAsSeries(iMA_buf,true); //establece el indexado de la matriz iMA_buf como series de tiempo
ArraySetAsSeries(Close_buf,true); //establece el indexado de la matriz Close_buf como series de tiempo
return(0); //return 0, initialization complete
}
//+------------------------------------------------------------------+
//| Función de deinicialización del Expert |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
IndicatorRelease(iMA_handle); //borra el controlador del indicador y elimina la signación del espacio de memoria que este ocupa
ArrayFree(iMA_buf); //libera la matriz dinámica iMA_buf de los datos
ArrayFree(Close_buf); //libera la matriz dinámica Close_buf de los datos
}
//+------------------------------------------------------------------+
//| Función tick del Expert |
//+------------------------------------------------------------------+
void OnTick()
{
int err1=0; //variable para almacenar los resultados del trabajo con el buffer del indicador
int err2=0; //variable para almacenar los resultados del trabajo con el gráfico de precio
err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf) ; //copia datos de la matriz del indiador en la matriz dinámica iMA_buf para trabajar con ellos posteriormente
err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf); //copia los datos del gráfico de precio en la matriz dinámica Close_buf para trabajar con ellos posteriormente
if(err1<0 || err2<0) //en caso de errores
{
Print("No hubo éxito al copiar los datos del indicador o del gráfico de precio" ); //escribe el mensaje de error en el archivo de registro
return; //y sale de la función
}
if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0]) //si los valores del indicador fueran mayores que el precio de cierre y se hicieran menores
{
if(m_Position.Select(my_symbol)) //si ya existe la posición para este símbolo
{
if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol) ; //y esta es una posición Sell, y por tanto la cierra
if(m_Position.PositionType()==POSITION_TYPE_BUY) return; //de lo contrario, si esta es una posición Buy entonces debe salir
}
m_Trade.Buy(0.1,my_symbol); //si hemos llegado hasta aquí significa que no hay posición, y por tanto la abrimos
}
if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0]) //si los valores del indicador fueran menores que el precio de cierre y se hicieran mayores
{
if(m_Position.Select(my_symbol)) //si existe la posición para este símbolo
{
if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol); //y esta es una posición Buy, y por tanto la cierra
if(m_Position.PositionType()==POSITION_TYPE_SELL) return; //de lo contrario, si esta es una posición Sell entonces debe salir
}
m_Trade.Sell(0.1,my_symbol); //si hemos llegado hasta aquí significa que no hay posición, y por tanto la abrimos
}
}
//+------------------------------------------------------------------+
Vamos a probar nuestro Expert Advisor con los parámetros de la siguiente forma:
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.

Figura 6. Nuestros resultados de las pruebas del Expert Advisor
Las reducciones no pueden pasar inadvertidas. Sin embargo, este artículo no tiene por objetivo programar un "super Expert Advisor" 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 Expert Advisor cuando disponemos de unos conocimientos básicos.
Tenemos un Expert Advisor 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 Expert Advisor. 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.

