English Русский 中文 Deutsch 日本語 Português
preview
Creación de un asesor experto integrado de MQL5 y Telegram (Parte 1): Envío de mensajes desde MQL5 a Telegram

Creación de un asesor experto integrado de MQL5 y Telegram (Parte 1): Envío de mensajes desde MQL5 a Telegram

MetaTrader 5Sistemas comerciales | 12 febrero 2025, 09:13
660 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Introducción

Este artículo seguirá el curso de la integración de Telegram con MetaTrader 5. Pretendemos lograr esto mediante la creación de un Asesor Experto (EA) personalizado en el lenguaje de programación MetaQuotes Language 5 (MQL5). Nuestra tarea principal es programar un asistente comercial que funcione en tiempo real y nos mantenga informados a través de un chat en Telegram. El bot de Telegram que construiremos actuará como un servidor de actualización, enviándonos jugosos fragmentos de información que nos ayudarán a tomar decisiones comerciales importantes.

Para alcanzar este objetivo, pasaremos por el proceso de establecer un bot de Telegram y ajustar nuestro EA para comunicarse con Telegram a través de una Interfaz de Programación de Aplicaciones (Application Programming Interface, API). Primero configuraremos BotFather, un bot de Telegram que te ayuda a crear nuevos bots y a gestionar los que ya tienes. Usando "BotFather", crearemos un nuevo bot y tendremos la oportunidad de ponerle un nombre. También obtendremos una pieza vital de información -el token- que utilizaremos para identificar y obtener acceso a nuestro bot desde la Interfaz de Programación de Aplicaciones (API). Después de eso, obtendremos la ID del chat y usaremos estos dos elementos para llegar a la API y hacerla funcionar.

Por eso, en este artículo, ofreceremos un tutorial de codificación completo. Le mostraremos cómo escribir e implementar un Asesor Experto que establecerá un vínculo bidireccional entre MetaTrader 5 y Telegram. Te explicaremos no sólo el “cómo” sino también el “por qué”, para que entiendas los aspectos técnicos y prácticos de la integración. También discutiremos posibles errores que pueden ocurrir durante la instalación y el funcionamiento, principalmente para ayudarle a evitarlos, pero también para asegurarnos de que sepa cómo manejarlos si ocurren a pesar de nuestros mejores esfuerzos por preverlos y prevenirlos.

Para absorber fácilmente el contenido en pequeñas partes, dividiremos el proceso en los siguientes subtemas:

  1. Introducción a la integración de MQL5 y Telegram
  2. Configurando el bot de Telegram
  3. Configuración de MetaTrader 5 para la comunicación por Telegram
  4. Implementación en MQL5
  5. Probando la integración
  6. Conclusión

Al final del artículo, debería tener una comprensión sólida de cómo lograr una comunicación integrada y automatizada entre MetaTrader 5 y Telegram, con un EA funcional como producto final.


Introducción a la integración de MQL5 y Telegram

  • Descripción general de la serie y objetivos:

Esta serie de artículos tiene como objetivo cerrar el círculo entre sus operaciones en la plataforma MetaTrader 5 y sus comunicaciones instantáneas en la aplicación Telegram. Al final de la serie, tendrás un Asesor Experto (EA) funcional en MQL5 que puede enviar y recibir mensajes e incluso transmitir imágenes a través de tu plataforma de negociación y a tu cuenta de Telegram. Cada parte de la serie se basa en la anterior, perfeccionando la funcionalidad del EA y el sistema comercial general que puedes utilizar.

  • Beneficios de integrar Telegram con MQL5:

La integración de Telegram con MQL5 tiene varias ventajas. Para empezar, ofrece la posibilidad de enviar notificaciones instantáneas. Si ha configurado un asesor experto para operar con MQL5, puede programarlo para que le envíe alertas a través de Telegram. Esto funciona muy bien porque usted puede configurar su algoritmo comercial de tal manera que las únicas alertas que reciba sean las de una nueva oportunidad comercial sorprendente o una actualización importante con respecto a una posición abierta. La otra ruta principal a través de la cual puede comunicarse con su algoritmo comercial a través de Telegram es mediante el uso de un bot de Telegram. Los bots ofrecen algunas ventajas distintivas cuando se trata de programar un servicio para enviarle alertas y/o permitir la comunicación limitada pero segura de datos comerciales confidenciales. Además, puedes compartir todo tipo de medios relevantes para el comercio (como gráficos o capturas de pantalla) trabajando en conjunto con el bot para permitir que tus algoritmos comerciales te sirvan mejor. Técnicamente, el bot retransmite la comunicación entre el usuario y el servidor. A continuación se muestra una visualización detallada de los procesos cronológicos:

Procesos cronológicos

  • Relevancia en el trading moderno:

El mundo comercial actual exige una rápida adaptabilidad de sus participantes; es una cuestión de ganancias y pérdidas. Necesariamente, los traders hemos buscado formas de automatizar nuestras estrategias, para estar en contacto con los mercados sin estar atados a nuestros escritorios. Uno de los enfoques más recientes para lograr esto implica el uso de MQL5, un poderoso lenguaje de programación, con Telegram, una aplicación de mensajería instantánea que puede configurarse para que funcione casi como un panel de operaciones personalizado. Esta configuración de notificaciones en Telegram permite a los usuarios recibir alertas en tiempo real sobre actividades relevantes en las cuentas que administran, asegurando un monitoreo eficiente y centralizado. Tengas o no un equipo, las capacidades de actualización peer-to-peer de Telegram lo convierten en una herramienta valiosa para cualquier operador.

  • Sentando las bases de la serie:

Comprender los conceptos esenciales y las herramientas básicas de la integración es primordial. Comenzaremos con lo básico: Crear un bot de Telegram y configurar MQL5 para enviar mensajes a través de él. Este paso es fundamental. Nos permite establecer una base sobre la que podemos construir funcionalidades más avanzadas, más sofisticadas y más útiles en futuras entregas. Al final de la Parte 1, poseeremos un sistema básico pero funcional capaz de enviar mensajes de texto desde nuestro EA a Telegram. Esta base no solo te brindará habilidades prácticas, sino que también te preparará para las tareas más complejas que te esperan, como enviar imágenes y manejar la comunicación bidireccional entre MQL5 y Telegram. Al final tendremos la integración de la siguiente manera:

Integración final de MQL5 con Telegram

Esto servirá como base básica para las demás partes.


Configurando el bot de Telegram

El primer paso para conectar Telegram a MetaTrader 5 es crear un bot de Telegram. Este bot servirá como intermediario para los mensajes enviados y recibidos desde Telegram y MetaTrader 5. Usando BotFather, crearemos un nuevo bot, lo configuraremos con los permisos necesarios y luego obtendremos el token API que permite la comunicación con nuestro bot.

Para crear un bot, primero abre la aplicación Telegram y busca "BotFather". Este es un bot especial que se usa para crear y administrar otros bots. Como podría haber muchos de ellos con nombres casi similares, asegúrese de ingresar las palabras como se ilustra.

La forma correcta de BotFather

Inicia un chat con BotFather y usa el comando "/newbot" para crear un nuevo bot. Luego, BotFather le solicita un nombre y un nombre de usuario para su bot. Después de eso, obtendrás un token API único. Esto es muy importante porque permite que su aplicación se autentique con los servidores de Telegram e interactúe con ellos de una manera que los servidores saben que es legítima. Para ilustrar el proceso realizado, consideramos una visualización de imagen en formato de intercambio de gráficos (GIF) como la que se muestra a continuación para garantizar que obtenga los pasos correctos.

Pasos para la creación (GIF)

Configuración del bot: Tras adquirir el token de la API, debemos configurar el bot para que se ajuste a nuestras necesidades. Podemos programarlo para que reconozca y responda a comandos utilizando el comando "/setcommands" de BotFather. Para abrir el bot, puedes buscarlo utilizando su nombre o simplemente hacer clic en el primer enlace proporcionado por "BotFather" como se muestra a continuación:

Abrir el bot (GIF)

También podemos dotar al bot de una interfaz de usuario más amigable. Añadir un perfil, una descripción y una foto lo hará un poco más atractivo, pero es un paso opcional. El siguiente paso en la configuración del bot es asegurarse de que puede gestionar la mensajería real de acuerdo con nuestros requisitos.

Obtener la ID del chat: Para enviar mensajes directos desde nuestro bot a un chat o grupo específico, necesitamos obtener la ID del chat. Podemos conseguirlo enviando un mensaje a nuestro bot y utilizando el método "getUpdates" de la API de Telegram para obtener la ID del chat. Necesitaremos esta ID si queremos que nuestro bot envíe mensajes a otro lugar que no sea su propietario. Si queremos que el bot envíe mensajes a un grupo o canal, podemos añadir primero el bot al grupo y luego utilizar los mismos métodos para obtener la ID del chat. Para obtener el ID del chat, utilizamos el siguiente fragmento de código. Simplemente copia y sustituye el token del bot por el token de tu bot y ejecútalo en tu navegador.

//CHAT ID = https://api.telegram.org/bot{BOT TOKEN}/getUpdates
//https://api.telegram.org/bot7456439661:AAELUurPxI1jloZZl3Rt-zWHRDEvBk2venc/getUpdates

Estos son los resultados que obtenemos:

Obtención del Chat ID 1

Puede ver que nuestro resultado no contiene ninguna actualización del mensaje, aunque devolvamos true, lo que indica que todo lo proporcionado es correcto. Si introduces algo en el enlace que no es correcto, recibirás una petición web errónea y obtendrás un falso retorno como el de abajo:

{"ok":false,"error_code":404,"description":"Not Found"}

En nuestro caso, devolvemos true, y sin embargo nuestra estructura está vacía. Esto se debe a que necesitamos enviar un mensaje al bot para que se produzca una actualización. En nuestro caso, enviamos un comando de arranque "/start".

Mensaje de inicio del bot

Una vez que enviamos el mensaje y volvemos a actualizar el enlace, ya tenemos la actualización. A este respecto, conviene tener en cuenta que los mensajes se almacenan en el servidor de Telegram sólo durante 24 horas, y después se descartan. Por lo tanto, si usted está recibiendo la ID de chat utilizando este método, asegúrese de que los mensajes fueron enviados dentro de las 24 horas antes del proceso. Esto es lo que tenemos:

Nueva actualización del bot

Recibimos las actualizaciones, pero la estructura de presentación es bastante compacta y poco atractiva. Para conseguir un formato más legible, sólo tienes que marcar la casilla "Pretty-Print" y deberías tener la siguiente estructura.

{
  "ok": true,
  "result": [
    {
      "update_id": 794283176,
      "message": {
        "message_id": 1,
        "from": {
          "id": [YOUR ID],
          "is_bot": false,
          "first_name": "Forex Algo-Trader",
          "username": "Forex_Algo_Trader",
          "language_code": "en"
        },
        "chat": {
          "id": [YOUR ID],
          "first_name": "Forex Algo-Trader",
          "username": "Forex_Algo_Trader",
          "type": "private"
        },
        "date": 1722368989,
        "text": "/start",
        "entities": [
          {
            "offset": 0,
            "length": 6,
            "type": "bot_command"
          }
        ]
      }
    }
  ]
}

Nuestro identificador de chat es el que aparece bajo la columna "chat id". Hasta aquí, armados con el token del bot y la ID del chat, podemos crear un programa que envíe mensajes desde MQL5 al bot de Telegram que hemos creado.


Configuración de MetaTrader 5 para la comunicación por Telegram

Para asegurarnos de que nuestra plataforma MetaTrader 5 puede comunicarse con Telegram, necesitamos añadir la URL API de Telegram a la lista de URLs permitidas en MetaTrader 5. Comenzamos abriendo MetaTrader 5 y navegando hasta el menú "Herramientas". Desde ahí, seleccionamos "Opciones", que también se puede abrir pulsando "CTRL + O".

Herramientas -> Opciones

Una vez que aparezca la ventana "Opciones", vaya a la pestaña "Asesores Expertos". Aquí, marcamos la casilla "Allow WebRequest for listed URL" y añadimos la URL "https://api.telegram.org" a la lista. Este paso es crucial porque otorga a nuestro Asesor Experto los permisos necesarios para enviar peticiones HTTP a la API de Telegram, permitiéndole enviar mensajes y actualizaciones a nuestro bot de Telegram. Al configurar estos ajustes, garantizamos una comunicación fluida y segura entre nuestra plataforma MetaTrader 5 y Telegram, lo que permite supervisar y gestionar eficazmente nuestras actividades comerciales en tiempo real.

Ventana de opciones

Después de hacer todo eso, ya está todo listo y ahora podemos comenzar la implementación en MQL5, donde definimos toda la lógica que se utilizará para crear el programa que retransmite los mensajes de MQL5 a Telegram. Empecemos entonces.


Implementación en MQL5

La integración se basará en un Asesor Experto (EA). Para crear un Asesor Experto, en su terminal MetaTrader 5, haga clic en la pestaña Herramientas y marque Editor del Lenguaje MetaQuotes, o pulse F4 en su teclado. También puede hacer clic en el icono IDE (Integrated Development Environment) de la barra de herramientas. Esto abrirá el entorno del Editor del lenguaje MetaQuotes, que permite escribir robots comerciales, indicadores técnicos, scripts y bibliotecas de funciones.

Abrir IDE

Una vez abierto el MetaEditor, en la barra de herramientas, navega hasta la pestaña Archivo y marca Nuevo Archivo, o simplemente pulsa CTRL + N, para crear un nuevo documento. También puede hacer clic en el icono Nuevo de la pestaña Herramientas. Aparecerá una ventana emergente del Asistente MQL (MQL Wizard).

Crear un nuevo EA

En el Asistente que aparece, marque Asesor Experto (plantilla) y haga clic en Siguiente.

Asistente MQL (MQL Wizard)

En las propiedades generales del Asesor Experto, en la sección nombre, indique el nombre de archivo de su experto. Tenga en cuenta que para especificar o crear una carpeta si no existe, se utiliza la barra invertida antes del nombre del EA. Por ejemplo, aquí tenemos "Experts\" por defecto. Esto significa que nuestro EA se creará en la carpeta Experts y podremos encontrarlo allí. Las demás secciones son bastante sencillas, pero puede seguir el enlace que figura al final del Asistente para saber cómo realizar el proceso con precisión.

Nuevo EA

Después de proporcionar el nombre de archivo de Asesor Experto que desee, haga clic en Siguiente, haga clic en Siguiente y, a continuación, haga clic en Finalizar. Después de hacer todo esto, estamos listos para codificar y crear nuestro programa.

En primer lugar, empezamos definiendo algunos metadatos sobre el Asesor Experto (EA). Incluye el nombre del EA, la información sobre los derechos de autor y un enlace al sitio web de MetaQuotes. También especificamos la versión del EA, que se establece en "1.00". 

//+------------------------------------------------------------------+
//|                                          TG NOTIFICATIONS EA.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

Al cargar el programa, se realiza una información similar a la que se muestra a continuación.

Información de carga del EA

A continuación, definimos varias constantes que se utilizarán en todo nuestro código. 

const string TG_API_URL = "https://api.telegram.org";
const string botTkn = "7456439661:AAELUurPxI1jloZZl3Rt-zWHRDEvBk2venc";
const string chatID = "{YOUR CHAT ID}";

Aquí, la constante "TG_API_URL" contiene la URL base para la API de Telegram, que es esencial para enviar el Protocolo de transferencia de hipertexto (Hypertext Transfer Protocol, HTTP) y las peticiones a los servidores de Telegram. La constante "botTkn" contiene el token único para nuestro bot de Telegram, proporcionado por BotFather, que es necesario para la autenticación. La constante "chatID" es el identificador único del chat de Telegram al que queremos enviar los mensajes. Aquí es donde introduces tu ID de chat que obtuvimos usando el método getUpdates de la API de Telegram. Observa que hemos utilizado variables de cadena constantes. La palabra clave const garantiza que nuestras variables permanezcan intactas y sin cambios una vez definidas. Así, no tendremos que redefinirlos de nuevo y mantendrán sus valores de inicialización a lo largo de todo el código. De esta forma, ahorramos tiempo y espacio ya que no tenemos que volver a introducirlas cada vez que necesitamos los valores, simplemente llamamos a las variables necesarias y de nuevo, las posibilidades de introducir erróneamente sus valores se reducen significativamente.

Nuestro código se basará principalmente en la sección de inicialización experta, ya que queremos hacer ilustraciones rápidas sin tener que esperar las marcas en el gráfico para que se generen señales. Por lo tanto, OnInit, el controlador de eventos, albergará la mayor parte de la estructura del código.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit(){

   ...
   
   return(INIT_SUCCEEDED);
}

La función OnInit es un manejador de eventos que se llama en la instancia de inicialización del experto para hacer las inicializaciones necesarias si es necesario. 

Para realizar la comunicación con el servidor de Telegram, utilizamos una función incorporada en MQL5 llamada WebRequest. La función es típicamente una función de tipo de datos entero con sobrecarga, presentando dos formas.

Funciones WebRequest

Para simplificar, utilizaremos la segunda versión. Desglosemos la función para que podamos entender qué significa cada parámetro.

int WebRequest(
   const string method,      // HTTP method (e.g., "GET", "POST")
   const string url,         // URL of the web server
   const string headers,     // Optional HTTP headers
   int timeout,              // Request timeout in milliseconds
   const char &data[],       // Data to send with the request
   char &result[],           // Buffer to store the response
   string &result_headers    // Buffer to store the response headers
);

Expliquemos brevemente los parámetros de la función WebRequest.

  • method: El método HTTP que se utilizará para la solicitud.</b0 Los métodos más comunes son "GET" y "POST". "GET" se utiliza normalmente para recuperar datos de un servidor. "POST" se utiliza para enviar datos a un servidor.
  • url: La URL del servidor web al que se envía la solicitud. Esto incluye el protocolo (http:// o https://), el dominio y la ruta/recurso al que se accede.
  • headers: Cabeceras HTTP opcionales para incluir en la solicitud. Las cabeceras pueden proporcionar información adicional al servidor (por ejemplo, tipo de contenido, tokens de autenticación).
  • timeout: El tiempo máximo (en milisegundos) para esperar una respuesta del servidor. Si el servidor no responde en ese tiempo, la solicitud se cancela y se devuelve un código de error. Por ejemplo, si establecemos un tiempo de espera de 10000 milisegundos, tenemos 10000/1000 = 10 segundos.
  • data: Los datos a enviar con la solicitud. En el caso de las solicitudes "POST", suele tratarse del cuerpo de la solicitud (por ejemplo, datos del formulario, carga útil JSON).
  • result: El búfer para almacenar los datos de respuesta del servidor. Este array se llenará con la respuesta del servidor, que podremos procesar en nuestro código.
  • result_headers: El búfer para almacenar las cabeceras de respuesta del servidor. Esta cadena se rellenará con las cabeceras enviadas por el servidor en su respuesta.

Ahora que ya tenemos una idea de para qué sirven los parámetros y por qué los necesitamos, continuemos definiendo algunas de las variables más necesarias que utilizaremos.

   char data[];
   char res[];
   string resHeaders;
   string msg = "EA INITIALIZED ON CHART "+_Symbol;
   //https://api.telegram.org/bot{HTTP_API_TOKEN}/sendmessage?chat_id={CHAT_ID}&text={MESSAGE_TEXT}
   const string url = TG_API_URL+"/bot"+botTkn+"/sendmessage?chat_id="+chatID+
   "&text="+msg;

En primer lugar, declaramos las matrices "data" y "res" de tipo char. Estos arrays se utilizarán en la función WebRequest para contener los datos enviados y recibidos del servidor web, respectivamente. El array "data" está pensado para cualquier carga que queramos enviar con nuestra petición HTTP, aunque por ahora lo mantendremos vacío. El array "res" se rellenará con la respuesta del servidor, permitiéndonos procesar y utilizar la respuesta del servidor en nuestro programa.

A continuación, definimos una variable string llamada "resHeaders" para almacenar las cabeceras de la respuesta HTTP que recibimos del servidor. Las cabeceras de respuesta HTTP proporcionan metadatos importantes sobre la respuesta, como el tipo de contenido, la información del servidor y los códigos de estado. Al capturar estas cabeceras, podemos obtener más contexto sobre la respuesta y manejarla adecuadamente con nuestro Asesor Experto (EA).

A continuación creamos una variable de cadena llamada "msg" que contiene el mensaje que queremos enviar a Telegram. En este caso, el mensaje se establece como "EA INITIALIZED ON CHART" seguido del símbolo del gráfico actual, representado por la variable incorporada _Symbol. La variable _Symbol contiene el nombre del símbolo del instrumento financiero para el cual se ejecuta el EA, como "AUDUSD" o "GBPUSD". Al incluir esta información en nuestro mensaje, proporcionamos un contexto claro y específico sobre la acción o el suceso que se ha producido, lo que puede resultar especialmente útil a efectos de supervisión y registro. Esto es sólo un valor arbitrario que queremos mostrar cuando el programa se inicializa y por lo tanto usted puede tener el suyo propio.

A continuación construimos el localizador de recursos uniforme (Uniform Resource Locator, URL) necesario para realizar una petición a la API de Telegram. Comenzamos con la URL base almacenada en la constante "TG_API_URL", que es "https://api.telegram.org". A continuación, añadimos la ruta al método API "sendMessage", incluyendo el token de nuestro bot (botTkn). Este token identifica y autentica de forma única a nuestro bot con los servidores de Telegram, asegurando que la petición es válida y está autorizada. La ruta URL tiene este aspecto: "/bot<botTkn>/sendmessage", donde <botTkn> se sustituye por el token del bot real.

A continuación, añadimos los parámetros de consulta a la URL. El primer parámetro es "chat_id", que especifica el identificador único del chat de Telegram al que queremos enviar nuestro mensaje. Se almacena en la constante "chatID". El segundo parámetro es texto, que contiene el mensaje real que queremos enviar, almacenado en la variable "msg". Estos parámetros se concatenan a la URL base para formar la URL de solicitud completa. La URL final tiene este aspecto: "https://api.telegram.org/bot<botTkn>/sendmessage?chat_id=<chatID>&text=<msg>", donde <botTkn>, <chatID> y <msg> se sustituyen por sus respectivos valores.

Por último, sólo tenemos que llamar a la función para realizar la comunicación pasándole los argumentos necesarios.

   int send_res = WebRequest("POST",url,"",10000,data,res,resHeaders);

Aquí, empleamos la función WebRequest para enviar una solicitud HTTP POST a la URL designada. La comunicación con un servicio web externo, como la API de Telegram, requiere que utilicemos esta función. Debemos especificar el método HTTP; en este caso, es "POST". Utilizamos este método cuando enviamos datos a un servidor que realiza alguna acción. La acción que queremos que realice este servidor es enviar un mensaje a un chat de Telegram. Proporcionamos la variable "url", que construimos anteriormente en el código. La URL que utilizamos contiene la dirección base de la API de Telegram, nuestro token único de bot, el método "sendMessage" de la API, la ID del chat al que queremos enviar el mensaje y el texto del mensaje en sí.

A continuación, especificamos que el parámetro headers es una cadena vacía, lo que indica que esta solicitud no necesita ninguna cabecera HTTP adicional. El tiempo de espera se especifica en 10 segundos, que suele ser 10*1000 = 10000 milisegundos, lo que suele ser bastante generoso en un mundo en el que los servidores suelen responder en pocos segundos. Este tiempo de espera evita que la solicitud se interrumpa indefinidamente y está diseñado para mantener la capacidad de respuesta del EA. Lo siguiente que hacemos es pasar el array de datos y el array de respuesta a la función. El array "data" contiene cualquier información extra que queramos enviar con la petición, y usamos el array response para contener el resultado de la petición. Por último, pasamos la cadena de cabecera de respuesta, que la función también utiliza para "almacenar" la cabecera de respuesta enviada por el servidor.

La función devuelve un código de estado entero, almacenado en la variable "send_res", que indica si la solicitud se ha realizado correctamente o si se ha producido un error. A partir de los resultados, podemos comprobar si el mensaje se ha enviado correctamente y, en caso contrario, informar del error encontrado.

Tras realizar la petición HTTP, podemos gestionar la respuesta comprobando el código de estado almacenado en la variable "send_res". Para conseguirlo, podemos utilizar sentencias condicionales para determinar el resultado de nuestra solicitud y tomar las medidas adecuadas en función del código de estado devuelto.

   if (send_res == 200){
      Print("TELEGRAM MESSAGE SENT SUCCESSFULLY");
   }

Aquí, si nuestra variable contiene el código de estado 200, entonces sabemos que nuestra solicitud fue exitosa. Podemos tomar esto como una señal de que nuestro mensaje llegó al chat de Telegram especificado. Así que, en este caso, imprimimos en el terminal algo parecido a "TELEGRAM MESSAGE SENT SUCCESSFULLY".

   else if (send_res == -1){
      if (GetLastError()==4014){
         Print("PLEASE ADD THE ",TG_API_URL," TO THE TERMINAL");
      }
      Print("UNABLE TO SEND THE TELEGRAM MESSAGE");
   }

Si el resultado no es igual a 200, comprobamos a continuación si es igual a -1. Este estado nos indica que algo ha fallado en la petición HTTP: ¡error! Pero no podemos dejar a nuestro usuario final atrapado en esta pantalla de error. Para que las cosas tengan más sentido para ellos, podemos ser un poco más detallados y astutos con nuestros mensajes de error. Eso es exactamente lo que vamos a hacer a continuación.

En primer lugar, comprobamos el error específico (mensaje) que recibimos cuando falló la llamada a la función. Utilizamos la función GetLastError para recuperar el código de error que nos indica qué ha ido mal. A continuación, interpretamos el escenario probable (lo que significa el código de error) e imprimimos un mensaje al usuario que le guiará para solucionar el problema que ha causado el error. En este caso, si es igual a 4014, sabemos que la URL no está listada ni habilitada en el terminal. Así pues, informamos al usuario para que añada y active la URL correcta en su terminal de negociación. Vamos a ponerlo a prueba para ver la importancia del "grito".

Cuando el problema no está asociado a la restricción de URL (GetLastError no arroja 4014), no nos limitamos a encogernos de hombros resignadamente. Imprimimos (print) un mensaje para el usuario, que indica claramente la naturaleza de la avería: "UNABLE TO SEND THE TELEGRAM MESSAGE". Ya es bastante malo que no podamos comunicarnos con nuestro bot, pero que un bot, y nosotros dos a este lado de la pantalla, quedemos completamente mudos, es peor que nada. Incluso detectamos la condición de respuesta "anómala" aleatoria.

   else if (send_res != 200){
      Print("UNEXPECTED RESPONSE ",send_res," ERR CODE = ",GetLastError());
   }

Si "send_res" no es equivalente a 200 (es decir, no es bueno), y no es -1 (lo que indica un problema obvio relacionado con la restricción de URL), entonces tenemos un rompecabezas entre manos. Si todo va bien, devolvemos el valor entero conseguido.

   return(INIT_SUCCEEDED);

Vamos a probarlo y ver si todo funciona bien.

En el chat del bot de Telegram, esto es lo que obtenemos:

Primer mensaje de Telegram

En el terminal de operaciones, esto es lo que obtenemos:

Primer mensaje en el terminal

Puedes ver que fuimos capaces de enviar un mensaje desde el terminal de comercio al servidor de telegram que lo retransmitió al chat de telegram, lo que significa que es un éxito.

El código fuente completo responsable de enviar el mensaje desde el terminal de operaciones al chat de Telegram a través del bot es el siguiente:

//+------------------------------------------------------------------+
//|                                          TG NOTIFICATIONS EA.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

// Define constants for Telegram API URL, bot token, and chat ID
const string TG_API_URL = "https://api.telegram.org";  // Base URL for Telegram API
const string botTkn = "7456439661:AAELUurPxI1jloZZl3Rt-zWHRDEvBk2venc";  // Telegram bot token
const string chatID = "{YOUR CHAT ID}";  // Chat ID for the Telegram chat

// The following URL can be used to get updates from the bot and retrieve the chat ID
// CHAT ID = https://api.telegram.org/bot{BOT TOKEN}/getUpdates
// https://api.telegram.org/bot7456439661:AAELUurPxI1jloZZl3Rt-zWHRDEvBk2venc/getUpdates

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
   char data[];  // Array to hold data to be sent in the web request (empty in this case)
   char res[];  // Array to hold the response data from the web request
   string resHeaders;  // String to hold the response headers from the web request
   string msg = "EA INITIALIZED ON CHART " + _Symbol;  // Message to send, including the chart symbol

   // Construct the URL for the Telegram API request to send a message
   // Format: https://api.telegram.org/bot{HTTP_API_TOKEN}/sendmessage?chat_id={CHAT_ID}&text={MESSAGE_TEXT}
   const string url = TG_API_URL + "/bot" + botTkn + "/sendmessage?chat_id=" + chatID +
      "&text=" + msg;

   // Send the web request to the Telegram API
   int send_res = WebRequest("POST", url, "", 10000, data, res, resHeaders);

   // Check the response status of the web request
   if (send_res == 200) {
      // If the response status is 200 (OK), print a success message
      Print("TELEGRAM MESSAGE SENT SUCCESSFULLY");
   } else if (send_res == -1) {
      // If the response status is -1 (error), check the specific error code
      if (GetLastError() == 4014) {
         // If the error code is 4014, it means the Telegram API URL is not allowed in the terminal
         Print("PLEASE ADD THE ", TG_API_URL, " TO THE TERMINAL");
      }
      // Print a general error message if the request fails
      Print("UNABLE TO SEND THE TELEGRAM MESSAGE");
   } else if (send_res != 200) {
      // If the response status is not 200 or -1, print the unexpected response code and error code
      Print("UNEXPECTED RESPONSE ", send_res, " ERR CODE = ", GetLastError());
   }

   return(INIT_SUCCEEDED);  // Return initialization success status
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   // Code to execute when the expert is deinitialized
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
   // Code to execute on every tick event
}
//+------------------------------------------------------------------+

Ya que esto ha sido un éxito, en el siguiente subtema, vamos a alterar el código a unos cuantos formatos de mensaje diferentes para que podamos ver nuestro alcance en el envío de mensajes, cometer los errores que uno puede cometer y ver cómo mitigarlos. Por lo tanto, también es igualmente significativo.


Probando la integración

Para asegurarnos de que nuestro Asesor Experto (EA) envía correctamente mensajes a Telegram, necesitamos probar la integración a fondo. Un aspecto crucial de las pruebas es verificar el comportamiento del EA cuando ciertas configuraciones son incorrectas, como cuando la casilla "Allow WebRequest for listed URL" está desactivada en el terminal de operaciones. Para asegurarnos de que lo hacemos correctamente, desactivemos la casilla.

Casilla de verificación deshabilitada

Si ejecutamos el programa, obtenemos un error que indica al usuario que la comunicación sólo puede realizarse si el enlace proporcionado está incluido y permitido en el terminal de negociación.

Error detallado

Además, puede ver que no sólo informamos del error, sino que también presentamos al usuario una solución viable para mitigar los errores encontrados.

Ahora que ya podemos identificar y solucionar los errores, procedamos a hacer los formatos de los mensajes más creativos, claros y elegantes. En primer lugar, incluyamos emojis en nuestro mensaje inicial.

   //--- Simple Notification with Emoji:
   string msg = "🚀 EA INITIALIZED ON CHART " + _Symbol + " 🚀";

En este caso, sólo añadimos dos emojis de cohetes al mensaje inicial. Tras la compilación, esto es lo que obtenemos:

Emoji de cohete

Puedes ver que el mensaje sencillo con el emoji se ha enviado correctamente. Para obtener los caracteres emoji, basta con pulsar simultáneamente las teclas Windows + punto (.). Ahora podemos seguir siendo más creativos y modificar nuestro mensaje de notificación para que contenga señales de negociación como "BUY" o "SELL", información sobre el saldo de la cuenta, la apertura de instancias de negociación, niveles de negociación modificados como Stop Loss y Take Profit, resumen de rendimiento diario e información actualizada sobre el estado de la cuenta. Se trata de mensajes arbitrarios que pueden modificarse para adaptarse al estilo de negociación de cada uno. Esto se consigue mediante el siguiente código.

   //--- Simple Notification with Emoji:
   string msg = "🚀 EA INITIALIZED ON CHART " + _Symbol + " 🚀";
   //--- Buy/Sell Signal with Emoji:
   string msg = "📈 BUY SIGNAL GENERATED ON " + _Symbol + " 📈";
   string msg = "📉 SELL SIGNAL GENERATED ON " + _Symbol + " 📉";
   //--- Account Balance Notification:
   double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);
   string msg = "💰 Account Balance: $" + DoubleToString(accountBalance, 2) + " 💰";
   //--- Trade Opened Notification:
   string orderType = "BUY";  // or "SELL"
   double lotSize = 0.1;  // Example lot size
   double price = 1.12345;  // Example price
   string msg = "🔔 " + orderType + " order opened on " + _Symbol + "; Lot size: " + DoubleToString(lotSize, 2) + "; Price: " + DoubleToString(price, 5) + " 🔔";
   //--- Stop Loss and Take Profit Update:
   double stopLoss = 1.12000;  // Example stop loss
   double takeProfit = 1.13000;  // Example take profit
   string msg = "🔄 Stop Loss and Take Profit Updated on " + _Symbol + "; Stop Loss: " + DoubleToString(stopLoss, 5) + "; Take Profit: " + DoubleToString(takeProfit, 5) + " 🔄";
   //--- Daily Performance Summary:
   double profitToday = 150.00;  // Example profit for the day
   string msg = "📅 Daily Performance Summary 📅; Symbol: " + _Symbol + "; Profit Today: $" + DoubleToString(profitToday, 2);
   //--- Trade Closed Notification:
   string orderType = "BUY";  // or "SELL"
   double profit = 50.00;  // Example profit
   string msg = "❌ " + orderType + " trade closed on " + _Symbol + "; Profit: $" + DoubleToString(profit, 2) + " ❌";
   //--- Account Status Update:
   double accountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   double accountFreeMargin = AccountInfoDouble(ACCOUNT_FREEMARGIN);
   string msg = "📊 Account Status 📊; Equity: $" + DoubleToString(accountEquity, 2) + "; Free Margin: $" + DoubleToString(accountFreeMargin, 2);

Cuando ejecutamos este fragmento de código con los formatos de mensaje individualmente, obtenemos la siguiente suma de resultados:

Resultados del mensaje de integración

A partir del fragmento de código y la imagen anteriores, se puede ver que la integración fue un éxito. De este modo, logramos nuestro objetivo de enviar mensajes desde los terminales comerciales al chat bot de Telegram. En caso de que quieras enviar los mensajes a un canal o grupo de Telegram, sólo tienes que añadir el bot al grupo o canal y convertirlo en administrador. Por ejemplo, nosotros creamos un grupo y lo llamamos "Forex Algo Trader Group", tomando nuestro nombre y logotipo, pero usted puede asignar al suyo un nombre más creativo y diferente. Después, convertimos al bot en administrador. 

Bot administrador

Sin embargo, incluso si promocionas el bot a un administrador, todavía necesitas obtener la ID de chat para el grupo específicamente. Si la ID de chat del bot permanece, los mensajes siempre se reenviarán a él y no al grupo previsto. Por lo tanto, el proceso para obtener la ID del grupo es similar al inicial. 

// The following URL can be used to get updates from the bot and retrieve the chat ID
// CHAT ID = https://api.telegram.org/bot{BOT TOKEN}/getUpdates
https://api.telegram.org/bot7456439661:AAELUurPxI1jloZZl3Rt-zWHRDEvBk2venc/getUpdates

Sólo tenemos que enviar un mensaje al grupo y ejecutar el código en el navegador. El mensaje que enviamos es el siguiente

Mensaje inicial del grupo para obtener el "Chat ID"

En el navegador, obtenemos la siguiente información en un formato estructurado:

{
  "ok": true,
  "result": [
    {
      "update_id": 794283177,
      "my_chat_member": {
        "chat": {
          "id": -4273023945,
          "title": "Forex Algo Trader Group",
          "type": "group",
          "all_members_are_administrators": true
        },
        "from": {
          "id": <YOUR ID>,
          "is_bot": false,
          "first_name": "Forex Algo-Trader",
          "username": "Forex_Algo_Trader",
          "language_code": "en"
        },
        "date": 1722593740,
        "old_chat_member": {
          "user": {
            "id": 
<YOUR ID> ,
            "is_bot": true,
            "first_name": "mql5tg_allan_bot",
            "username": "mql5_tg_allan_bot"
          },
          "status": "left"
        },
        "new_chat_member": {
          "user": {
            "id": <YOUR ID>,
            "is_bot": true,
            "first_name": "mql5tg_allan_bot",
            "username": "mql5_tg_allan_bot"
          },
          "status": "member"
        }
      }
    },
    {
      "update_id": 794283178,
      "message": {
        "message_id": 64,
        "from": {
          "id": 
<FROM ID> ,
          "is_bot": false,
          "first_name": "Forex Algo-Trader",
          "username": "Forex_Algo_Trader",
          "language_code": "en"
        },
        "chat": {
          "id": -4273023945,
          "title": "Forex Algo Trader Group",
          "type": "group",
          "all_members_are_administrators": true
        },
        "date": 1722593740,
        "new_chat_participant": {
          "id": 
<NEW ID> ,
          "is_bot": true,
          "first_name": "mql5tg_allan_bot",
          "username": "mql5_tg_allan_bot"
        },
        "new_chat_member": {
          "id": <NEW ID>,
          "is_bot": true,
          "first_name": "mql5tg_allan_bot",
          "username": "mql5_tg_allan_bot"
        },
        "new_chat_members": [
          {
            "id": 
<NEW ID> ,
            "is_bot": true,
            "first_name": "mql5tg_allan_bot",
            "username": "mql5_tg_allan_bot"
          }
        ]
      }
    },
    {
      "update_id": 794283179,
      "my_chat_member": {
        "chat": {
          "id": -4273023945,
          "title": "Forex Algo Trader Group",
          "type": "group",
          "all_members_are_administrators": true
        },
        "from": {
          "id": <FROM ID>,
          "is_bot": false,
          "first_name": "Forex Algo-Trader",
          "username": "Forex_Algo_Trader",
          "language_code": "en"
        },
        "date": 1722593975,
        "old_chat_member": {
          "user": {
            "id": <USER ID>,
            "is_bot": true,
            "first_name": "mql5tg_allan_bot",
            "username": "mql5_tg_allan_bot"
          },
          "status": "member"
        },
        "new_chat_member": {
          "user": {
            "id": <USER ID>,
            "is_bot": true,
            "first_name": "mql5tg_allan_bot",
            "username": "mql5_tg_allan_bot"
          },
          "status": "administrator",
          "can_be_edited": false,
          "can_manage_chat": true,
          "can_change_info": true,
          "can_delete_messages": true,
          "can_invite_users": true,
          "can_restrict_members": true,
          "can_pin_messages": true,
          "can_promote_members": false,
          "can_manage_video_chats": true,
          "can_post_stories": false,
          "can_edit_stories": false,
          "can_delete_stories": false,
          "is_anonymous": false,
          "can_manage_voice_chats": true
        }
      }
    },
    {
      "update_id": 794283180,
      "message": {
        "message_id": 65,
        "from": {
          "id": <YOUR FROM ID>,
          "is_bot": false,
          "first_name": "Forex Algo-Trader",
          "username": "Forex_Algo_Trader",
          "language_code": "en"
        },
        "chat": {
          "id": -4273023945,
          "title": "Forex Algo Trader Group",
          "type": "group",
          "all_members_are_administrators": true
        },
        "date": 1722594029,
        "text": "MESSAGE TO GET THE CHAT ID"
      }
    }
  ]
}

Aquí, nuestro ID de chat tiene un signo negativo delante del número. Este es el ID que extraemos y lo cambiamos por el inicial. Así que ahora nuestro ID de chat será el siguiente:

// Define constants for Telegram API URL, bot token, and chat ID
const string TG_API_URL = "https://api.telegram.org";  // Base URL for Telegram API
const string botTkn = "7456439661:AAELUurPxI1jloZZl3Rt-zWHRDEvBk2venc";  // Telegram bot token
const string chatID = "-4273023945";  // Chat ID for the Telegram chat

Si ejecutamos esto, obtendremos el siguiente resultado.

Chat de grupo de Telegram

Hasta este punto, se puede ver que hemos sido capaces de crear un programa en MQL5 que envía correctamente mensajes desde el terminal de comercio al campo de chat del bot de Telegram con toda la información necesaria. Esto es un éxito para un mensaje simple pero para mensajes complejos que contengan caracteres extraños como Caracteres de salto de línea "\n" o letras de Conjuntos de caracteres Unicode como los códigos emoji "U+1F600" no se enviarán. Lo estudiaremos en las siguientes partes. Por ahora, mantengamos todo simple y directo al grano. ¡Salud!


Conclusión

En este artículo, creamos un Asesor Experto que funciona con MQL5 y Telegram. Esto permite la comunicación entre el terminal y un bot de Telegram, lo que significa que puedes enviar mensajes del terminal al bot y del bot al terminal. Esto está muy bien por dos razones: una, porque el bot es esencialmente un proxy entre usted y el terminal para enviar y recibir mensajes; dos, porque por alguna razón, esta configuración de comercio parece mucho más cool que enviar un mensaje por correo electrónico.

También hemos indagado en el proceso de pruebas, señalando los posibles errores que pueden producirse cuando los parámetros WebRequest no están correctamente configurados. Hemos averiguado los motivos de estos errores y los hemos corregido para que el programa funcione ahora con mayor fiabilidad. Es decir, funciona sin problemas ni errores, enviando mensajes con la información correcta al lugar adecuado en el momento oportuno. Esta comprensión del "por qué" y el "cómo" del error nos permite construir con confianza en el futuro, sabiendo que nuestra "célula fundacional" es de fiar.

En las siguientes partes de esta serie, elevaremos nuestra integración a un nivel superior construyendo un indicador personalizado que produzca señales de trading. Estas señales se utilizarán para enviar mensajes a nuestro chat de grupo en Telegram, lo que nos proporcionará actualizaciones en tiempo real sobre el tipo de oportunidades potenciales que solemos buscar y aprovechar. No se trata sólo de hacer que nuestra estrategia comercial funcione mejor. También se trata de mostrar cómo podemos combinar MQL5 con Telegram para crear un flujo de trabajo de trading dinámico que envíe alertas sin que tengamos que hacer nada más que mirar nuestros teléfonos. Permanezca atento mientras seguimos construyendo y perfeccionando este sistema integrado.


Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15457

Archivos adjuntos |
Creación de un asesor experto integrado de MQL5 y Telegram (Parte 2): Envío de señales de MQL5 a Telegram Creación de un asesor experto integrado de MQL5 y Telegram (Parte 2): Envío de señales de MQL5 a Telegram
En este artículo, creamos un Asesor Experto integrado con MQL5 y Telegram que envía señales de cruce de medias móviles a Telegram. Detallamos el proceso de generación de señales de trading a partir de cruces de medias móviles, implementando el código necesario en MQL5, y asegurando que la integración funciona a la perfección. El resultado es un sistema que proporciona alertas comerciales en tiempo real directamente a su chat grupal de Telegram.
Aprendizaje automático y Data Science (Parte 29): Consejos esenciales para seleccionar los mejores datos de divisas para el entrenamiento de IA Aprendizaje automático y Data Science (Parte 29): Consejos esenciales para seleccionar los mejores datos de divisas para el entrenamiento de IA
En este artículo, profundizamos en los aspectos cruciales de la elección de los datos de Forex más relevantes y de alta calidad para mejorar el rendimiento de los modelos de IA.
Características del Wizard MQL5 que debe conocer (Parte 31): Selección de la función de pérdida Características del Wizard MQL5 que debe conocer (Parte 31): Selección de la función de pérdida
La función de pérdida es la métrica clave de los algoritmos de aprendizaje automático que proporciona información al proceso de formación cuantificando el rendimiento de un conjunto determinado de parámetros en comparación con el objetivo previsto. Exploramos los distintos formatos de esta función en una clase de asistente personalizada MQL5.
Implementación de Deus EA: Trading automatizado con RSI y promedios móviles en MQL5 Implementación de Deus EA: Trading automatizado con RSI y promedios móviles en MQL5
Este artículo describe los pasos para implementar Deus EA basado en los indicadores RSI y promedio móvil para guiar el trading automatizado.