¡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 5: Mejoras y Herramientas Adicionales
Capítulo 15: Uso de Bibliotecas y Scripts Externos
En este capítulo, aprenderemos a utilizar bibliotecas estándar, crear scripts auxiliares y aprovechar funciones avanzadas como ArraySort() en MQL5. Estas herramientas son esenciales para organizar tu código, reutilizar funciones y optimizar el rendimiento de tus Expert Advisors (EAs) e indicadores.
15.1. Importación de Bibliotecas Estándar (#include)
La directiva #include permite importar bibliotecas estándar o personalizadas en tu código. Esto es útil para reutilizar funciones comunes sin tener que escribirlas desde cero cada vez.
Ejemplo Práctico: Importación de una Biblioteca Personalizada
Supongamos que queremos crear una biblioteca con funciones matemáticas útiles y luego usarla en un EA.
Paso 1: Crear la Biblioteca
Guarda el siguiente código en un archivo llamado MathLibrary.mqh:
//+------------------------------------------------------------------+
//| MathLibrary.mqh - Biblioteca de funciones matemáticas |
//+------------------------------------------------------------------+
// Función para calcular el promedio de un array
double CalculateAverage(double &array[]) {
double sum = 0;
for (int i = 0; i < ArraySize(array); i++) {
sum += array[i];
}
return sum / ArraySize(array);
}
// Función para calcular el máximo de un array
double FindMaximum(double &array[]) {
double max = array[0];
for (int i = 1; i < ArraySize(array); i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
Paso 2: Usar la Biblioteca en un EA
Ahora, usaremos esta biblioteca en un EA para calcular el promedio y el máximo de un array de precios.
//+------------------------------------------------------------------+
//| EA que utiliza la biblioteca MathLibrary |
//+------------------------------------------------------------------+
#include <MathLibrary.mqh> // Importar la biblioteca
void OnStart() {
// Declarar un array de precios
double prices[] = {1.2000, 1.2050, 1.1980, 1.2020, 1.2040};
// Calcular el promedio usando la función de la biblioteca
double average = CalculateAverage(prices);
Print("Promedio de precios: ", DoubleToString(average, _Digits));
// Encontrar el máximo usando la función de la biblioteca
double maximum = FindMaximum(prices);
Print("Precio máximo: ", DoubleToString(maximum, _Digits));
}
Explicación del Código
- Creación de la Biblioteca:
- La biblioteca
MathLibrary.mqhcontiene dos funciones:CalculateAverage: Calcula el promedio de un array.FindMaximum: Encuentra el valor máximo de un array.
- La biblioteca
- Importación de la Biblioteca:
- La directiva
#include <MathLibrary.mqh>importa las funciones de la biblioteca en el EA.
- La directiva
- Uso de las Funciones:
- El EA utiliza las funciones de la biblioteca para calcular el promedio y el máximo de un array de precios.
15.2. Creación de Scripts Auxiliares
Los scripts son programas que se ejecutan una sola vez y son útiles para realizar tareas específicas, como limpiar objetos gráficos o exportar datos.
Ejemplo Práctico: Script para Exportar Datos Históricos a un Archivo CSV
//+------------------------------------------------------------------+
//| Script para exportar datos históricos a un archivo CSV |
//+------------------------------------------------------------------+
void OnStart() {
// Nombre del archivo CSV
string csvFileName = "HistoricalData.csv";
// Obtener el número total de barras disponibles
int bars = Bars(_Symbol, _Period);
// Abrir el archivo CSV para escritura
int fileHandle = FileOpen(csvFileName, FILE_WRITE | FILE_CSV);
if (fileHandle != INVALID_HANDLE) {
// Escribir encabezado si el archivo está vacío
if (FileSize(fileHandle) == 0) {
FileWrite(fileHandle, "Timestamp,Open,High,Low,Close");
}
// Llenar el archivo con datos históricos
for (int i = 0; i < 100; i++) {
datetime time = iTime(_Symbol, _Period, i);
double open = iOpen(_Symbol, _Period, i);
double high = iHigh(_Symbol, _Period, i);
double low = iLow(_Symbol, _Period, i);
double close = iClose(_Symbol, _Period, i);
FileWrite(fileHandle, TimeToString(time, TIME_DATE | TIME_SECONDS),
DoubleToString(open, _Digits),
DoubleToString(high, _Digits),
DoubleToString(low, _Digits),
DoubleToString(close, _Digits));
}
// Cerrar el archivo
FileClose(fileHandle);
Print("Datos históricos exportados a ", csvFileName);
} else {
Print("Error al abrir el archivo CSV.");
}
}
Explicación del Código
- Exportación de Datos:
- El script exporta los últimos 100 datos históricos (timestamp, apertura, máximo, mínimo y cierre) a un archivo CSV.
- Escritura en Archivo:
- Usa
FileWrite()para escribir los datos en formato CSV.
- Usa
- Resultados:
- El archivo generado (
HistoricalData.csv) puede ser abierto en Excel o cualquier herramienta de análisis de datos.
- El archivo generado (
15.3. Uso de Funciones Avanzadas como ArraySort()
La función ArraySort() permite ordenar arrays en orden ascendente o descendente. Esto es útil para encontrar valores máximos, mínimos o medias.
Ejemplo Práctico: Ordenar Precios y Encontrar el Medio
//+------------------------------------------------------------------+
//| Ejemplo de uso de ArraySort() |
//+------------------------------------------------------------------+
void OnStart() {
// Declarar un array de precios desordenados
double prices[] = {1.2000, 1.1980, 1.2050, 1.2020, 1.2040};
// Ordenar el array en orden ascendente
ArraySort(prices, WHOLE_ARRAY, 0, MODE_ASCEND);
// Mostrar los precios ordenados
Print("Precios ordenados:");
for (int i = 0; i < ArraySize(prices); i++) {
Print("Precio ", i, ": ", DoubleToString(prices[i], _Digits));
}
// Encontrar el precio medio
int middleIndex = ArraySize(prices) / 2;
Print("Precio medio: ", DoubleToString(prices[middleIndex], _Digits));
}
Explicación del Código
- Ordenación del Array:
- La función
ArraySort()ordena el arraypricesen orden ascendente.
- La función
- Cálculo del Precio Medio:
- El índice medio se calcula dividiendo el tamaño del array entre 2.
- Resultados:
- Los precios ordenados y el precio medio se imprimen en la ventana de resultados.
Interactividad: Ejercicios Prácticos
Ejercicio 1: Crea una biblioteca personalizada con funciones para calcular el mínimo y el rango de un array.
Ver solución:Ocultar soluciónGuarda el siguiente código en un archivo llamado ArrayUtils.mqh:
//+------------------------------------------------------------------+
//| ArrayUtils.mqh - Biblioteca para operaciones con arrays |
//+------------------------------------------------------------------+
// Función para calcular el mínimo de un array
double FindMinimum(double &array[]) {
if (ArraySize(array) == 0) {
Print("Error: El array está vacío.");
return 0;
}
double min = array[0]; // Inicializar con el primer elemento
for (int i = 1; i < ArraySize(array); i++) {
if (array[i] < min) {
min = array[i]; // Actualizar el valor mínimo
}
}
return min;
}
// Función para calcular el rango de un array
double CalculateRange(double &array[]) {
if (ArraySize(array) == 0) {
Print("Error: El array está vacío.");
return 0;
}
double max = array[0]; // Inicializar con el primer elemento
double min = array[0]; // Inicializar con el primer elemento
for (int i = 1; i < ArraySize(array); i++) {
if (array[i] > max) {
max = array[i]; // Actualizar el valor máximo
}
if (array[i] < min) {
min = array[i]; // Actualizar el valor mínimo
}
}
return max - min; // Rango = Máximo - Mínimo
}
Explicación del Código
- Función
FindMinimum:- Recibe un array como parámetro y devuelve el valor mínimo.
- Si el array está vacío, imprime un mensaje de error y devuelve
0. - Itera sobre el array para encontrar el valor más pequeño.
- Función
CalculateRange:- Recibe un array como parámetro y devuelve el rango (diferencia entre el máximo y el mínimo).
- Si el array está vacío, imprime un mensaje de error y devuelve
0. - Calcula tanto el máximo como el mínimo en un solo bucle y luego calcula el rango como la diferencia entre ambos.
- Uso de Referencias (
&array[]):- Las funciones reciben el array por referencia (
&array[]) para evitar copiar los datos y mejorar la eficiencia.
- Las funciones reciben el array por referencia (
Ejemplo de Uso en un EA
Ahora, usaremos esta biblioteca en un EA para calcular el mínimo y el rango de un array de precios.
//+------------------------------------------------------------------+
//| EA que utiliza la biblioteca ArrayUtils |
//+------------------------------------------------------------------+
#include <ArrayUtils.mqh> // Importar la biblioteca
void OnStart() {
// Declarar un array de precios
double prices[] = {1.2000, 1.1980, 1.2050, 1.2020, 1.2040};
// Calcular el mínimo usando la función de la biblioteca
double minimum = FindMinimum(prices);
Print("Precio mínimo: ", DoubleToString(minimum, _Digits));
// Calcular el rango usando la función de la biblioteca
double range = CalculateRange(prices);
Print("Rango de precios: ", DoubleToString(range, _Digits));
}
Resultado Esperado
Cuando ejecutes este EA, verás lo siguiente en la ventana de resultados:
Precio mínimo: 1.1980
Rango de precios: 0.0070
Interpretación del Cambio
Este ejercicio implementa una biblioteca personalizada con funciones reutilizables para calcular el mínimo y el rango de un array. Esto es útil porque:
- Centraliza las funciones comunes en una biblioteca, lo que facilita su reutilización en múltiples proyectos.
- Mejora la organización del código al separar las funciones auxiliares del código principal.
- Permite realizar cálculos complejos de manera eficiente y clara.
Casos Prácticos
Esta biblioteca puede ser utilizada para:
- Analizar rangos de precios históricos para identificar volatilidad.
- Encontrar valores mínimos o máximos en indicadores técnicos, como el RSI o el MACD.
- Implementar estrategias basadas en umbrales dinámicos, como stop loss o take profit basados en el rango.
¡Espero que este ejemplo te ayude a entender cómo crear y usar bibliotecas personalizadas en MQL5!
Ejercicio 2: Escribe un script que elimine todos los objetos gráficos de un gráfico.
Ver solución:Ocultar solución//+------------------------------------------------------------------+
//| Script para eliminar todos los objetos gráficos de un gráfico |
//+------------------------------------------------------------------+
void OnStart() {
// Obtener la cantidad total de objetos gráficos en el gráfico actual
int totalObjects = ObjectsTotal(0);
// Iterar sobre todos los objetos y eliminarlos uno por uno
for (int i = totalObjects - 1; i >= 0; i--) {
string objectName = ObjectName(0, i); // Obtener el nombre del objeto
if (!ObjectDelete(0, objectName)) { // Intentar eliminar el objeto
Print("Error al eliminar el objeto: ", objectName, ". Código de error: ", GetLastError());
} else {
Print("Objeto eliminado: ", objectName);
}
}
Print("Todos los objetos gráficos han sido eliminados.");
}
Explicación del Código
- Obtención del Número Total de Objetos:
- La función
ObjectsTotal(0)devuelve el número total de objetos gráficos en el gráfico actual (0indica el gráfico principal).
- La función
- Iteración Sobre los Objetos:
- Se utiliza un bucle
forque itera desde el último objeto hasta el primero (i = totalObjects - 1hastai >= 0). - Esto es importante porque al eliminar un objeto, el índice de los objetos restantes puede cambiar. Iterar en orden inverso evita problemas de índice.
- Se utiliza un bucle
- Eliminación de Objetos:
- La función
ObjectName(0, i)obtiene el nombre del objeto en el índicei. - La función
ObjectDelete(0, objectName)intenta eliminar el objeto con el nombre especificado. - Si la eliminación falla, se imprime un mensaje de error con el código de error usando
GetLastError().
- La función
- Resultados:
- Cada vez que un objeto se elimina correctamente, se imprime su nombre en la ventana de resultados.
- Al finalizar, se imprime un mensaje indicando que todos los objetos han sido eliminados.
Resultado Esperado
Cuando ejecutes este script en un gráfico con objetos gráficos (como líneas, flechas o etiquetas), verás lo siguiente en la ventana de resultados:
Objeto eliminado: Line1
Objeto eliminado: Arrow1
Objeto eliminado: Label1
...
Todos los objetos gráficos han sido eliminados.
Si algún objeto no se puede eliminar, verás un mensaje de error como este:
Error al eliminar el objeto: Line2. Código de error: 4106
Interpretación del Cambio
Este ejercicio implementa un script que limpia completamente un gráfico eliminando todos los objetos gráficos. Esto es útil porque:
- Permite mantener el gráfico limpio y organizado, especialmente después de pruebas o análisis complejos.
- Evita confusiones causadas por objetos gráficos antiguos o innecesarios.
- Facilita la reutilización del gráfico para nuevas estrategias o análisis.
Casos Prácticos
Este script puede ser utilizado para:
- Limpiar un gráfico antes de aplicar una nueva estrategia o indicador.
- Eliminar objetos temporales creados durante la depuración de un EA o indicador.
- Automatizar la limpieza de gráficos en múltiples ventanas o símbolos.
¡Espero que este ejemplo te ayude a entender cómo eliminar objetos gráficos en MQL5!
Ejercicio 3: Usa ArraySort() para ordenar un array de ganancias/pérdidas y encontrar el percentil 75.
//+------------------------------------------------------------------------+
//| Script para calcular el percentil 75 de un array de ganancias/pérdidas |
//+------------------------------------------------------------------------+
void OnStart() {
// Declarar un array de ganancias/pérdidas (positivas = ganancias, negativas = pérdidas)
double profits[] = {100.5, -20.3, 50.0, 75.2, -10.0, 200.0, 150.0, -5.0, 80.0, 90.0};
// Ordenar el array en orden ascendente
ArraySort(profits, WHOLE_ARRAY, 0, MODE_ASCEND);
// Mostrar los valores ordenados
Print("Valores ordenados:");
for (int i = 0; i < ArraySize(profits); i++) {
Print("Valor ", i, ": ", DoubleToString(profits[i], 2));
}
// Calcular el índice correspondiente al percentil 75
int arraySize = ArraySize(profits);
double percentileIndex = (arraySize - 1) * 0.75; // Índice del percentil 75
// Encontrar el valor del percentil 75
int lowerIndex = (int)MathFloor(percentileIndex); // Índice inferior
int upperIndex = (int)MathCeil(percentileIndex); // Índice superior
double percentile75;
if (lowerIndex == upperIndex) {
// Si el índice es un número entero, tomar el valor directamente
percentile75 = profits[lowerIndex];
} else {
// Interpolar entre los dos valores más cercanos
double weight = percentileIndex - lowerIndex;
percentile75 = profits[lowerIndex] + weight * (profits[upperIndex] - profits[lowerIndex]);
}
// Mostrar el resultado
Print("Percentil 75: ", DoubleToString(percentile75, 2));
}
Explicación del Código
- Declaración del Array:
- El array
profits[]contiene valores de ganancias (positivos) y pérdidas (negativos). - Estos valores representan resultados hipotéticos de operaciones.
- El array
- Ordenación del Array:
- La función
ArraySort()ordena el array en orden ascendente (MODE_ASCEND). - Esto es necesario para calcular percentiles, ya que requiere que los datos estén ordenados.
- La función
- Cálculo del Índice del Percentil 75:
- El índice del percentil 75 se calcula como
(arraySize - 1) * 0.75. - Este cálculo determina la posición en el array donde se encuentra el percentil 75.
- El índice del percentil 75 se calcula como
- Interpolación para Valores No Enteros:
- Si el índice no es un número entero, se interpola entre los dos valores más cercanos.
- Por ejemplo, si el índice es
6.75, se interpola entre el valor en el índice6y el índice7.
- Resultado Final:
- El valor del percentil 75 se imprime en la ventana de resultados.
Resultado Esperado
Cuando ejecutes este script, verás lo siguiente en la ventana de resultados:
Valores ordenados:
Valor 0: -20.30
Valor 1: -10.00
Valor 2: -5.00
Valor 3: 50.00
Valor 4: 75.20
Valor 5: 80.00
Valor 6: 90.00
Valor 7: 100.50
Valor 8: 150.00
Valor 9: 200.00
Percentil 75: 97.88
Interpretación del Cambio
Este ejercicio implementa un script que calcula el percentil 75 de un array de ganancias/pérdidas utilizando ArraySort() y una interpolación para índices no enteros. Esto es útil porque:
- El percentil 75 es una medida estadística que indica el valor por debajo del cual se encuentra el 75% de los datos.
- Permite evaluar el rendimiento de un sistema de trading al identificar umbrales clave, como el nivel de ganancia que supera el 75% de las operaciones.
Casos Prácticos
Este script puede ser utilizado para:
- Analizar el rendimiento de un EA o estrategia de trading.
- Identificar umbrales de ganancia o pérdida para ajustar stop loss o take profit.
- Comparar diferentes sistemas de trading basándose en métricas como el percentil 75.
¡Espero que este ejemplo te ayude a entender cómo calcular percentiles en MQL5!
Conclusión: El uso de bibliotecas, scripts y funciones avanzadas como ArraySort() es fundamental para organizar y optimizar tu código en MQL5. Al dominar estas herramientas, puedes:
* Reutilizar funciones comunes en múltiples proyectos.
* Automatizar tareas repetitivas con scripts.
* Realizar cálculos complejos de manera eficiente.
En el próximo capítulo, exploraremos cómo integrar APIs externas para ampliar las capacidades de tus EAs.
