¡Bienvenido al Tutorial de MQL5!
Este material está diseñado para traders y desarrolladores que ya tienen nociones básicas de programación (variables, bucles, condicionales, etc.). Aunque repasaremos los comandos y estructuras principales de MQL5, el enfoque está en aplicar conceptos prácticos para desarrollar Expert Advisors (EAs), indicadores y scripts.
Si eres completamente nuevo en programación, te recomendamos:
- Consultar la documentación oficial de MQL5 para comprender los fundamentos del lenguaje.
- Practicar con los 60+ ejercicios y ejemplos resueltos de este tutorial, que van desde lo básico hasta lo avanzado.
- Empezar con proyectos simples (como indicadores básicos o scripts de alertas) antes de abordar EAs complejos.
Este tutorial no solo te enseñará a codificar, sino que también te guiará en la implementación de estrategias reales, gestión de riesgos y optimización. ¡Manos a la obra!
¡Importante!
Si en algún momento te sientes perdido, recuerda que la práctica constante y la experimentación son clave en el aprendizaje de MQL5. No dudes en revisar los ejemplos paso a paso y adaptarlos a tus propias estrategias.
¡Esperamos que disfrutes este tutorial y que te conviertas en un experto en MQL5! 🚀
Sumario:
- Sección 1: Introducción a MQL5
- ¿Qué es MQL5?
- Configuración del Entorno de Desarrollo
- Conceptos Fundamentales de Programación
- Sección 2: Fundamentos de Programación en MQL5
- Estructura Básica de un Script en MQL5
- Trabajando con Datos del Mercado
- Gestión de Posiciones y Órdenes
- Manipulación de Símbolos y Cuentas
- Sección 3: Construcción de Estrategias Automatizadas
- Creación de un Expert Advisor Básico
- Optimización de Código
- Pruebas y Backtesting
- Sección 4: Temas Intermedios
- Indicadores Personalizados
- Gestión Avanzada de Riesgos
- Notificaciones y Logs
- Trabajo con Arrays y Matrices
- Sección 5: Mejoras y Herramientas Adicionales
- Uso de Bibliotecas y Scripts Externos
- Integración con Servicios Externos
- Depuración y Mantenimiento
- Sección 6: Caso Práctico Completo
- Desarrollo de un EA Completo
- Publicación y Comercialización
- Anexos
- Recursos Adicionales
- Referencia de Funciones
- Glosario de Términos
Sección 2: Fundamentos de Programación en MQL5
Capítulo 4: Estructura Básica de un Script en MQL5
En este capítulo, exploraremos la estructura básica de un script en MQL5 y cómo funcionan las funciones principales que definen el ciclo de vida de un programa: OnInit(), OnDeinit() y OnTick(). Estas funciones son esenciales para cualquier tipo de aplicación en MQL5, ya sea un script, un indicador personalizado o un Expert Advisor.
4.1. Función OnInit() (Inicialización)
La función OnInit() se ejecuta una sola vez cuando el script, indicador o EA se inicia. Es ideal para realizar tareas de configuración inicial, como cargar datos, verificar condiciones o inicializar variables.
Ciclo de Vida:
- Se llama automáticamente al iniciar el programa.
- Si ocurre un error durante la inicialización, el programa no continuará su ejecución.
Ejemplo práctico: Verificamos si el símbolo actual está disponible antes de continuar.
//+------------------------------------------------------------------+
//| Inicialización del programa |
//+------------------------------------------------------------------+
int OnInit() {
if (!SymbolExists(_Symbol)) {
Print("El símbolo ", _Symbol, " no está disponible.");
return(INIT_FAILED); // Devolvemos un código de error
}
Print("Programa iniciado correctamente con el símbolo: ", _Symbol);
return(INIT_SUCCEEDED); // Indicamos que la inicialización fue exitosa
}
Explicación del Código:
- Usamos
SymbolExists()para verificar si el símbolo está disponible. - Si no está disponible, devolvemos
INIT_FAILEDpara detener la ejecución. - En caso contrario, mostramos un mensaje de éxito y retornamos
INIT_SUCCEEDED.
4.2. Función OnDeinit() (Finalización)
La función OnDeinit() se ejecuta cuando el programa termina su ejecución. Es útil para liberar recursos, cerrar archivos o guardar datos antes de finalizar.
Ciclo de Vida:
- Se llama automáticamente al cerrar el programa.
- Puede ser utilizado para limpiar recursos o realizar acciones finales.
Ejemplo práctico: Guardamos un registro de cuándo se cerró el programa.
//+------------------------------------------------------------------+
//| Finalización del programa |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
Print("Programa finalizado. Razón: ", EnumToString((ENUM_DEINIT_REASON)reason));
// Ejemplo: Guardar información en un archivo
CFileText file;
if (file.Open("log.txt", FILE_WRITE)) {
file.WriteLine("El programa se cerró el " + TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS));
file.Close();
}
}
Explicación del Código:
- Usamos
EnumToString()para convertir el motivo de la desinicialización (reason) en una cadena legible. - Creamos un archivo de texto llamado
log.txty registramos la hora de cierre del programa.
4.3. Función OnTick() (Procesamiento de Ticks)
La función OnTick() se ejecuta cada vez que llega un nuevo tick de precio para el símbolo seleccionado. Esta es la función principal en los Expert Advisors y scripts que requieren procesar datos en tiempo real.
Ciclo de Vida:
- Se llama automáticamente cada vez que hay un cambio en los precios.
- Ideal para implementar lógicas de trading basadas en señales de mercado.
Ejemplo práctico: Implementamos un EA simple que abre una posición larga si el precio supera un nivel clave.
//+------------------------------------------------------------------+
//| Procesamiento de ticks |
//+------------------------------------------------------------------+
void OnTick() {
double precioActual = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double nivelClave = 1.1200;
// Verificar si el precio supera el nivel clave
if (precioActual > nivelClave) {
Print("Precio actual: ", DoubleToString(precioActual, _Digits), ". Superando nivel clave.");
// Abrir una posición larga
if (OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0)) {
Print("Posición larga abierta.");
} else {
Print("Error al abrir la posición. Código de error: ", GetLastError());
}
}
}
Explicación del Código:
- Obtenemos el precio actual usando
SymbolInfoDouble(). - Comparamos el precio con un nivel clave predefinido.
- Si se cumple la condición, intentamos abrir una posición larga utilizando
OrderSend(). - Mostramos mensajes informativos en caso de éxito o error.
Ciclo de Vida de un Script en MQL5
A continuación, te presentamos un resumen del ciclo de vida de un script en MQL5:
- Inicio (
OnInit()): Se ejecuta al iniciar el programa. Aquí realizamos tareas de configuración. - Procesamiento (
OnTick()): Se ejecuta cada vez que llega un nuevo tick de precio. Aquí implementamos la lógica principal del programa. - Finalización (
OnDeinit()): Se ejecuta al cerrar el programa. Aquí limpiamos recursos o realizamos acciones finales.
Interactividad: Ejercicios Prácticos
Ejercicio 1: Crea un script que muestre un mensaje en la ventana de resultados cada vez que el precio de un símbolo específico cambia más del 0.1% respecto al tick anterior.
Ver solución:Ocultar solución//+------------------------------------------------------------------+
//| Script para detectar cambios de precio mayores al 0.1% |
//| |
//| Propósito: Mostrar un mensaje cuando el precio cambie más del |
//| 0.1% respecto al tick anterior. |
//+------------------------------------------------------------------+
// Variable global para almacenar el último precio procesado
double lastPrice = 0.0;
// Función de inicialización
int OnInit() {
// Verificar si el símbolo actual está disponible
if (!SymbolExists(_Symbol)) {
Print("El símbolo ", _Symbol, " no está disponible.");
return(INIT_FAILED); // Finalizar si el símbolo no existe
}
// Inicializar la variable lastPrice con el precio actual
lastPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
Print("Programa iniciado. Precio inicial: ", DoubleToString(lastPrice, _Digits));
return(INIT_SUCCEEDED);
}
// Función principal que se ejecuta en cada tick
void OnTick() {
// Obtener el precio actual del Ask
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
// Calcular el porcentaje de cambio entre el precio actual y el último precio
double priceChangePercent = MathAbs((currentPrice - lastPrice) / lastPrice * 100);
// Verificar si el cambio es mayor al 0.1%
if (priceChangePercent > 0.1) {
// Mostrar un mensaje con los detalles del cambio
Print("Cambio de precio detectado! Porcentaje: ",
DoubleToString(priceChangePercent, 2),
"% (Último precio: ", DoubleToString(lastPrice, _Digits),
", Precio actual: ", DoubleToString(currentPrice, _Digits), ")");
}
// Actualizar el último precio procesado
lastPrice = currentPrice;
}
// Función de finalización
void OnDeinit(const int reason) {
Print("Programa finalizado. Razón: ", EnumToString((ENUM_DEINIT_REASON)reason));
}
Explicación del Código
- Variable Global (
lastPrice):- Se utiliza para almacenar el precio del último tick procesado. Esta variable permite comparar el precio actual con el anterior.
- Función
OnInit():- Se ejecuta una vez al iniciar el script.
- Verifica si el símbolo actual (
_Symbol) está disponible en el mercado. - Inicializa la variable
lastPricecon el precio actual del Ask (SYMBOL_ASK).
- Función
OnTick():- Se ejecuta cada vez que llega un nuevo tick de precio.
- Obtiene el precio actual del Ask usando
SymbolInfoDouble(). - Calcula el porcentaje de cambio entre el precio actual y el último precio almacenado.
- Si el cambio supera el 0.1%, muestra un mensaje en la ventana de resultados con los detalles del cambio.
- Actualiza la variable
lastPricecon el precio actual para futuras comparaciones.
- Función
OnDeinit():- Se ejecuta cuando el script termina su ejecución.
- Muestra un mensaje indicando la razón de la finalización (por ejemplo, si el usuario cerró manualmente el script o si ocurrió un error).
Cómo Funciona el Script
- El script monitorea continuamente los precios del símbolo seleccionado.
- En cada tick, calcula el porcentaje de cambio entre el precio actual y el último precio registrado.
- Si el cambio supera el 0.1%, muestra un mensaje informativo con el porcentaje exacto de cambio y los valores de los precios involucrados.
- Al finalizar, guarda un registro de la razón de la desinicialización.
Este tipo de script puede ser útil para detectar movimientos significativos en el mercado y tomar decisiones comerciales basadas en esos eventos.
¡Espero que este ejemplo te sea útil para practicar y entender mejor cómo funcionan las funciones principales en MQL5!
Ejercicio 2: Modifica el ejemplo de OnTick() para incluir una posición corta si el precio cae por debajo de otro nivel clave.
//+------------------------------------------------------------------+
//| Script para abrir posiciones largas y cortas basadas en niveles |
//| |
//| Propósito: Abrir una posición larga si el precio supera un nivel |
//| clave y una posición corta si cae por debajo de otro. |
//+------------------------------------------------------------------+
// Niveles clave para tomar decisiones
double nivelClaveCompra = 1.1200; // Nivel para abrir posición larga
double nivelClaveVenta = 1.1150; // Nivel para abrir posición corta
// Función principal que se ejecuta en cada tick
void OnTick() {
// Obtener el precio actual del Ask (para compras) y Bid (para ventas)
double precioActualAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double precioActualBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// Verificar si no hay posiciones abiertas antes de tomar una decisión
if (PositionsTotal() == 0) {
// Si el precio supera el nivel clave de compra, abrir posición larga
if (precioActualAsk > nivelClaveCompra) {
Print("Precio actual (Ask): ", DoubleToString(precioActualAsk, _Digits),
". Superando nivel clave de compra (", DoubleToString(nivelClaveCompra, _Digits), ").");
// Intentar abrir posición larga
if (OrderSend(_Symbol, OP_BUY, 0.1, Ask, 0, 0, 0)) {
Print("Posición larga abierta.");
} else {
Print("Error al abrir posición larga. Código de error: ", GetLastError());
}
}
// Si el precio cae por debajo del nivel clave de venta, abrir posición corta
if (precioActualBid < nivelClaveVenta) {
Print("Precio actual (Bid): ", DoubleToString(precioActualBid, _Digits),
". Cayendo por debajo del nivel clave de venta (", DoubleToString(nivelClaveVenta, _Digits), ").");
// Intentar abrir posición corta
if (OrderSend(_Symbol, OP_SELL, 0.1, Bid, 0, 0, 0)) {
Print("Posición corta abierta.");
} else {
Print("Error al abrir posición corta. Código de error: ", GetLastError());
}
}
}
}
Explicación del Código
- Niveles Clave (
nivelClaveCompraynivelClaveVenta):- Se definen dos niveles clave: uno para abrir una posición larga (
nivelClaveCompra) y otro para abrir una posición corta (nivelClaveVenta).
- Se definen dos niveles clave: uno para abrir una posición larga (
- Función
OnTick():- Se ejecuta cada vez que llega un nuevo tick de precio.
- Obtiene el precio actual del Ask (
SYMBOL_ASK) para verificar si debe abrirse una posición larga y el precio del Bid (SYMBOL_BID) para verificar si debe abrirse una posición corta.
- Verificación de Posiciones Abiertas (
PositionsTotal()):- Antes de tomar cualquier acción, verifica si ya hay posiciones abiertas para evitar múltiples órdenes simultáneas.
- Condición para Posición Larga:
- Si el precio actual del Ask supera el nivel clave de compra (
nivelClaveCompra), intenta abrir una posición larga utilizandoOrderSend()con el tipo de ordenOP_BUY.
- Si el precio actual del Ask supera el nivel clave de compra (
- Condición para Posición Corta:
- Si el precio actual del Bid cae por debajo del nivel clave de venta (
nivelClaveVenta), intenta abrir una posición corta utilizandoOrderSend()con el tipo de ordenOP_SELL.
- Si el precio actual del Bid cae por debajo del nivel clave de venta (
- Manejo de Errores:
- Si ocurre un error al enviar la orden, se muestra el código de error utilizando
GetLastError().
- Si ocurre un error al enviar la orden, se muestra el código de error utilizando
Cómo Funciona el Script
- El script monitorea continuamente los precios del símbolo seleccionado.
- En cada tick, verifica si el precio actual supera el nivel clave de compra o cae por debajo del nivel clave de venta.
- Si se cumplen las condiciones y no hay posiciones abiertas, abre una posición larga o corta según corresponda.
- Muestra mensajes informativos en la ventana de resultados para confirmar las acciones tomadas o reportar errores.
Este tipo de lógica es fundamental en la creación de Expert Advisors básicos y puede ser ampliada con más funcionalidades, como stop loss, take profit y gestión de riesgos.
¡Espero que este ejemplo te sea útil para entender cómo implementar estrategias simples de trading en MQL5!
Ejercicio 3: Añade funcionalidad a la función OnDeinit() para guardar el número total de ticks procesados en un archivo de texto.
//+------------------------------------------------------------------+
//| Script para contar ticks y guardar el total en un archivo |
//| |
//| Propósito: Contar el número total de ticks procesados durante |
//| la ejecución del script y guardar este valor en un |
//| archivo de texto al finalizar. |
//+------------------------------------------------------------------+
// Variable global para contar los ticks procesados
int tickCounter = 0;
// Función principal que se ejecuta en cada tick
void OnTick() {
// Incrementar el contador de ticks
tickCounter++;
}
// Función de finalización
void OnDeinit(const int reason) {
// Mostrar mensaje informativo en la ventana de resultados
Print("Programa finalizado. Razón: ", EnumToString((ENUM_DEINIT_REASON)reason));
Print("Número total de ticks procesados: ", tickCounter);
// Crear o abrir un archivo de texto para guardar el resultado
CFileText file;
if (file.Open("tick_counter.txt", FILE_WRITE)) {
// Escribir el número total de ticks en el archivo
file.WriteLine("Número total de ticks procesados: " + IntegerToString(tickCounter));
file.Close(); // Cerrar el archivo después de escribir
Print("El número de ticks ha sido guardado en 'tick_counter.txt'.");
} else {
// Mostrar mensaje de error si no se pudo abrir el archivo
Print("Error al guardar el número de ticks en el archivo.");
}
}
Explicación del Código
- Variable Global (
tickCounter):- Se utiliza para llevar la cuenta del número total de ticks procesados durante la ejecución del script.
- Función
OnTick():- Se ejecuta cada vez que llega un nuevo tick de precio.
- Incrementa el contador
tickCounteren 1 para registrar que se ha procesado un tick.
- Función
OnDeinit():- Se ejecuta cuando el script termina su ejecución.
- Muestra un mensaje informativo con la razón de la finalización y el número total de ticks procesados.
- Intenta crear o abrir un archivo llamado
tick_counter.txtutilizando la claseCFileText. - Si el archivo se abre correctamente, escribe el número total de ticks procesados en una línea dentro del archivo y luego lo cierra.
- Si ocurre un error al abrir o escribir en el archivo, muestra un mensaje de error en la ventana de resultados.
Cómo Funciona el Script
- Durante la ejecución del script, cada vez que llega un tick, el contador
tickCounterse incrementa en 1. - Cuando el script termina su ejecución (ya sea porque el usuario lo cierra manualmente o debido a otra razón), la función
OnDeinit()guarda el valor del contador en un archivo de texto llamadotick_counter.txt. - El archivo se crea o sobrescribe si ya existe, y el número total de ticks procesados se guarda como una cadena de texto.
- Si hay algún problema al trabajar con el archivo (por ejemplo, permisos insuficientes), se muestra un mensaje de error.
Resultado Esperado
Al ejecutar este script y luego cerrarlo, encontrarás un archivo llamado tick_counter.txt en la carpeta donde se almacenan los archivos del terminal MetaTrader 5 (generalmente en MQL5/Files). Este archivo contendrá una línea similar a la siguiente:
Número total de ticks procesados: 12345
Este tipo de funcionalidad es útil para depuración, análisis posterior o simplemente para mantener registros de la actividad del script.
¡Espero que este ejemplo te sea útil para entender cómo trabajar con archivos en MQL5 y guardar datos importantes al finalizar la ejecución de un programa!
Consejos Adicionales
- Optimiza tus Scripts: Evita realizar operaciones costosas dentro de
OnTick()para mejorar el rendimiento. - Usa Logs: Registra eventos importantes en archivos de texto para facilitar el depurado y análisis posterior.
- Prueba en Backtesting: Antes de usar tus scripts en vivo, prueba su comportamiento en el entorno de backtesting.
Resumen: En este capítulo, hemos aprendido sobre las funciones principales que conforman la estructura de un script en MQL5: OnInit(), OnDeinit() y OnTick(). Estas funciones definen el ciclo de vida de un programa y permiten implementar lógicas avanzadas para automatizar estrategias de trading.
En el próximo capítulo, profundizaremos en cómo trabajar con datos del mercado y gestionar órdenes de forma eficiente.
¡Sigue practicando y perfeccionando tus habilidades en MQL5!
