Categorías
Programación

Enviar mensajes a Telegram

Configuración y código NinjaScript para enviar mensajes de texto e imagénes a Telegram.

Desde un indicador, estrategia, Add-On y en general cualquier NinjaScript de NinjaTrader, se pueden enviar mensajes con texto y/o imágenes a Telegram.

Para lograr la comunicación entre Telegram y NinjaTrader hay que realizar dos tipos de acciones:

  1. Configuración en Telegram para crear un bot y un canal.
  2. Programación del código correspondiente en NinjaTrader.

Para este artículo voy a utilizar como caso práctico un indicador de NinjaTrader, de modo que cuando se haga doble clic sobre el panel del chart en el que está cargado el indicador, se envíe a Telegram un mensaje con un texto y otro mensaje con la captura de pantalla del chart.

Al final del artículo se encuentran las actualizaciones que he añadido al contenido original.


Crear un bot en Telegram

El bot servirá para la comunicación entre Telegram y NinjaTrader.

Primero instalamos en el teléfono móvil la app Telegram, si no la tuviéramos ya instalada.

Ahora hay que crear el bot. Abrimos el browser en el móvil, y en la barra de direcciones escribimos : telegram.me/botfather

Instalar BotFather
Escribir en el browser del teléfono móvil la URL telegram.me/botfather

Esto abrirá Telegram y creará automáticamente un nuevo canal llamado BotFather desde el cuál podremos crear y gestionar nuestros bots. Entramos en el canal BotFather y escribimos /newbot.

A continuación el canal solicita un nombre para el bot (en el ejemplo he usado testbolsa01), y un usuario para el bot (he usado testbolsa01bot).

BotFather. Comando newbot

Tras introducir los datos anteriores, el canal me devuelve un mensaje que incluye un token o identificador único para el bot. Este token debe conservarse de forma segura y no compartirse. Más adelante lo utilizaremos en el código NinjaScript. Opcionalmente puedo comprobar que el bot se ha creado correctamente, ejecutando el comando /mybots que mostrará una lista con el bot.

Telegram Bot Token-ID para enviar mensajes a Telegram

Para establecer una comunicación básica con el bot y comprobar que está activo puedo abrir un navegador en cualquier dispositivo (pc, teléfono móvil o tablet) y escribir en su barra de direcciones: https://api.telegram.org/bot<TOKEN-ID>/getMe

Donde <TOKEN-ID> es el token del bot; con lo que siguiendo con el ejemplo habría que escribir: https://api.telegram.org/bot746195535:AAE80G12j0IMTb3AgjnzjvH64k28amzFIDc/getMe

Si el bot está operativo en la ventana del browser aparecerá un simple mensaje de éxito como el siguiente, con el parámetro ok = true.

Telegram Browser Success

Crear un channel en Telegram

Una vez creado el bot que servirá para enviar mensajes a Telegram, el siguiente paso es crear el canal de Telegram donde se publicarán los mensajes enviados.

Abrimos el menú de Telegram y seleccionamos Nuevo canal.

Telegram. Crear Nuevo Canal

Para el nombre del canal recomiendo emplear palabras simples, sin espacios en blanco, ni tildes ni símbolos de acentuación o especiales. Y aún así puede que el nombre del canal dé problemas y el código NinjaScript capture una excepción de «Chat no encontrado» en cuyo caso habrá que probar con otro nombre.

Elijo arbitrariamente testbolsa02 como nombre para el canal. El canal debe ser público.

Telegram Nuevo Canal creado

Autorizar al bot como administrador

Ahora hay que autorizar al bot testbolsa01bot como administrador del canal testbolsa02.

Entramos en el canal testbolsa02 y pulsamos sobre el encabezado para abrir la configuración.

Configuración Canal para enviar mensajes a Telegram

Pulsamos en Miembros/Administradores y por último en Añadir administrador.

Telegram. Añadir Administrador

Pulsamos en la lupa para abrir la búsqueda y escribimos testbolsa01bot. Y lo elegimos para añadirlo a los administradores del canal.

Telegram Buscar Administrador

Nos aseguramos de que tenga los siguientes permisos. Y pulsamos en el tick de Aceptar.

Permisos Administrador Telegram

Y con esto finalizamos la configuración en Telegram.


Importar librerías en NinjaTrader

Existe un proyecto opensource para enviar mensajes desde aplicaciones .NET a Telegram que se encuentra en este repositorio de GitHub. Aquí el lector encontrará documentación detallada sobre Telegram y la comunicación con .NET.

Pero en resumen y para el objetivo que estamos persiguiendo, sólo necesitamos conseguir dos ficheros DLL:

  • Telegram.Bot.dll
  • Newtonsoft.Json.dll

La versión más reciente de los ficheros se puede obtener clonando el repositorio de GitHub y compilando la solución en VisualStudio. Pero para facilitar la tarea también se pueden descargar directamente desde los links que facilito al final del artículo, aunque con el riesgo de que los ficheros estén desactualizados.

Una vez conseguidas las 2 DLL’s, hay que copiarlas en el directorio \Documents\NinjaTrader 8\bin\Custom.

Después arrancamos NinjaTrader, abrimos el NinjaScript Editor, clic derecho para abrir el menú contextual, clic en References…, pulsamos en add y añadimos las 2 DLL’s anteriores.

Código de la estrategia en NinjaTrader

Desde el NinjaScript Editor creamos una estrategia nueva y añadimos las siguientes constantes y variables globales. Observar que el nombre del canal debe ir prefijado con una arroba.

Variables globales para enviar mensajes a Telegram

Dentro del método OnStateChange, en el State.DataLoaded creamos un objeto de tipo TelegramBotClient que usaremos para la comunicación con el bot de Telegram. Al método constructor hay que pasarle el token del bot que nos facilitó BotFather.

En el State.Historical obtenemos la referencia al Chart y nos subscribimos al evento de pulsación del mouse en el panel en que se cargue el indicador. La referencia al Chart hay que conseguirla desde un Dispatcher para no provocar excepciones de seguridad por intentar acceder a objetos propiedad del hilo UI principal. En el State.Terminated nos desubscribimos del evento para liberar los recursos asociados.

OnStateChange para enviar mensajes a Telegram

Método manejador del evento MouseMove

Dentro de este método programamos el comportamiento para cuando el usuario haga doble clic sobre el panel en el cuál está cargado el indicador.

Primero se comprueba que el usuario ha hecho doble clic. Después se obtiene una captura de pantalla de todo el chart. Esa captura se codifica y se graba a un Stream que se enviará a continuación a Telegram en modo asíncrono.

NinjaScript MouseDown para enviar mensajes a Telegram

Envío asíncrono a Telegram

Es necesario crear un método asíncrono para la comunicación con Telegram. Desde ese método asíncrono enviamos el Stream anterior que contiene la captura de pantalla. También aprovechamos para enviar un mensaje de texto.

Enviar mensajes a Telegram

Compilamos el código y ya está la solución finalizada. Cargamos el indicador en un chart y al hacer doble clic sobre su panel se deberían enviar los dos mensajes (texto + imagen) al canal de Telegram.


Descargas

Fichero comprimido con las dos DLL’s y el código fuente del indicador.


Actualizaciones

El artículo ha sido actualizado con dos videos de ejemplo de cómo crear un bot y un canal en Telegram, que se muestran a continuación. Estos videos son complementarios al contenido del artículo.

También he añadido un ejemplo de código para enviar un mensaje + imagen a Telegram cuando se cumple una condición lógica.

Código con condición lógica

El ejemplo que hemos visto tiene una finalidad didáctica. Pero sería más útil enviar el mensaje desde una estrategia automática, cuando se cumpla una condición lógica como puede ser la concurrencia de señales procedentes de indicadores para abrir posición, o bien al lograrse el filled de una orden de entrada, o al saltar un stop-loss, etc.

En el ejemplo voy a simplificar al máximo la condición lógica y voy a enviar un mensaje de texto y una captura de pantalla del chart cuando la barra corriente sea la 20. Evidentemente el lector tendrá que modificar esta condición y editarla de acuerdo a sus necesidades.

Código enviar texto + imagen a Telegram

16 respuestas a «Enviar mensajes a Telegram»

Hola, he seguido tus pasos y en output1 del ninja me aparece el siguiente mensaje y no se envia nada al grupo de telegram:
Screenshot submitted to Telegram…
Telegram.Bot.Exceptions.ChatNotFoundException: chat not found
at Telegram.Bot.TelegramBotClient.d__54`1.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at NinjaTrader.NinjaScript.Indicators.Utilities.Zi8ScreenSnapShot.d__2.MoveNext()

Hola Andreu, según parece hay un problema en Telegram con el canal, que no lo encuentra. Asegúrate bien de todos los pasos al configurar el bot y el canal en Telegram, la arroba delante del nombre, de que el canal sea público (si es privado no funciona), que el bot está autorizado como administrador, etc. Te aseguro que la solución funciona porque la utilizo en mis sistemas, y me llegan al instante tanto los mensajes de texto como las capturas de imagen del chart. Saludos

saludos.. muchas gracias por su colaboracion
tengo un dilema ya hice todo lo que puso en el tutorial pero cuando compilo me sale error CS0101 en linea 31 col 14 y no hallo el error me prodia ayudar con eso

Hola Jair, la línea 31 es la cabecera de la declaración de la clase: public class Zi8ScreenSnapShot : Indicator
No hay lugar para ningún error.
El fichero .zip es para NinjaTrader 8 y se debe importar, sin descomprimir, desde Tools / Import / Ninjascript Add-On.
Este proceso de import genera un indicador llamado Zi8ScreenSnapShot. Comprueba si el mensaje de error que te aparece en el log es de este script. Posiblemente sea de otro indicador o estrategia que tengas en tu librería.
Saludos

saludos de nuevo alguna recomendación porque ya hice lo que me recomendó pero me sale una advertencia «estos archivos de ninjascript fue realizado desde una versión anterior incompatible de ninja trader» y tengo una versión reciente de ninja8 64bits

Mi versión es la 8.0.21.0 64-bits (es del 25 de febrero de 2020). Pero me extraña que la versión sea el problema.
Prueba a borrar el indicador siguiendo estos pasos:

  1. Abre el editor de código desde New/NinjaScript Editor.
  2. En el NinjaScript Explorer abre la carpeta Indicators/Utilities.
  3. Haz clic derecho sobre el indicador Zi8ScreenSnapShot y pulsa en Remove.
  4. Por último pulsa en el botón Compile en la barra de botones del NinjaScript Editor.

De este modo el indicador ya no existirá en la librería y si te aparece algún error en la compilación será debido a otro indicador o estrategia. En una de las columnas del log del Editor te informará del nombre del NinjaScript (indicador, estrategia, Add-On, etc) que causa el error.
Saludos

¡Hola!. Muchas gracias por este post. Me ha funcionado a la primera. Increíblemente bien explicado paso a paso.

Ahora estoy intentando que me envíe a Telegram el mensaje y captura de pantalla si ocurre un evento (el precio mayor a un nivel) en OnBarUpdate.

Compila bien pero en la ejecución me aparece un error en el Log y se cuelga.

Estoy viendo si encuentro la forma de hacerlo funcionar.

Saludos cordiales.

Gracias por tu comentario Juan Carlos. Si quieres comparte por aquí el mensaje de error por si puedo ayudarte. Pero empieza por asegurarte de que no se envíe el mensaje en barras históricas, quizás de ahí provenga el error. Por ejemplo, al inicio del OnBarUpdate o al menos antes de enviar el mensaje, puedes escribir:
if( State == State.Historical)
return;

Gracias por tu pronta respuesta. El error se produce en ejecución, cuando el precio llega a un determinado nivel, no en barras históricas:

Error on calling «OnBarUpdate» method on bar xxxx: The calling thread cannot access this object because a different thread owns it.

Básicamente, lo que intento hacer es que cuando el precio llega a un determinado nivel, hago que suene una alarma y reutilizo dentro de OnBarUpdate las instrucciones para capturar la pantalla y enviar los mensajes. Algo como esto:

if([Condición de Alarma])
{
Mensaje = «Largo en: » + Disparo.ToString(«N2»);
if (ch != null)
{
//Capturar la pantalla en un PngBitmapEncoder:
RenderTargetBitmap screenCapture = ch.GetScreenshot(ShareScreenshotType.Chart);
if (screenCapture == null)
return;
BitmapFrame outputFrame = BitmapFrame.Create(screenCapture);
//Enviar la imagen a Telegram :
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(outputFrame);
png.Save(ms);
Print(«Screenshot submitted to Telegram…»);
sendPhoto(ms.ToArray());
}
}
PlaySound(Alarma_Entrada);
Reset_Alarms = false;
}

La variable «Mensaje» la utilizo para cambiar el texto del mensaje telegram en sendPhoto:

await Bot.SendTextMessageAsync(CHAT_ID, Mensaje);

Calculo que no estoy considerando todo lo que debería para incluir este código aquí.

Muchas gracias por tu ayuda.

Saludos cordiales.

He añadido más contenido al post y un ejemplo con código para procesarse en una condicion lógica. Espero que te ayude a resolver el problema. Saludos

Bueno, no me sale la captura de pantalla pero no se cuelga.
El mensaje de texto me salía dos veces, porque Bot.SendTextMessageAsync está en sendMessage() y en dentro de SendPhotoAsync(CHAT_ID, ms), que está llamada en SendMessage() pero ya me apañe con eso.

Seguiré intentando a ver como saco el Telegram con el screenshot.

Otra vez, muchas gracias por tu ayuda.

Has probado con el código de ejemplo que puse en la actualización del artículo ? Es más breve y directo. Todo está dentro de un único método. Sólo tienes que cambiar la condición del if( CurrentBar == 20 ) por la que tú quieras.

¡Funciona fantástico! Y quedó supersimple de adaptar.
Este finde trataré de entenderlo, aparte de que funcione.
¡Muchísimas gracias!

De nada Juan Carlos, me alegro de que funcione bien y que te sea útil.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

  Acepto la política de privacidad