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:
- Configuración en Telegram para crear un bot y un canal.
- 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
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
).
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.
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
.
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.
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. Es imprescindible que el canal sea público. También nos aseguramos que el enlace de invitación esté informado, y las notificaciones activadas.
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.
Pulsamos en Miembros/Administradores y por último en 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.
Nos aseguramos de que tenga los siguientes permisos. Y pulsamos en el tick de Aceptar.
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.
Para nuestro ejemplo sólo necesitamos conseguir los siguientes ficheros DLL:
- Telegram.Bot.dll
- Newtonsoft.Json.dll
- System.Runtime.CompilerServices.Unsafe.dll
- System.Threading.Tasks.Extensions.dll
La versión más reciente de estos ficheros se puede obtener clonando la última versión de ese 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 conseguidos los cuatro ficheros DLL, hay que copiarlos 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 DLL’s anteriores.
Si en el futuro actualizáramos esos ficheros copiando y pegando versiones más recientes de los mismos y nuestro código NinjaScript dejara de funcionar, tendríamos que actualizar las References, borrando las antiguas y añadiendo las nuevas, aún cuando el nombre de los ficheros DLL sea el mismo.
Código de la estrategia en NinjaTrader
Desde el NinjaScript Editor creamos una estrategia nueva.
En la cabecera del código, dentro de la región Using declarations
, añadimos las siguientes declaraciones.
A continuación añadimos las siguientes constantes y variables globales. Observar que el nombre del canal debe ir prefijado con una arroba.
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.
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.
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.
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 DLL’s y el código fuente del indicador.
Enviar mensajes a Telegram
Actualización videos
Incluyo 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.
Actualización código con condición lógica
Añado un ejemplo de código para enviar mensajes (texto + imagen) a Telegram cuando se cumple una 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.
88 respuestas a «Enviar mensajes a Telegram desde NinjaTrader»
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
Ahora si, no se porque pero me lo cambio a privado…
Gracias por tu ayuda y por tu trabajo
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
muchas muchas gracias.. 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:
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.
Hola, me interesa mucho este post, es muy didáctico. He revisado el mismo y llegado a la parte final de introducir el código en Ninja Strategy me queda una duda, ya que no se donde ponerlo. Miro en el Strategy pero solo veo interface visual, al igual que en Builder.
No se si me he explicado bien, es la primera vez qe voy a usar el Strategy aunque ya he utilizado el Builder para programar cruces de medias, etc.
Un saludo y gracias por tus aportaciones
Hola Harry, para escribir código hay que hacerlo desde el NinjaScript Editor. Este ejemplo de Telegram lo he sintetizado al máximo pero aún así hay que tener algún conocimiento de programación para entenderlo y aplicarlo. Y por supuesto saberse manejar con el NinjaScript Editor. El Strategy Builder no cuenta.
En el artículo he dejado un fichero .zip para descargar. Contiene dos ficheros dll y el fichero .cs con el código completo del indicador para enviar mensajes a Telegram. En el artículo explico cómo instalar esos dos ficheros dll (simplemente hay que copiarlos en la carpeta indicada), y el .cs puedes abrirlo con cualquier editor de texto y hacer un copy+paste del código en tu indicador o estrategia.
Saludos
Gracias, voy a trastear con el Ninjascript a ver si consigo montar esta estrategia. Muchas gracias por tu ayuda. Un saludo
Hola,
Muy buen articulo Supperia!! Enhorabuena.
He creado ya un canal en telegram y he puesto las primeras 4 lineas en mi indicador:
private const string API_TOKEN = «numero:codigo»;
private const string CHAT_ID = «@testbolsa02»;
private TelegramBotClient Bot;
private Chart ch;
para probar, he dado a compilar el indicador y me sale el «unhandled exeption: cannot find the path specified».
En la carpeta de bin/Custom solo he copiado los 2 archivos:
Telegram.Bot.dll
Newtonsoft.Json.dll
y los he añadido con «add» desde el Ninjascript editor.
que crees que puede ser?
Gracias!
Gracias Manu,
en la carpeta NinjaTrader8/trace se guardan ficheros de log diarios para registrar errores, entre otras cosas.
Después de que te salte la excepción, abre el fichero que empieza por «trace» más reciente en esa carpeta y busca la información sobre la excepción y el motivo. Podrás ver qué Ninjascript (indicador/estrategia/etc) es el culpable del error y el número de línea en que sucede.
Por otro lado, el ejemplo para descargar también te da problemas ?
No te habrás olvidado de la sentencia
using
al principio del código?using Telegram.Bot;
Aunque la declaración de las sentencias
using
están incluidas en el código de los ficheros de ejemplo, he actualizado el artículo para recalcarlas.Saludos
Gracias Supperia,
De momento solo he añadido las 4 lineas que indicaba, mas las de using (me faltaba la de Windows.Media.Imaging, que la acabo de añadir, pero el error es el mismo).
El error me sale al darle a compilar el indicador.
el error que me da es:
2020-09-17 08:54:02:024 *************** unhandled exception trapped ***************
2020-09-17 08:54:02:024 The system cannot find the path specified
2020-09-17 08:54:02:032 System.ComponentModel.Win32Exception (0x80004005): The system cannot find the path specified
at Microsoft.Win32.NativeMethods.CreateDirectory(String path, SafeLocalMemHandle acl)
at System.CodeDom.Compiler.TempFileCollection.CreateTempDirectoryWithAce(String directory, String identity)
at System.CodeDom.Compiler.TempFileCollection.GetTempFileName(String tempDir)
at System.CodeDom.Compiler.TempFileCollection.EnsureTempNameCreated()
at System.CodeDom.Compiler.TempFileCollection.AddExtension(String fileExtension, Boolean keepFile)
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames)
at NinjaTrader.Code.Compiler.Compile(Boolean checkCompileOnly, Boolean debugBuild, IEnumerable`1 filesToIgnore, IEnumerable`1 filesInTmp)
at NinjaTrader.Gui.NinjaScript.Editor.EditorViewModel.c__DisplayClass214_0.b__1(Object s)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
Nada, acabo de probar con tu ejemplo tal cual, y sale el mismo error……
El error parece que ocurre al generar los ficheros temporales que se crean al compilar y se me ocurre que pueda deberse a permisos de la aplicación. Pero vete a saber. No tiene que ver con este código de Telegram, desde luego, es algo que afecta a tu instalación a más bajo nivel. Trabajas en Windows nativo o con máquina virtual ?
Para ir acotando el error borra los indicadores/estrategias que hayas creado desde la última vez que todo te funcionaba bien. Y compila. Si sigues con errores, prueba a quitar las dlls, etc. Como último recurso tendrías que reinstalar Ninja. Informa por aquí si lo vas resolviendo.
Hola,
Si, lo tengo en una maquina virtual, y ese parece ser el motivo…
en el ordenador de casa ha compilado sin problemas
Gracias!!
Gracias Manu por la información. Le será muy útil a cualquier lector que le ocurra lo mismo. Saludos
Buen post. Una consulta. Puedo a través de código cambiar la forma de las velas en ninjatrader ? Puedo hacer mi propio gráfico desde cero accediendo a los datos en tiempo real mediante código en ninjatrader ? Saludos
Hola Jesús, aunque tu consulta no tenga que ver con el artículo, te contesto por aquí.
Puedes construir tipos de barras personalizados para que las barras del chart se construyan siguiendo la lógica que indiques. Por ejemplo, construir barras delta con informacion del orderflow (bid,ask).
Esto se hace programando BarsTypes a medida. En la carpeta Custom/BarsTypes tienes los tipos de barras disponibles. Puedes crearte otros nuevos, sin límite.
Sin embargo, para alterar el aspecto de las barras puedes programar ChartStyles. En la carpeta Custom/ChartStyles están los disponibles por defecto, y del mismo modo puedes crearte los que quieras.
Obviamente para todo esto necesitas conocimientos más o menos avanzados de programación.
Saludos
gracias compañero una pregunta como puedo hacer para que me envie el mesaje cada vez que se realiza una orden.
como debo hacer o cual seria el codigo para que cada que abra y cierre una operacion me envie el mensaje gracias
Hola Arturo,
tienes que incluir el código expuesto en el artículo para el envío del mensaje a Telegram, en el lugar adecuado.
Si quieres que se envíe cada vez que se logra el filled de la orden (y también podrías diferenciar entre un filled parcial o total) tendrías que hacerlo dentro del método OnExecution.
El método OnExecution es llamado con cada filled de cualquier orden.
Si lo que quieres es que se envíe un mensaje a Telegram cada vez que NinjaTrader envíe una orden al bróker, tendrías que implementar el envío del mensaje a Telegram dentro del método OnOrderUpdate cuando el status de la orden sea Submitted.
Si quieres que se notifique cuando la posición esté abierta (Long o Short) o cerrada (Flat) puedes implementar el envío del mensaje a Telegram dentro del método OnPositionUpdate.
Saludos
realmente lo intente pero no fui capaz deseo que cada vez que se abra un corto o un largo o se cierre una posición en el chart me envie el mensaje a telegram el codigo lo tengo de esta forma y solo me envia el pantallazo cuando lo monto en el chart me podrias ayudar con eso gracias dime que cambios y donde los realizo gracias
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @»Enter the description for your new custom Indicator here.»;
Name = «Zi8ScreenSnapShot»;
Calculate = Calculate.OnBarClose;
IsOverlay = true;
DisplayInDataBox = true;
DrawOnPricePanel = true;
DrawHorizontalGridLines = true;
DrawVerticalGridLines = true;
PaintPriceMarkers = true;
ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right;
//Disable this property if your indicator requires custom values that cumulate with each new market data event.
//See Help Guide for additional information.
IsSuspendedWhileInactive = true;
}
else if (State == State.DataLoaded)
{
Bot = new TelegramBotClient(API_TOKEN);
}
else if (State == State.Historical)
{
if (ChartControl != null)
{
Dispatcher.BeginInvoke(new Action(() =>
{
ch = Window.GetWindow(ChartControl) as Chart;
}));
}
}
}
protected override void OnBarUpdate()
{
if (CurrentBar == 20)
{
sendCombiMessage();
}
}
private async Task sendCombiMessage()
{
Dispatcher.Invoke(new Action(async () =>
{
try
{
Chart _chart = Window.GetWindow(ChartControl) as Chart;
if (_chart != null)
{
RenderTargetBitmap screenCapture = _chart.GetScreenshot(ShareScreenshotType.Chart);
if (screenCapture == null)
return;
BitmapFrame outputframe = BitmapFrame.Create(screenCapture);
using (MemoryStream ns = new MemoryStream())
{
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(outputframe);
png.Save(ns);
byte[] bb = ns.ToArray();
MemoryStream nsbb = new MemoryStream(bb);
await Bot.SendTextMessageAsync(CHAT_ID, «orden a mercado ….»);
await Bot.SendPhotoAsync(CHAT_ID, nsbb);
}
}
}
catch (Exception ex)
{
Print(ex.ToString());
}
}));
gracias por tu atencion
Arturo, estás usando el mismo código del artículo, que sólo envía el mensaje en la barra 20. Si quieres reaccionar a algún evento de orden o posición, tendrás que hacerlo dentro de los otros métodos que te indiqué: OnOrderUpdate, OnExecutionUpdate, OnPositionUpdate.
al poner este codigo me aparece el error en la primera linea el error dice: no se encontro ningun miembro adecuado para invalidar
protected override void OnPositionUpdate(Cbi.Position position, double averagePrice,
int quantity, Cbi.MarketPosition marketPosition)
{
if (position.MarketPosition == MarketPosition.Flat)
{
sendCombiMessage();
}
}
private async Task sendCombiMessage()
{
Dispatcher.Invoke(new Action(async () =>
{
try
{
Arturo, sobrescribir y programar los métodos OnOrderUpdate, OnExecutionUpdate y OnPositionUpdate, requiere de conocimientos avanzados en programación. Te van a surgir dificultades que no podrás resolver si no eres un programador con cierta experiencia.
Ese error es o bien porque no estás usando una estrategia sino un indicador, o bien porque no has colocado el cuerpo del método en el lugar adecuado (asegúrate de que está dentro de las llaves de la clase de la estrategia). Saludos.
Buenas,
Quería añadir una función que mandara un mensaje a Telegram cada vez que ejecuto una orden manualmente (no desde el código) y había pensado dos maneras de hacerlo:
– Cuando Order.OrderStatus.Initialized fuera True
Pero da error (creo que por usar un private override)
– Cuando hago click en el botón de buy o sell
Pero no sé cuáles son las coordenadas
¿Cuál sería la mejor forma de hacerlo?
Muchas gracias
Hola Andrés, si quieres enviar la orden discrecionalmente podrías hacerlo capturando el evento OnClick de un botón añadido al chart donde cargues la estrategia.
Pero antes tendrías que programar dentro de la estrategia todo el código para añadir el botón al chart y el handler para el evento. En el foro de NinjaTrader hay varios ejemplos de como añadir botones y otros controles a un chart. Saludos
Respecto a mi mensaje anterior, he intentado solucionarlo con el método OnExecutionUpdate() pero me salta el eror CD0115
protected override void OnExecutionUpdate(Execution execution)
{
// Remember to check the underlying Order object for null before trying to access its properties
if (execution.Order != null && execution.Order.OrderState == OrderState.Filled)
{
sendCombiMessage();
}
}
¿Alguna idea de cómo solucionar ese error («No se encontró ningún miembro válido que invalidar»)?
¿Es necesario. auqnue la orden vaya a ser manual, crear un objeto tipo Order primero?
Muchas gracias
Te faltan parámetros de entrada en la cabecera del método. La firma correcta es :
protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
Buenas de nuevo, muchas gracias por tus respuesta; eso ya lo probé y me seguía dando el mismo error.
Probé a quitar el override del método ya que es una forma de solucionarlo pero, aunque ya no daba error, no enviaba los mensajes a Telegram.
El error que me sale es:
«(NinjaTraderNinjaScript.Indicators.Utilities.Zi8ScreenSnapShot.OnExecutionUpdate(NinjaTrader.Cbi.Execution, string, double, int, ninjatrader.Cbi.MarketPosition, string, System.DateTime): no se encontró ningún miembro adecuado que invalidar.»
Buenas, ya he encontrado el error; estba usando un indicador en vez de una estrategia. Al cambiarlo ya no me da errores al compilar, sin embargo, me sigue sin mandar las capturas.
He añadido un print justo antes del sendCombiMessage pero tampoco me lo muestra.
El método OnExecutionUpdate es propio de la clase Strategy, no se puede sobrescribir en indicadores. De ahí el error.
Prueba a utilizar el código del ejemplo sin más, con el OnBarUpdate y el sendCombiMessage. Sólo para confirmar que tienes bien configurada la conexión al Telegram y se envía el mensaje del ejemplo.
Y una vez que tengas seguro que la conexión te funciona, ya puedes implementar el código para llamar desde el OnExecutionUpdate al sendCombiMessage. Saludos
Buenas de nuevo,
Para usar la condición lógica del ejemplo, ¿dónde hay que meterlo? Lo he puesto al final del código del indicador (después de ‘private async Task sendPhoto’) pero no se envía nada.
Con el de hacer click 2 vece sí que se está enviando así que no sé si lo he puesto bien o no.
Para probarlo había abierto un Chart con el Nasdaq pero no ha llegado a enviarse nada.
Muchas gracias
Andrés, ahí no tienes que hacerlo. El método sendCombiMessage es el que se comunica con Telegram y le envía los datos que deben publicarse (texto, imágenes, etc).
Lo que tú quieres es llamar a este método cuando lo necesites. P.ej. cuando se logre un filled de una orden de entrada, o se consiga un take-profit, o salte un stop-loss, o se cumpla un trigger, etc. Ahí es donde tendrás que meter el IF para comprobar que se cumple esa condición y entonces llamar al método asíncrono sendCombiMessage. Eso hay que hacerlo dentro del OnExecutionUpdate, o del OnOrderUpdate o del OnPositionUpdate; dependerá de lo que quieras.
Buenas,
Siis, me he explicado mal, ahí lo tengo.
Ahora mismo el código es así:
protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
{
// Remember to check the underlying Order object for null before trying to access its properties
if (execution.Order != null && execution.Order.OrderState == OrderState.Filled)
Print(execution.ToString());
sendCombiMessage();
}
Siendo el print para debuggear y ver si al menos estaba entrando en la función.
Sin embargo, por mucho que ejecute una orden manualmente no llega a entrar en ningún momento.
Es normal Andrés, una estrategia sólo reconoce las órdenes que se envían desde su código. Si envías una orden manualmente desde fuera de la estrategia no va a pasar por el OnOrderUpdate, OnExecutionUpdate, etc.
Una posible solución sería añadir unos botones al chart desde el código de la estrategia, y enviar las órdenes desde dentro de la estrategia después de hacer click en los botones. Pero eso ya es otro tema y que requiere de mucho más código. Tendrías que buscar algún ejemplo en el foro de soporte de NinjaTrader de cómo añadir botones a un chart, capturar su evento OnClick, etc.
Buenos dias, me baje hace un tiempo las dll pero no las encuentro y ahora he intentado bajarmelas pero no se puede.
Ya no estan accesibles?
Gracias
Saludos
Hola Andreu, acabo de verificar que sí funciona el enlace de descarga. Es un fichero zip que a su vez contiene ficheros .dll así que algunos anti-malware pudieran rechazarlo por ese motivo. Comprueba que no tengas en tu sistema alguna protección activada que impida la descarga (tanto en el browser como en el sistema operativo). Saludos.
Hola, he probado con el Firefox y si que he podido, con el google Chrome no me ha dejado..
Gracias
Hola, sabes como se podría utilizar el código de captura pantalla que has utilizado para Telegram y poder utilizarlo en un canal de discord?
Me podéis ayudar
Gracias
Hola Andreu,
lo siento pero ese código sólo sirve para Telegram. Para Discord habría que estudiar su API (https://discord.com/developers/docs/intro) y si fuera posible, desarrollar una solución a medida.
ok, gracias
he seguido todos los pasos pero al tratar de iniciar la estrategia. he copiado todo el código para tratar de probar, me tira un error y se deshabilita
el bot funciona (he cambiado los nombres por razones obvias):
{«ok»:true,»result»:{«id»:5318501580,»is_bot»:true,»first_name»:»este es el nombre «,»username»:»nombre del bot»,»can_join_groups»:true,»can_read_all_group_messages»:false,»supports_inline_queries»:false}}
en ninja me sale el error Error on calling on statechange method. invalid format. a valid token looks like: «1234567:……………………»
alguien puede ayudarme? gracias por adelantado
Hola Manuel,
parece que el error está en la variable que aloja el token.El código tiene que ser algo así:
// Alojo el token en una constante:
private const string API_TOKEN = "746195535:Axe82h72j0IMsg0pHJnbjvH64k69amOFIXv";
// Llamo al constructor del Bot y le paso el token como parámetro:
TelegramBotClient Bot = new TelegramBotClient(API_TOKEN);
Asegúrate de que el string que se asigna al token está bien escrito.
Hola,
Me sale el mismo error que Manuel. El código es correcto. Tengo otro bot, si ingreso este token de API funciona. Si copio el otro token, no funciona y aparece el mensaje de error. Ya he creado un nuevo token. Sin éxito. ¿Me puedes ayudar? no se que mas puede ser
Hola Andreas,
si el código es correcto y no tiene bugs porque te funciona con otro bot, entonces el problema puede estar en la configuración del propio bot en Telegram. Has comprobado que el bot está autorizado como administrador en el channel correspondiente ?
Muchas gracias por la respuesta rápida. El bot está autorizado como administrador. Puedo enviar mensajes al canal a través de una URL. ¿Podría ser debido a un antiguo Telegram.Bot.dll? No tuve éxito con la compilación y descargué los archivos de su sitio. Sin embargo, al iniciar Ninjatrader recibo estos mensajes en el registro:
Vendor assembly ‘System.Runtime.CompilerServices.Unsafe’ version=’4.0.6.0′ loaded.
Vendor assembly ‘Newtonsoft.Json’ version=’11.0.0.0′ loaded.
Vendor assembly ‘Telegram.Bot’ version=’15.1.0.0′ loaded.
Vendor assembly ‘System.Threading.Tasks.Extensions’ version=’4.2.0.1′ loaded.
¿No debería Telegram.Bot.dll ser 16.2?
Hola Andreas. He vuelto a subir el .zip para descargar, con los mismos ficheros que tengo en mi instalación de NinjaTrader. Por lo tanto, la solución funciona con certeza.
Quizás tu problema tenga que ver con las referencias de los ficheros DLL. Si se copian y vuelven a pegar ficheros DLL aunque tengan el mismo nombre, es recomendable actualizar las referencias. Desde el NinjaScript Editor, clic derecho y References… Entonces borrar las referencias a los antiguos ficheros DLL y añadir las nuevas, aunque tengan la misma ruta de fichero. Saludos
Hola con que .NET Framework trabaja? o que version Telegram.bot estas usando?
Saludos,
Miguel
Hola Miguel, no sabría decirte exactamente qué versión tiene el compilado de Telegram.Bot puesto para descargar, porque lo generé desde source code y no tengo a mano los originales; parece que es la 15.1 pero en las releases del proyecto en GitHub no figura esa versión, tendría que investigarlo. El .NET Framework que aparece en la información del proyecto es la 4.5. Aunque no sean las últimas versiones funcionan perfectamente integrados con NinjaTrader 8. Saludos
¡Hola! Comentaros dos pruebas que hice, por si os sirve. No me funcionó usar un bot como administrador de más de un Chat. Lo puedes poner, pero no funcionaba luego, apareciendo el error de «chat not found». No sé si alguien tiene experiencia sobre ésto.
Lo que sí funciona es poner el API_TOKEN y el CHAT_ID como parámetros, para poder cambiarlos desde ahí si varios usan el mismo Indicador o Estrategia.
Saludos cordiales.
Gracias Juan Carlos por compartir tu experiencia, será de ayuda para quién se encuentre con el mismo problema. Saludos
¡Buenos días!
¿Hay alguna forma de hacer ésto al revés?
Me explico: ¿se puede enviar un mensaje de Telegram al Ninja y que Ninja conteste?
Tengo a Ninja en la nube con una Estrategia automática. Le programé que cada x minutos me envíe un mensaje para saber que está activo, porque algunas veces se cuelga.
Estaba pensando si se podía hacer algo en el otro sentido.
Saludos cordiales.
Hola Juan Carlos,
NinjaTrader, al estar integrada en .NET, puede aprovecharse de toda la funcionalidad incluida en WCF (Windows Communication Foundation) para la comunicación entre aplicaciones windows, de modo que puede acceder a eventos y datos originados por otras aplicaciones.
Aquí el problema radica en programar la publicación del evento/dato desde la aplicación origen, Telegram en este caso. No sé si podría hacerse mediante un bot personalizado en Telegram, pero ya sería un tema exclusivo de programación en Telegram que queda fuera de mis conocimientos, lo siento. Saludos
hola yo de nuevo He podido resolver todos mis problemas anteriores y estoy totalmente entusiasmado con las posibles aplicaciones. He incorporado su código en mi estrategia y lo estoy ejecutando en varios gráficos. El software ahora me envía una imagen de gráfico en un telegrama para ciertos eventos definidos. Todo genial. Desafortunadamente, a veces, cuando ocurre tal evento, me envía una foto en blanco. Luego hago clic en los gráficos individuales, dejo que Ninjascripts se vuelva a cargar y luego el error desaparece por un tiempo. No recibo ningún mensaje de error en NinjaTrader. ¿Alguna vez has observado algo como esto? Saludos Andrés.
Hola Andrés,
nunca me ha ocurrido y habré publicado unos cientos de capturas.
Parece un problema de renderizado y se trataría más de un tema gráfico que tuviera que ver con las librerías de directX o con la tarjeta gráfica por ejemplo.
De todos modos, abre el fichero trace.txt más reciente en la carpeta Documentos/NinjaTrader 8/trace a ver si encuentras algún mensaje de error relacionado con el renderizado.
Comprueba también que la ventana del chart no estuviera minimizada, ni el protector de pantalla activado, alguna aplicación de gráficos abierta con la que estuvieras compartiendo los recursos gráficos del equipo, etc. Saludos
Buenos días, el código funciona perfectamente en NinjaTrader 8.0.23 , pero en versiones mas nuevas el mismo código no me funciona. Lo he puesto en un Servidor (clouding) con la versión 8.0.27 y no funciona.
He probado en otro ordenador con la ultima versión de NinjaTrader y tampoco funciona, alguien tiene información si hay que actualizar alguna librería .dll ?
Hola Diego, yo lo tengo funcionando en local con NinjaTrader 8.0.27.1, con el mismo código y librerías que están compartidas aquí y funciona sin problemas. A lo mejor tu host tiene alguna limitación en las comunicaciones. Comprueba si en la ventana Output, y también en la pestaña Log, se muestra algún mensaje de error. Saludos
Gracias por la respuesta, el error estaba en el envío de histórico de mensajes cuando se activa la estrategia.
Solo he colocado esto antes del envío del mensaje
if( State == State.Historical)
return;
Gracias
¡Hola!
Con la última versión de Ninja (8.1.1.3) aparece el siguiente mensaje de error al cargarlo:
‘NinjaTrader.NinjaScript.AddOnBase’ from assembly
‘Telegram.Bot’: Unable to load one or more of the requestet
types. Retrieve the LoaderExceptions property for more
information.
Quité las referencias y volví a cargarlas. Ni eso ni mis consultas a Ninja me dieron ningún resultado.
¿Se os ocurre algo?
Saludos cordiales.
Hola Juan Carlos,
yo también tengo instalada la última versión 8.1.1.3 (en Windows 10, la 11 no la he instalado) y los mensajes a Telegram me funcionan bien. Asegúrate de tener todas las dlls necesarias en la carpeta Custom, y que son:
Newtonsoft.Json
System.Runtime.CompilerServices.Unsafe
System.Threading.Tasks.Extensions
Telegram.Bot
Con esas dlls debería funcionarte todo bien. Compila y comprueba que no hay errores.
Aparte yo tengo estas otras dlls también instaladas: (no deberían influir pero lo comparto por si acaso)
Microsoft.Extensions.Caching.Abstractions
Microsoft.Extensions.Caching.Memory
Microsoft.Extensions.DependencyInjection.Abstractions
Microsoft.Extensions.Options
Microsoft.Extensions.Primitives
Espero que lo puedas solucionar. Saludos
Pues saqué las referencias, cerré Ninja, borré las 4 dlls, bajé las que están en este sitio, las volví a copiar en la carpeta Custom, abrí Ninja, abrí el editor, puse las 4 dlls como referencias … ¡funcionó!.
No sé que hice distinto, quizás no cerré y abrí Ninja. O que se han actualizado las dlls. La cuestión que desapareció el error.
Probé alguna estrategia y manda mensajes a Telegram, así que todo bien.
yo también tengo Windows 10 y la misma versión de Ninja, así que me extrañaba. Las otras dlls no las cargué.
¡Muchas gracias!
Saludos cordiales.
Me alegro que lo hayas solucionado y muchas gracias por compartir la experiencia, seguro que le puede ayudar a alguien más. Saludos
Gran respeto al autor!
La parte principal del script funciona perfectamente.
Después de revisar la parte principal del código, decidí revisar el funcionamiento de la parte adicional, que envía una pantalla cuando se cumple una determinada condición. La compilación fue exitosa, pero cuando el indicador se instala en un gráfico configurado, el script envía solo 1-2 capturas de pantalla y se congela, mientras que el gráfico se congela en el estado de «cargando datos». Esto sugiere que el bot de Telegram está configurado correctamente y que la primera parte del script funciona bien. Aparentemente el problema está en la extensión.
En mi condición, se comprueba el volumen actual y si es mayor que el valor que puse en la variable, entonces la pantalla se envía a Telegram. Creo que el problema está en un gran flujo de datos y el método de envío de una pantalla no funciona y se congela.
He pegado su código adicional para la condición en el método
protected override void OnBarUpdate()
Aquí está mi código para la condición:
protected override void OnBarUpdate()
{
// Comprobando el valor del volumen de la barra actual
if (Volume[0] > VolumeThreshold)
{
sendCombiMessage();
}
}
Ayúdame a descubrir cuál es el problema o qué me perdí.
Tengo la sensación de que el código no tiene tiempo para enviar la pantalla y está bloqueado, pero envía algunas capturas de pantalla al inicio y luego se congela.
¿Tal vez en su código necesita configurar de alguna manera la cola de envío con una pausa, o configurar una espera antes de enviar la pantalla actual?
Gracias de nuevo por el código y gracias por la ayuda si puedes ayudar…
Hola Roon,
tendrías que hacer un debugging de tu código para conocer la causa que origina el fallo.
Pero para ir descartando posibilidades, empieza por quitar la condición lógica del OnBarUpdate para que siempre envíe el mensaje+foto con cada cierre de barra.
Deja el OnBarUpdate sin nada más, sólo la llamada a Telegram. E incluye el chequeo para RealTime.
Carga el indicador en un chart rápido de p.ej. 10-sec para no aguardar esperas. Yo lo acabo de testear y funciona perfectamente; cada 10-sec me envía el mensaje+foto a Telegram.
Comprueba si así te funciona y en ese caso el fallo estará en otro lugar del código.
Saludos
Aquí está mi código primera parte:
https://prnt.sc/pF_XGjij6ucd
Aquí está la segunda parte del código:
https://prnt.sc/He4s4ShnZ-L9
Y la última parte del código:
https://prnt.sc/bQXTm5QTjPX1
¿Puede decirme por qué un doble clic del mouse envía una pantalla, y cuando se cumple mi condición, el código envía una pantalla, a veces 2, y se congela en el «estado de carga» en el gráfico?
esto significa que el código funciona, envía tanto la pantalla como el texto, pero solo al principio, luego se congela.
¿Puedes sugerir dónde me equivoqué?
Gracias de antemano.
Si en el OnBarUpdate no chequeas que
State == State.Realtime
, cuando cargues el indicador en el chart con cada barra histórica se ejecutará el código para snapshot + envío a Telegram. Esto se ejecutará prácticamente al instante y para muchas barras por lo que se amontonarán muchas tareas pendientes que posiblemente sea la causa de que se congele la ejecución.Como te decía en la anterior respuesta, en el OnBarUpdate debes incluir un chequeo de estar en tiempo real, antes del envío a Telegram:
En un entorno productivo, el envío de mensajes a Telegram sólo debe implementarse en tiempo real. En backtesting, con barras ya pasadas y muy antiguas, no tiene sentido enviar mensajes a Telegram. Se podría hacer pero habría que incluir más programación C# avanzada, aguardar a la terminación de tareas asíncronas, etc. Y repito que no tiene sentido recibir alertas en tiempo real vía Telegram de sucesos que han pasado en barras muy antiguas.
Saludos
PD: con el MouseDown te funcionará siempre porque nunca pulsarás tan rápido y tantas veces seguidas como para colapsar el proceso.
Gracias por la ayuda !
El código que publicaste funciona bien, incluso cada 5 segundos.
Mi código ya está funcionando también. El error estaba en la condición, era necesario agregar tiempo real.
if ((State == State.Realtime) && (Volume[0] > VolumeThreshold))
Me alegro de que ya te funcione y espero que tu experiencia le pueda servir a otros lectores. Gracias por compartir.
Hola, muchas gracias por el gran trabajo, estuve usando el código con un bot viejo sin problemas. Ahora cuando lo hice con un bot nuevo, me aparece el mismo error que otros usuarios «Invalid token». Al parecer es una problema de la versión
https://stackoverflow.com/questions/70959823/invalid-format-telegram-bot-token-api-telegram-bot-package
copié de nuevo los archivos y ahora funcionó, sin cambiar nada del código, creo que tenía una versión más antigua del post.
HI
thanks for the tutorial. i have a small issue. when I try to compile the code I get the following error «The type or namespace name «Telegram» could not be found (are you missing a directive …»
line 24
line 24 is using telegram.bot
I did copy the files I downloaded from your zip file and copied them to the C:\Users\Administrator\Documents\NinjaTrader 8\bin\Custom folder
any suggestions?
thanks
Hello jonathan,
Did you follow these instructions? (You have to do it only once, before the first compilation) :
Thanks alot. i missed that part 🙁
i did click on compile and didn’t get any errors. How do I know if it works?.
i also see that the strategy i created has a different icon than the rest. see attached https://ibb.co/yRRM6Z0
thanks
Run it. If you followed the article step to step, it will work.
Yes, the custom ninjascripts have a different icon that standard ninjascripts.
Buenas tardes,
He seguido todos los pasos para programar el bot en Ninjatrader 8 (Version 8.1.1.7), pero al copiar y pegar los archivos .dll se me ha caido completamente ninjatrader hasta tal punto que me daba un error de inicio:
«Unable to retrieve type info for NinjaTrader.Ninjascript.AddOnBase from assembly Ninjatrader.Custom: unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.»
No se que cual puede ser el error… he tenido que instalar de cero el ninjatrader… Puede ser las .dll? que sean antiguas? o puede ser la version de ninjatrader?
Por favor, podrias explicarme brevemente como clonar la última versión de ese repositorio de GitHub y compilando la solución en VisualStudio? Ya que creo que he descargado los .dll antiguos…
El archivo Newtonsoft.Json.dll ya lo tenia en la carpeta de otro indicador, es estrictamente necesario copiarlo nuevamente?
Muchas gracias!
Hola Erik, no sé cuál ha podido ser el error en tu instalación: conflictos con alguna referencia (p.ej. si estaba duplicado el Newtonsoft.json.dll), si había algún fichero .cs con errores, etc …, pueden ser muchos los motivos que impidan la compilación. Pero no es necesario reinstalar. En ese caso debería haber bastado con eliminar las .dlls y los .cs que hubieras creado.
Para evitarte problemas de nuevo sigue estos pasos:
1.- Abre el editor de NinjaTrader y compila para asegurarte de que tu entorno actual es estable. Si tienes errores de compilación tendrás que solucionarlos antes de seguir.
2.- Si has compilado con éxito, cierra NinjaTrader y copia las dlls en la carpeta bin/Custom de NinjaTrader, según explico en el artículo.
3.- Abre el editor de NinjaTrader y referencia esas dlls. Si ya tuvieras la Newtonsoft.json referenciada (o cualquiera otra de las cuatro), no la referencies de nuevo aunque el fichero esté en otra ubicación.
4.- Compila. Si la compilación tiene éxito podrás continuar con el proyecto sin problema. Si la compilación no tiene éxito tendrás que averiguar por qué y será por alguna referencia o por algún código que provoque el conflicto. Para volver al estado anterior sólo tendrías que ir al editor, borrar las referencias añadidas y compilar; por último con NinjaTrader cerrado borrarías las dlls.
Las .dll que tengo publicadas en el artículo no son las últimas, pero funcionan perfectamente. Si quisieras la última versión tendrías que ir al Git del proyecto, descargarlo y compilarlo en VisualStudio. Yo no lo clono, simplemente descargo el zip y lo descomprimo para abrir la solución en VisualStudio.
Saludos
Does this work for with multiple tabs open in NT8? With another script, I had problems switching between tabs. Thus I would often receive images when the tab was currently selected, but when there was an alert from a tab which was not open/on display, it would take the wrong image.
Yes Chris, that’s how it is. Image capture only works with the chart open tab.
For the script to work, each strategy would have to be loaded in its own chart and always have the tab visible.