Capítulo 13: Notificaciones y Logs
En este capítulo, aprenderemos a implementar notificaciones, registros de eventos y alertas visuales en MQL5. Estas herramientas son esenciales para monitorear el rendimiento de tus Expert Advisors (EAs), depurar errores y recibir actualizaciones en tiempo real sobre el estado de tus operaciones.
13.1. Envío de Notificaciones por Correo Electrónico o SMS
MQL5 permite enviar notificaciones automáticas a través de correo electrónico o SMS utilizando las funciones SendMail() y SendNotification(). Esto es útil para recibir alertas importantes, como la apertura o cierre de posiciones.
Ejemplo Práctico: Envío de Notificaciones
//+------------------------------------------------------------------+
//| Ejemplo de envío de notificaciones |
//+------------------------------------------------------------------+
// Parámetros de entrada
input string EmailAddress = "tucorreo@example.com"; // Dirección de correo electrónico
input string NotificationMessage = "¡Alerta de Trading!"; // Mensaje de notificación
// Función principal que se ejecuta en cada tick
void OnTick() {
// Verificar si hay posiciones abiertas
if (PositionsTotal() > 0) {
// Enviar una notificación por correo electrónico
SendMail("Estado de Posiciones", "Tienes " + IntegerToString(PositionsTotal()) + " posiciones abiertas.");
// Enviar una notificación push al dispositivo móvil
SendNotification(NotificationMessage);
}
}
Explicación del Código
- Envío de Correo Electrónico:
- La función
SendMail()envía un correo electrónico con un asunto y un cuerpo personalizados. - Antes de usar esta función, asegúrate de configurar tu servidor SMTP en MetaTrader 5 (
Herramientas > Opciones > Correo).
- La función
- Envío de Notificaciones Push:
- La función
SendNotification()envía una notificación push a tu dispositivo móvil vinculado a MetaTrader 5. - Para usar esta función, asegúrate de habilitar las notificaciones en la aplicación móvil de MetaTrader.
- La función
- Personalización de Mensajes:
- Puedes incluir información dinámica, como el número de posiciones abiertas o el saldo actual, en los mensajes de notificación.
13.2. Registro de Eventos con Print() y FileWrite()
El registro de eventos es crucial para depurar y analizar el comportamiento de tus EAs. MQL5 ofrece varias formas de registrar eventos, como Print() para la consola y FileWrite() para archivos de texto.
Ejemplo Práctico: Registro de Eventos
//+------------------------------------------------------------------+
//| Ejemplo de registro de eventos |
//+------------------------------------------------------------------+
// Nombre del archivo de registro
string logFileName = "TradingLog.txt";
// Función principal que se ejecuta en cada tick
void OnTick() {
// Registrar eventos en la consola
Print("Tick procesado. Precio actual: ", DoubleToString(Bid, _Digits));
// Registrar eventos en un archivo de texto
FileWriteLog(logFileName, "Tick procesado. Precio actual: " + DoubleToString(Bid, _Digits));
}
// Función para escribir en un archivo de texto
void FileWriteLog(string fileName, string message) {
int fileHandle = FileOpen(fileName, FILE_WRITE | FILE_TXT); // Abrir el archivo en modo escritura
if (fileHandle != INVALID_HANDLE) {
FileWrite(fileHandle, TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS), ": ", message); // Escribir mensaje
FileClose(fileHandle); // Cerrar el archivo
} else {
Print("Error al abrir el archivo de registro.");
}
}
Explicación del Código
- Registro en la Consola:
- La función
Print()muestra mensajes en la ventana de resultados de MetaTrader 5. - Es útil para depurar rápidamente problemas durante el desarrollo.
- La función
- Registro en Archivos de Texto:
- La función
FileWriteLog()escribe mensajes en un archivo de texto, lo que permite almacenar un historial detallado de eventos. - El archivo se guarda en la carpeta
Filesde MetaTrader 5.
- La función
- Formato del Registro:
- Los mensajes incluyen una marca de tiempo (
TimeCurrent()) para facilitar el seguimiento de eventos.
- Los mensajes incluyen una marca de tiempo (
13.3. Uso de Alertas Visuales
Las alertas visuales son una forma efectiva de destacar eventos importantes directamente en el gráfico. Puedes usar la función Alert() para mostrar mensajes emergentes o dibujar objetos gráficos con ObjectCreate().
Ejemplo Práctico: Alertas Visuales
//+------------------------------------------------------------------+
//| Ejemplo de alertas visuales |
//+------------------------------------------------------------------+
// Función principal que se ejecuta en cada tick
void OnTick() {
// Mostrar una alerta visual si el precio cruza un nivel clave
double keyLevel = 1.2000;
if (Bid > keyLevel && PositionsTotal() == 0) {
Alert("¡El precio ha cruzado el nivel clave de ", DoubleToString(keyLevel, _Digits), "!");
DrawKeyLevel(keyLevel);
}
}
// Función para dibujar un nivel clave en el gráfico
void DrawKeyLevel(double level) {
string objectName = "KeyLevel";
if (!ObjectCreate(0, objectName, OBJ_HLINE, 0, 0, level)) {
Print("Error al crear el objeto gráfico. Código de error: ", GetLastError());
} else {
ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrRed); // Color rojo
ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_DASH); // Línea discontinua
ObjectSetString(0, objectName, OBJPROP_TOOLTIP, "Nivel Clave"); // Tooltip
}
}
Explicación del Código
- Alertas Emergentes:
- La función
Alert()muestra un mensaje emergente cuando se cumple una condición específica. - Es útil para captar la atención del trader inmediatamente.
- La función
- Objetos Gráficos:
- La función
ObjectCreate()dibuja un objeto gráfico en el gráfico, como una línea horizontal (OBJ_HLINE). - Puedes personalizar el color, estilo y tooltip del objeto para mejorar su visibilidad.
- La función
- Condiciones de Activación:
- Las alertas visuales se activan cuando el precio cruza un nivel clave, lo que puede ser útil para identificar puntos de entrada o salida.
Interactividad: Ejercicios Prácticos
Ejercicio 1: Modifica el código de notificaciones para incluir el saldo de la cuenta en el mensaje de correo electrónico.
Ver solución:Ocultar solución//+------------------------------------------------------------------+
//| Ejemplo de envío de notificaciones con saldo de cuenta |
//+------------------------------------------------------------------+
// Parámetros de entrada
input string EmailAddress = "tucorreo@example.com"; // Dirección de correo electrónico
input string NotificationMessage = "¡Alerta de Trading!"; // Mensaje de notificación
// Función principal que se ejecuta en cada tick
void OnTick() {
// Obtener el saldo actual de la cuenta
double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
// Verificar si hay posiciones abiertas
if (PositionsTotal() > 0) {
// Crear un mensaje personalizado con el saldo de la cuenta
string emailSubject = "Estado de Posiciones";
string emailBody = "Tienes " + IntegerToString(PositionsTotal()) + " posiciones abiertas.\n";
emailBody += "Saldo actual de la cuenta: " + DoubleToString(accountBalance, 2) + " " + AccountCurrency();
// Enviar una notificación por correo electrónico
SendMail(emailSubject, emailBody);
// Enviar una notificación push al dispositivo móvil
SendNotification(NotificationMessage);
}
}
Explicación del Código
- Obtención del Saldo de la Cuenta:
- Usamos la función
AccountInfoDouble(ACCOUNT_BALANCE)para obtener el saldo actual de la cuenta. - También usamos
AccountCurrency()para incluir la moneda de la cuenta en el mensaje.
- Usamos la función
- Personalización del Mensaje de Correo Electrónico:
- El mensaje de correo electrónico (
emailBody) incluye:- El número de posiciones abiertas (
PositionsTotal()). - El saldo actual de la cuenta (
accountBalance), formateado con dos decimales usandoDoubleToString. - La moneda de la cuenta (
AccountCurrency()).
- El número de posiciones abiertas (
- El mensaje de correo electrónico (
- Envío del Correo Electrónico:
- La función
SendMail()envía el correo electrónico con un asunto (emailSubject) y un cuerpo personalizado (emailBody).
- La función
- Notificación Push:
- La función
SendNotification()envía una notificación push al dispositivo móvil vinculado a MetaTrader 5.
- La función
Resultado Esperado
Cuando ejecutes este EA, recibirás un correo electrónico similar al siguiente:
Asunto: Estado de Posiciones
Cuerpo:
Tienes 2 posiciones abiertas.
Saldo actual de la cuenta: 10,000.50 USD
Además, recibirás una notificación push en tu dispositivo móvil con el mensaje configurado en NotificationMessage.
Interpretación del Cambio
Este ejercicio mejora el sistema de notificaciones al incluir información relevante sobre el estado de la cuenta, como el saldo actual. Esto es útil porque:
- Proporciona una visión clara del estado financiero de la cuenta en tiempo real.
- Facilita la toma de decisiones basadas en el saldo disponible.
- Personaliza los mensajes de notificación para que sean más informativos y útiles.
Casos Prácticos
Esta implementación puede ser utilizada para:
- Monitorear el saldo de la cuenta después de abrir o cerrar posiciones.
- Recibir alertas cuando el saldo caiga por debajo de un umbral crítico.
- Integrar información financiera en informes automáticos enviados por correo electrónico.
¡Espero que este ejemplo te ayude a entender cómo personalizar mensajes de notificación en MQL5!
Ejercicio 2: Implementa un sistema de registro que guarde el historial de operaciones (abiertas y cerradas) en un archivo CSV.
Ver solución:Ocultar solución//+------------------------------------------------------------------+
//| Sistema de registro de operaciones en un archivo CSV |
//+------------------------------------------------------------------+
// Nombre del archivo CSV
string csvFileName = "TradingHistory.csv";
// Función principal que se ejecuta en cada tick
void OnTick() {
// Registrar operaciones abiertas
LogOpenPositions();
// Registrar operaciones cerradas
LogClosedPositions();
}
// Función para registrar operaciones abiertas
void LogOpenPositions() {
int totalOpenPositions = PositionsTotal();
if (totalOpenPositions > 0) {
for (int i = 0; i < totalOpenPositions; i++) {
ulong ticket = PositionGetTicket(i);
string symbol = PositionGetString(POSITION_SYMBOL);
double volume = PositionGetDouble(POSITION_VOLUME);
double price = PositionGetDouble(POSITION_PRICE_OPEN);
int type = (int)PositionGetInteger(POSITION_TYPE);
string operationType = (type == POSITION_TYPE_BUY) ? "Buy" : "Sell";
string logMessage = TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS) + "," +
IntegerToString(ticket) + "," +
symbol + "," +
operationType + "," +
DoubleToString(volume, 2) + "," +
DoubleToString(price, _Digits) + ",Open\n";
WriteToCSV(csvFileName, logMessage);
}
}
}
// Función para registrar operaciones cerradas
void LogClosedPositions() {
int totalClosedDeals = HistoryDealsTotal();
if (totalClosedDeals > 0) {
for (int i = 0; i < totalClosedDeals; i++) {
ulong ticket = HistoryDealGetTicket(i);
if (ticket > 0) {
string symbol = HistoryDealGetString(ticket, DEAL_SYMBOL);
double volume = HistoryDealGetDouble(ticket, DEAL_VOLUME);
double price = HistoryDealGetDouble(ticket, DEAL_PRICE);
int type = (int)HistoryDealGetInteger(ticket, DEAL_TYPE);
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
string operationType = (type == DEAL_TYPE_BUY) ? "Buy" : "Sell";
string logMessage = TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS) + "," +
IntegerToString(ticket) + "," +
symbol + "," +
operationType + "," +
DoubleToString(volume, 2) + "," +
DoubleToString(price, _Digits) + "," +
DoubleToString(profit, 2) + ",Closed\n";
WriteToCSV(csvFileName, logMessage);
}
}
}
}
// Función para escribir en un archivo CSV
void WriteToCSV(string fileName, string message) {
int fileHandle = FileOpen(fileName, FILE_WRITE | FILE_CSV); // Abrir el archivo en modo escritura CSV
if (fileHandle != INVALID_HANDLE) {
if (FileSize(fileHandle) == 0) {
// Escribir encabezado si el archivo está vacío
FileWrite(fileHandle, "Timestamp,Ticket,Symbol,Type,Volume,Price,Profit,Status");
}
FileWrite(fileHandle, message); // Escribir el mensaje
FileClose(fileHandle); // Cerrar el archivo
} else {
Print("Error al abrir el archivo CSV.");
}
}
Explicación del Código
- Registro de Operaciones Abiertas:
- La función
LogOpenPositionsitera sobre todas las posiciones abiertas usandoPositionsTotal()yPositionGetTicket. - Para cada posición, obtiene detalles como el símbolo, volumen, precio de apertura y tipo de operación (compra o venta).
- Los datos se formatean en una línea CSV con campos separados por comas.
- La función
- Registro de Operaciones Cerradas:
- La función
LogClosedPositionsitera sobre todas las operaciones cerradas usandoHistoryDealsTotal()yHistoryDealGetTicket. - Para cada operación cerrada, obtiene detalles como el símbolo, volumen, precio, tipo de operación y ganancia/pérdida.
- Los datos también se formatean en una línea CSV.
- La función
- Escritura en Archivo CSV:
- La función
WriteToCSVmaneja la escritura en el archivo CSV. - Si el archivo está vacío (
FileSize(fileHandle) == 0), escribe un encabezado con los nombres de las columnas. - Luego, escribe cada línea de registro en el archivo.
- La función
- Formato del Archivo CSV:
- El archivo incluye las siguientes columnas:
- Timestamp: Marca de tiempo de la operación.
- Ticket: Número de ticket de la operación.
- Symbol: Símbolo del instrumento financiero.
- Type: Tipo de operación (compra o venta).
- Volume: Volumen de la operación.
- Price: Precio de apertura o cierre.
- Profit: Ganancia o pérdida (solo para operaciones cerradas).
- Status: Estado de la operación (abierta o cerrada).
- El archivo incluye las siguientes columnas:
Resultado Esperado
Cuando ejecutes este EA, se generará un archivo CSV llamado TradingHistory.csv en la carpeta Files de MetaTrader 5. El archivo tendrá un formato similar al siguiente:
Timestamp,Ticket,Symbol,Type,Volume,Price,Profit,Status
2023.10.01 10:00:00,123456,EURUSD,Buy,0.10,1.2000,,Open
2023.10.01 10:05:00,123457,EURUSD,Sell,0.10,1.1980,20.00,Closed
Interpretación del Cambio
Este ejercicio implementa un sistema de registro que guarda el historial de operaciones en un archivo CSV. Esto es útil porque:
- Proporciona un registro estructurado y fácil de analizar de todas las operaciones realizadas.
- Facilita la auditoría y el análisis posterior del rendimiento del EA.
- Permite exportar los datos a herramientas externas (como Excel o Python) para realizar análisis avanzados.
Casos Prácticos
Este sistema puede ser utilizado para:
- Monitorear el desempeño de tus EAs en tiempo real.
- Identificar patrones en las operaciones abiertas y cerradas.
- Generar informes automáticos para evaluar la efectividad de tus estrategias.
¡Espero que este ejemplo te ayude a entender cómo implementar un sistema de registro en MQL5!
Ejercicio 3: Crea un EA que muestre una alerta visual cuando el spread supere un umbral específico.
Ver solución:Ocultar solución//+------------------------------------------------------------------+
//| EA que muestra una alerta visual cuando el spread es alto |
//+------------------------------------------------------------------+
// Parámetros de entrada
input int MaxSpreadPips = 2; // Umbral máximo permitido para el spread (en pips)
// Variables globales
bool alertShown = false; // Controla si la alerta ya se ha mostrado
// Función principal que se ejecuta en cada tick
void OnTick() {
// Calcular el spread actual en pips
double currentSpread = (SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID)) / Point();
// Verificar si el spread supera el umbral
if (currentSpread > MaxSpreadPips) {
if (!alertShown) {
// Mostrar una alerta visual
Alert("¡El spread actual (" + DoubleToString(currentSpread, 1) + " pips) supera el umbral de " +
IntegerToString(MaxSpreadPips) + " pips!");
// Dibujar una línea horizontal en el gráfico para destacar el spread
DrawSpreadAlertLine(currentSpread);
// Marcar que la alerta ya se ha mostrado
alertShown = true;
}
} else {
// Restablecer la bandera si el spread vuelve a estar dentro del umbral
alertShown = false;
// Eliminar la línea de alerta del gráfico
ObjectDelete(0, "SpreadAlertLine");
}
}
// Función para dibujar una línea de alerta en el gráfico
void DrawSpreadAlertLine(double spreadValue) {
string objectName = "SpreadAlertLine";
if (!ObjectCreate(0, objectName, OBJ_HLINE, 0, 0, Bid)) {
Print("Error al crear la línea de alerta. Código de error: ", GetLastError());
} else {
ObjectSetInteger(0, objectName, OBJPROP_COLOR, clrRed); // Color rojo
ObjectSetInteger(0, objectName, OBJPROP_STYLE, STYLE_DASHDOT); // Estilo de línea discontinua
ObjectSetString(0, objectName, OBJPROP_TOOLTIP, "Spread elevado: " + DoubleToString(spreadValue, 1) + " pips"); // Tooltip
}
}
Explicación del Código
- Parámetros de Entrada:
MaxSpreadPips: Define el umbral máximo permitido para el spread en pips. Si el spread supera este valor, se mostrará una alerta.
- Cálculo del Spread Actual:
- El spread se calcula como la diferencia entre el precio de compra (
SYMBOL_ASK) y el precio de venta (SYMBOL_BID), convertida a pips dividiendo porPoint().
- El spread se calcula como la diferencia entre el precio de compra (
- Verificación del Umbral:
- Si el spread supera el umbral (
MaxSpreadPips), se muestra una alerta visual usando la funciónAlert(). - Para evitar múltiples alertas consecutivas, se usa una variable booleana (
alertShown) para controlar si la alerta ya se ha mostrado.
- Si el spread supera el umbral (
- Dibujo de la Línea de Alerta:
- La función
DrawSpreadAlertLinedibuja una línea horizontal (OBJ_HLINE) en el gráfico para destacar visualmente el nivel del spread. - La línea tiene un color rojo, un estilo discontinuo y un tooltip informativo.
- La función
- Restablecimiento de la Alerta:
- Si el spread vuelve a estar dentro del umbral, se elimina la línea de alerta del gráfico usando
ObjectDelete()y se restablece la banderaalertShown.
- Si el spread vuelve a estar dentro del umbral, se elimina la línea de alerta del gráfico usando
Resultado Esperado
Cuando ejecutes este EA, verás lo siguiente:
- Si el spread supera el umbral (por ejemplo, 2 pips):
- Aparecerá una ventana emergente con el mensaje:
¡El spread actual (2.5 pips) supera el umbral de 2 pips!
- Se dibujará una línea roja discontinua en el gráfico con un tooltip que indica el valor del spread.
- Si el spread vuelve a estar dentro del umbral:
- La línea de alerta desaparecerá del gráfico.
Interpretación del Cambio
Este ejercicio implementa un sistema de alertas visuales para monitorear el spread en tiempo real. Esto es útil porque:
- Ayuda a identificar condiciones de mercado adversas (como spreads altos durante noticias o volatilidad extrema).
- Proporciona una advertencia clara y visible directamente en el gráfico.
- Permite tomar decisiones informadas sobre cuándo operar o evitar abrir posiciones.
Casos Prácticos
Este EA puede ser utilizado para:
- Evitar operaciones en momentos de alta volatilidad o liquidez reducida.
- Monitorear el spread en símbolos exóticos o menos líquidos.
- Integrar alertas visuales en estrategias automatizadas para mejorar la toma de decisiones.
¡Espero que este ejemplo te ayude a entender cómo implementar alertas visuales en MQL5!
Conclusión: Las notificaciones, registros y alertas visuales son herramientas poderosas para mejorar la experiencia de trading automatizado. Al dominar estas técnicas, puedes:
* Monitorear tus EAs en tiempo real.
* Depurar errores y optimizar el rendimiento.
* Recibir actualizaciones importantes directamente en tu correo electrónico, dispositivo móvil o gráfico.
En el próximo capítulo, exploraremos cómo trabajar con arrays y matrices multidimensionales en MQL5.
¡Sigue practicando y perfeccionando tus habilidades en MQL5!
