Como criar bots para Telegram em MQL5
Introdução
Durante a conferência F8, realizada em San Francisco em 12 de abril de 2016, o Facebook anunciou a integração da API para bots dentro do Messenger. No mesmo dia, uma grande atualização foi realizada na plataforma Bot do Telegram. A versão 2.0 foi uma surpresa agradável com a sua funcionalidade. Parece que os bots que costumavam ser populares na era ICQ estão retornando agora. Na nova fase de desenvolvimento, os bots receberam uma funcionalidade interativa, a interface aberta para programação e suporte multimídia. Basicamente, eles têm todas as condições de se tornarem insubstituíveis quando você deseja encontrar, ver ou comprar algo.
Este artigo é um manual passo-a-passo para a criação de bots para o Telegram em MQL5. Então, o que é um "bot"? Um bot (abreviação de "robot") é uma conta especial no Telegram para troca de mensagens. Bots operam no seu lado (cliente) e interagem com o servidor Telegram, usando um conjunto especial de comandos que são parte da API Bot. Antes de prosseguir com a criação de um bot, por favor faça o download do Telegram e conecte-se a ele. O registro está ligado ao número de telefone, mas você também pode procurar pelo nome de usuário (@username). Agora está na hora de inteirar-se com uma pasta de todos os bots.
Registo de um novo bot
Um bot especial chamado @BotFather é responsável pelo registro e criação dos bots. Vamos encontrá-lo através do motor de busca. Depois de adicioná-lo à lista de contatos, vamos começar a nos comunicar com ele usando o comando /start. Como resposta ele irá enviar-lhe uma lista de todos os comandos disponíveis, como mostrado na Fig. 1.
.
Fig.1. Lista dos comandos @BotFather.
Com o comando /newbot começamos o registro de um novo bot. Precisamos chegar com dois nomes. O primeiro é um nome de bot que pode ser definido na sua língua nativa. O segundo é um nome de usuário em latim do bot que termina com um prefixo "bot". Como resultado, obtém-se um símbolo - a chave de acesso via API para operar um bot. O exemplo de registo é mostrado na Fig. 2.
Fig.2. Registo de um novo bot.
Se desejar, alguns parâmetros podem ser alterados. Sugiro que mantenha as configurações no modo em linha. Caso contrário, os bots não trabalharão com ele. Eu recomendaria definir apenas as qualidades estéticas:- /setcomands - definir a lista dos comandos suportados. Esta lista aparecerá aos usuários como uma dica quando entrar o símbolo "/" na janela do chat.
- /setuserpic – configurando a imagem no perfil Sem este símbolo, o bot não é o bastante para ser apresentável.
- /SetDescription - um texto exibido como uma saudação quando um bot é adicionado ao Messenger. Normalmente, existem algumas frases para descrever a finalidade de um bot.
Assim, um novo bot é registrado. Vamos agora discutir os modos que podem ser utilizados.
Modo de operação para bots
O Telegram possui três esquemas de interação entre bots e usuários. Primeiro - conversas privadas. Cada usuário comunica com um bot de forma independente do outro, como mostra a Fig 3, ao fazer solicitações e receber respostas.
Fig.3. Bot e conversas privadas.
Os usuários enviam mensagens a um bot. Eles são armazenados no servidor não mais do que 24 horas, depois são removidos. Um bot tem tempo para solicitar e responder essas mensagens. Este é o principal modo o qual os nossos bots estarão operando.
O segundo modo envolve um grupo de chats. Neste caso, a mensagem enviada por qualquer membro de um grupo é visto por todo o grupo (Fig. 4).
Fig.4. Bot e um chat de grupo.
No que diz respeito aos bots, você pode deixá-los participar de grupos usando o comando /setjoingroups. Se um bot é adicionado a um grupo, então usando o comando /setprivacy, você pode definir a opção de receber todas as mensagens ou apenas aqueles que começam com um sinal de símbolo "/". Para ser honesto, eu somente consegui pensar num bot desta forma - estatísticas de mensagens para uma análise posterior.
O terceiro modo de operação incide sobre um canal. Canais do Telegram são contas para transmitir mensagens a um grande público que suportam um número ilimitado de assinantes. A característica importante dos canais é que os usuários não podem deixar comentários e likes no feed de notícias (conexão one-way). Apenas os administradores do canal podem criar mensagens lá (Fig. 5).
Fig.5. Bot como administrador de canal.
Bots também podem ser adicionados à lista dos administradores. Isso faz do canal uma ferramenta ideal para fornecer sinais de negociação. Mais adiante, vamos escrever um bot simples que publica os sinais do indicador padrão MACD. Um novo canal público pode ser criado através do menu "Novo Canal" do messenger. Não se esqueça de adicionar o seu bot à lista de canais dos administradores. Isso é conseguido através da janela de propriedade do canal. Todos os preparativos foram concluídas para prosseguirmos com a programação.
Manipulação de um fluxo de mensagens
Enquanto escrevia este artigo, eu tinha a meta de criar uma classe que realizaria a rotina de tratamento das mensagens e me permitia focar na lógica do bot. Como resultado, a classe CCustomBot implementa uma funcionalidade mínima para o trabalho já escrito.
A comunicação com um servidor ocorre através de solicitações POST, usando a função WebRequest. Cada comando tem a sua própria URL:
https://api.telegram.org/bot< TOKEN >/ METHOD_NAME
Onde o TOKEN é um sinal de um bot registrado; METHOD_NAME - uma lista dos métodos suportados.
Respostas do servidor chegam no formato JSON, portanto, um bom analisador JSON foi exigido. Eu apliquei um analisador nativo JSON de serialização e desserialização. Eu gostaria de agradecer Alexey (sergeev) pelo trabalho que realizou. Além disso, o painel para a exibição de alguns parâmetros também foi aplicado. A classe CComment retirado do Codebase era adequado para esta tarefa. Nomes de métodos públicos da classe foram copiados da documentação para a API Bot alcançar a universalidade. Os métodos que foram implementados a classe estão listados abaixo:
A fim de entender como usar essas funções, estamos chegando mais fundo na programação.
GetMe
Uma vez que durante cada pedido um sinal é enviado, assim acima de tudo, a função GetMe que verifica sua credibilidade é implementada. É aconselhável realizar esta verificação no início do EA e notificar o usuário em caso de falha.
int GetMe() | |
Valor retornado | código de erro |
Se for bem sucedido, o GetMe retorna 0 e você pode descobrir o nome de usuário bot através do método Name(). Este nome não é utilizado na operação. No entanto, será mostrado no painel para fins de informação. O endereço telegram.me/<botname> permite a utilização de uma web-versão do Messenger e servirá como um link para anunciar o seu bot. O EA que verifica o sinal em OnInit ficaria da seguinte forma:
//+------------------------------------------------------------------+ //| Telegram_GetMe.mq5 | //| Copyright 2014, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict #include <Telegram.mqh> input string InpToken="177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";//Token CCustomBot bot; int getme_result; //+------------------------------------------------------------------+ //| OnInit | //+------------------------------------------------------------------+ int OnInit() { //--- configuração token bot.Token(InpToken); //--- checagem token getme_result=bot.GetMe(); //--- executando o timer EventSetTimer(3); OnTimer(); //--- feito return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| OnDeinit | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); } //+------------------------------------------------------------------+ //| OnTimer | //+------------------------------------------------------------------+ void OnTimer() { //--- mostrar mensagem de erro if(getme_result!=0) { Comment("Error: ",GetErrorDescription(getme_result)); return; } //--- mostrar Nome do bot Comment("Bot name: ",bot.Name()); //---{ insert your code here } } //+------------------------------------------------------------------+
GetUpdates
A principal função GetUpdates lê as mensagens armazenados no servidor. Ele precisa ser chamado pelo timer. Um período para atualizar o timer não deve ser ajustado abaixo de 1 segundo, a fim de evitar a sobrecarga do servidor.
int GetUpdate() | |
Valor retornado | código de erro |
Vamos dar uma olhada no interior desta função. Quando chamada, é realizado a leitura e análise de todas as mensagens não lidas recebidos dos usuários. Abaixo, o exemplo de uma dessas mensagens:
{ "ok":true, "result":[ { "update_id":349778698, "message":{ "message_id":2, "from":{ "id":198289825, "first_name":"Andriy", "last_name":"Voitenko", "username":"avaticks" }, "chat":{ "id":198289825, "first_name":"Andriy", "last_name":"Voitenko", "username":"avaticks", "type":"private" }, "date":1459775817, "text":"\/start" } } ] }
Um usuário com o nome de Avaticks enviou o comando /start para o bot. O ponto é salvar essas mensagens e respondê-las no futuro. O número chat[id] é um identificador exclusivo. O mesmo usuário que se comunica com um bot através de vários dispositivos, tem diferentes identificadores do chat. Este parâmetro é adequado como uma chave única para a construção de um chat. Durante a operação, os bots vão acumular os arrays do chat e atualizar a última mensagem recebida em cada um deles. Se nós respondemos a ele, então esta mensagem será manipulada e podemos definir a flag feita a ele. O tipo de chat também é conhecido. Pode ser privado ou um grupo.
Para escrever seu próprio bot, é obrigatório herdar do CCustomBot e redeterminar a função virtual da classe ProcessMessage, que está prevista na execução da lógica de operação. Um bot completo, de acordo com a documentação do Telegram, precisa saber como responder a dois comandos: "/start" e "/help". Vamos escrever o primeiro bot que irá responder a eles.
//+------------------------------------------------------------------+ //| Telegram_GetUpdates.mq5 | //| Copyright 2014, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict #include <Telegram.mqh> //+------------------------------------------------------------------+ //| CMyBot | //+------------------------------------------------------------------+ class CMyBot: public CCustomBot { public: void ProcessMessages(void) { for(int i=0; i<m_chats.Total(); i++) { CCustomChat *chat=m_chats.GetNodeAtIndex(i); //--- se a mensagem não foi processada if(!chat.m_new_one.done) { chat.m_new_one.done=true; string text=chat.m_new_one.message_text; //--- início if(text=="/start") SendMessage(chat.m_id,"Hello, world! I am bot. \xF680"); //--- ajuda if(text=="/help") SendMessage(chat.m_id,"My commands list: \n/start-start chatting with me \n/help-get help"); } } } }; //--- input string InpToken="177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";//Token //--- CMyBot bot; int getme_result; //+------------------------------------------------------------------+ //| OnInit | //+------------------------------------------------------------------+ int OnInit() { //--- configuração token bot.Token(InpToken); //--- checagem token getme_result=bot.GetMe(); //--- executando o timer EventSetTimer(3); OnTimer(); //--- feito return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| OnDeinit | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); } //+------------------------------------------------------------------+ //| OnTimer | //+------------------------------------------------------------------+ void OnTimer() { //--- mostrar mensagem de erro if(getme_result!=0) { Comment("Error: ",GetErrorDescription(getme_result)); return; } //--- mostrar Nome do bot Comment("Bot name: ",bot.Name()); //--- mensagens de leitura bot.GetUpdates(); //--- processando mensagem bot.ProcessMessages(); } //+------------------------------------------------------------------+O resultado obtido é mostrado na Figura 6.
Fig.6. Bot com um conjunto mínimo de comandos.
Trabalhando com um teclado
Para a comunicação interativa dos usuários com os bots, os desenvolvedores trouxeram a ideia de um "teclado". Ao enviar mensagens para cada chat, um "teclado" com um conjunto pré-selecionado de chaves pode ser exibido. Ao pressionar uma tecla, um usuário envia uma mensagem com um texto indicado nele. Desta forma, a interação entre um bot e um usuário é significativamente simplificada.
A classe tem três funções para trabalhar com o teclado. A primeira função cria o objeto do teclado.
string ReplyKeyboardMarkup(const string keyboard, const bool resize, const bool one_time) | |
keyboard | string que define a localização das chaves |
resize | permissão para redimensionar o tamanho do teclado |
one_time | para mostrar o teclado apenas uma vez. O teclado desaparece após pressionar a tecla. |
Valor retornado | A string (objeto JSON) precisa ser transmitida como o parâmetro reply_markup ao enviar uma mensagem com SendMessage |
O teclado desaparece após pressionar a tecla.
string ReplyKeyboardHide() | |
Valor retornado | A string (objeto JSON) precisa ser transmitida como o parâmetro reply_markup ao enviar uma mensagem com SendMessage |
A terceira função permite enviar um pequeno painel cujo tipo indica que um bot espera uma resposta de você na forma de texto (o teclado não é exibido).
string ForceReply() | |
Valor retornado | A string (objeto JSON) precisa ser transmitida como o parâmetro reply_markup ao enviar uma mensagem com SendMessage |
Agora passamos a analisar como essas funções são usadas.
SendMessage
O teclado não pode ser exibido ou ocultado por si só. A ação é enviada com uma mensagem A função SendMessage envia as seguintes mensagens ao chat:
int SendMessage(const long chat_id, const string text, const string reply_markup=NULL) | |
chat_id | número do chat |
text | message text |
reply markup | keyboard (JSON object) |
Valor retornado | código de erro |
O teclado é opcional no presente caso. Nós podemos enviar mensagens simples de texto dos nossos programas MQL. Na minha opinião, esta função é mais interessante que a nativa SendNotification. Em primeiro lugar, podemos enviar mensagens com mais frequência (aproximadamente uma vez por segundo). Em segundo, o formato HTML é suportado. Além disso, a capacidade de enviar Emoji é um bonus.
O Тelegram suporta um número de caracteres Emoji que pode ser visto aqui. Como você pode ver, a maioria dos códigos Emoji estão na faixa de 1F300 - 1F700. Seus bitness vão além do código de dois bytes de strings aceitáveis em MQL5. Se você remover dígitos mais altos, apenas um número de dois bytes permanece, então o intervalo obtido (F300 - F700) cai na área (E000- f8ff), que na tabela de Unicode é reservado para um determinado uso. Desta forma, nada nos impede de usar 2 bits mais baixos para o envio de Emoji. A mensagem string com um Emoji clássico, com um código de U+1F642 é o seguinte:
string text="Have a nice day.\xF642";//mensagem de texto com o Emoji U+1F642
Na verdade, isso também serve para as chaves que são um texto. Nada nos impede de usar Emoji em chaves. Vamos escrever um exemplo para a exibição de três teclas com o handler de eventos.
//+------------------------------------------------------------------+ //| Telegram_SendMessage.mq5 | //| Copyright 2014, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict #include <Telegram.mqh> //+------------------------------------------------------------------+ //| CMyBot | //+------------------------------------------------------------------+ class CMyBot: public CCustomBot { private: string m_button[3]; public: //+------------------------------------------------------------------+ void CMyBot::CMyBot(void) { m_button[0]="Button #1"; m_button[1]="Button #2"; m_button[2]="Button #3"; } //+------------------------------------------------------------------+ string GetKeyboard() { return("[[\""+m_button[0]+"\"],[\""+m_button[1]+"\"],[\""+m_button[2]+"\"]]"); } //+------------------------------------------------------------------+ void ProcessMessages(void) { for(int i=0;i<m_chats.Total();i++) { CCustomChat *chat=m_chats.GetNodeAtIndex(i); if(!chat.m_new_one.done) { chat.m_new_one.done=true; string text=chat.m_new_one.message_text; //--- Comandos de início ou de ajuda if(text=="/start" || text=="/help") bot.SendMessage(chat.m_id,"Click on the buttons",bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); //--- evento on click int total=ArraySize(m_button); for(int k=0;k<total;k++) { if(text==m_button[k]) bot.SendMessage(chat.m_id,m_button[k],bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } } } } }; input string InpToken="177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";//Token CMyBot bot; int getme_result; //+------------------------------------------------------------------+ //| OnInit | //+------------------------------------------------------------------+ int OnInit() { //--- configuração token bot.Token(InpToken); //--- checagem token getme_result=bot.GetMe(); //--- executando o timer EventSetTimer(1); OnTimer(); //--- feito return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| OnDeinit | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); } //+------------------------------------------------------------------+ //| OnTimer | //+------------------------------------------------------------------+ void OnTimer() { //--- mostrar mensagem de erro if(getme_result!=0) { Comment("Error: ",GetErrorDescription(getme_result)); return; } //--- mostrar Nome do bot Comment("Bot name: ",bot.Name()); //--- mensagens de leitura bot.GetUpdates(); //--- processando mensagem bot.ProcessMessages(); } //+------------------------------------------------------------------+
Como resultado, receberemos uma mensagem com o teclado como mostrado na Fig. 7.
Fig.7. Mensagem com teclado.
//+------------------------------------------------------------------+ //| Telegram_SendMessage.mq5 | //| Copyright 2014, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict #include <Telegram.mqh> #define MUTE_TEXT "Mute" #define UNMUTE_TEXT "Unmute" #define LOCK_TEXT "Lock" #define UNLOCK_TEXT "Unlock" #define RADIO_SELECT "\xF518" #define RADIO_EMPTY "\x26AA" #define MUTE_CODE "\xF515" #define UNMUTE_CODE "\xF514" #define LOCK_CODE "\xF512" #define UNLOCK_CODE "\xF513" //+------------------------------------------------------------------+ //| CMyBot | //+------------------------------------------------------------------+ class CMyBot: public CCustomBot { private: string m_radio_button[3]; int m_radio_index; bool m_lock_state; bool m_mute_state; public: //+------------------------------------------------------------------+ void CMyBot::CMyBot(void) { m_radio_button[0]="Radio Button #1"; m_radio_button[1]="Radio Button #2"; m_radio_button[2]="Radio Button #3"; m_radio_index=0; m_lock_state=false; m_mute_state=true; } //+------------------------------------------------------------------+ string GetKeyboard() { //--- string radio_code[3]={RADIO_EMPTY,RADIO_EMPTY,RADIO_EMPTY}; if(m_radio_index>=0 && m_radio_index<=2) radio_code[m_radio_index]=RADIO_SELECT; //--- string mute_text=UNMUTE_TEXT; string mute_code=UNMUTE_CODE; if(m_mute_state) { mute_text=MUTE_TEXT; mute_code=MUTE_CODE; } //--- string lock_text=UNLOCK_TEXT; string lock_code=UNLOCK_CODE; if(m_lock_state) { lock_text=LOCK_TEXT; lock_code=LOCK_CODE; } //--- //Print(m_lock.GetKey()); return(StringFormat("[[\"%s %s\"],[\"%s %s\"],[\"%s %s\"],[\"%s %s\",\"%s %s\"]]", radio_code[0],m_radio_button[0], radio_code[1],m_radio_button[1], radio_code[2],m_radio_button[2], lock_code,lock_text, mute_code,mute_text)); } //+------------------------------------------------------------------+ void ProcessMessages(void) { for(int i=0;i<m_chats.Total();i++) { CCustomChat *chat=m_chats.GetNodeAtIndex(i); if(!chat.m_new_one.done) { chat.m_new_one.done=true; string text=chat.m_new_one.message_text; //--- início if(text=="/start" || text=="/help") { bot.SendMessage(chat.m_id,"Click on the buttons",bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } //--- Clique num botão de opção int total=ArraySize(m_radio_button); for(int k=0;k<total;k++) { if(text==RADIO_EMPTY+" "+m_radio_button[k]) { m_radio_index=k; bot.SendMessage(chat.m_id,m_radio_button[k],bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } } //--- Desbloquear if(text==LOCK_CODE+" "+LOCK_TEXT) { m_lock_state=false; bot.SendMessage(chat.m_id,UNLOCK_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } //--- Bloquear if(text==UNLOCK_CODE+" "+UNLOCK_TEXT) { m_lock_state=true; bot.SendMessage(chat.m_id,LOCK_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } //--- Ativar o som if(text==MUTE_CODE+" "+MUTE_TEXT) { m_mute_state=false; bot.SendMessage(chat.m_id,UNMUTE_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } //--- Mudo if(text==UNMUTE_CODE+" "+UNMUTE_TEXT) { m_mute_state=true; bot.SendMessage(chat.m_id,MUTE_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false)); } } } } };
Como resultado obtemos a seguinte janela (Figura 8).
Fig.8. Controles RadioButton e CheckBox
Podemos ver aqui que o Emoji usado fornece configurações com uma melhor visibilidade. Além destes controles, poderemos implementar facilmente um menu hierárquico com navegação em cada sub-menu. Tudo vai depender da funcionalidade que você vai usar e decidir implementar.
No caso de decidirmos publicar mensagens no canal, há uma segunda opção - SendMessage.
int SendMessage(const string channel_name, const string text) | |
channel_name | channel name as @name |
text | message text. Tags HTML são suportadas. |
Valor retornado | código de erro |
O resultado desta função é apresentada abaixo na Figura 9.
Trabalhando com multimídia
Bots podem trocar fotos, arquivos de áudio e vídeo, mensagens de voz, etiquetas e coordenadas de localização. Até o momento em que escrevo este artigo, foi lançado o Bot API 2.0 com uma função de troca de dados de contatos e convites. De toda a lista fornecida, apenas a opção de trocar fotos possui relevância para nós.
SendPhoto
A classe tem implementado a oportunidade de enviar fotos com duas formas de aplicação.
int SendPhoto(const long chat_id, const string local_path, string &photo_id, const string caption=NULL, const bool common_flag=false, const int timeout=10000) | |
chat_id | número do chat |
local_path | local path to the folder in <data folder>\MQL5\Files |
photo_id | identificador da foto enviada o servidor |
caption | texto da assinatura abaixo da foto |
common_flag | flag de localização do arquivo na pasta comum de todos os terminais do cliente: \Terminal\Common\Files |
timeout | tempo limite de operação em milissegundos |
Exemplo do código que envia foto:
CCustomBot bot; string token = "208375865:AAFnuOjlZ3Wsdan6PAjeqqUtBybe0Di1or8"; bot.Token(token); string photo_id; int result=bot.SendPhoto(198289825,"EURUSD1.gif",photo_id,"screenshot"); if(result==0) Print("Photo ID: ",photo_id); else Print("Error: ",GetErrorDescription(result));
Eu acredito que você terá casos onde será necessário enviar uma foto para vários usuários ou enviar a mesma foto diversas vezes. Neste caso, é mais racional fazer apenas uma vez o upload de uma foto, aplicando o identificador photo_id juntamente com a segunda opção da função SendPhoto, no reenvio de uma foto:
int SendPhoto(const long chat_id, const string photo_id, const string caption=NULL) | |
chat_id | número do chat |
photo_id | identificador da foto enviada o servidor |
caption | texto da assinatura abaixo da foto |
SendChartAction
Imagine que você lida com a resposta de um usuário e está quase pronto para fornecer-lhe um resultado. Como pode demorar alguns segundos para criar uma resposta, seria educado notificar usuário que já está sendo processada. É para isso que os eventos são usados. Por exemplo, enquanto a imagem do gráfico é formada para ser enviada a um usuário, você pode enviar o evento "envio de fotos" no mesmo período. Isto é conseguido através do SendChatAction.
int SendChatAction(const long chat_id, const ENUM_CHAT_ACTION actiona) | |
chat_id | número do chat |
ação | identificador de evento |
Exemplos de bots
O primeiro bot Telegram_Bot_EA permite a obtenção de informações sobre o saldo da conta, cotações e imagens do gráfico. O funcionamento é mostrado neste vídeo.
O segundo bot Telegram_Search_EA envia resultados de pesquisa ao site MQL5.com. Veja o vídeo abaixo e saiba como ele realmente funciona.
O terceiro bot Telegram_Signal_EA publica sinais do indicador padrão MACD no canal. Eu acho que será fácil mudar o MACD pelo seu indicador favorito e usar esse código nos seus propósitos.
//+------------------------------------------------------------------+ //| Telegram_Signal_EA_v1.mq4 | //| Copyright 2014, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| inclusão | //+------------------------------------------------------------------+ #include <Telegram.mqh> //--- Parâmetros de entrada input string InpChannelName="@forexsignalchannel";//Nome do Canal input string InpToken="177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";//Token //--- Variáveis globais CCustomBot bot; int macd_handle; datetime time_signal=0; //+------------------------------------------------------------------+ //| Função de inicialização do Expert | //+------------------------------------------------------------------+ int OnInit() { time_signal=0; //--- configuração token bot.Token(InpToken); //--- obter um handle de indicador macd_handle=iMACD(NULL,0,12,26,9,PRICE_CLOSE); if(macd_handle==INVALID_HANDLE) return(INIT_FAILED); //--- feito return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Função tick do Expert | //+------------------------------------------------------------------+ void OnTick() { //--- obtenção do tempo datetime time[1]; if(CopyTime(NULL,0,0,1,time)!=1) return; //--- Verifica o sinal em cada barra if(time_signal!=time[0]) { //--- primeiro cálculo if(time_signal==0) { time_signal=time[0]; return; } double macd[2]={0.0}; double signal[2]={0.0}; if(CopyBuffer(macd_handle,0,0,2,macd)!=2) return; if(CopyBuffer(macd_handle,1,0,2,signal)!=2) return; time_signal=time[0]; //--- Enviar sinal BUY if(macd[1]>signal[1] && macd[0]<=signal[0]) { string msg=StringFormat("Name: MACD Signal\nSymbol: %s\nTimeframe: %s\nType: Buy\nPrice: %s\nTime: %s", _Symbol, StringSubstr(EnumToString(_Period),7), DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits), TimeToString(time[0])); int res=bot.SendMessage(InpChannelName,msg); if(res!=0) Print("Error: ",GetErrorDescription(res)); } //--- Enviar sinal SELL if(macd[1]<signal[1] && macd[0]>=signal[0]) { string msg=StringFormat("Name: MACD Signal\nSymbol: %s\nTimeframe: %s\nType: Sell\nPrice: %s\nTime: %s", _Symbol, StringSubstr(EnumToString(_Period),7), DoubleToString(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits), TimeToString(time[0])); int res=bot.SendMessage(InpChannelName,msg); if(res!=0) Print("Error: ",GetErrorDescription(res)); } } } //+------------------------------------------------------------------+
Como resultado, você receberá mensagens mostradas na Fig. 9.
Fig.9. Sinais do indicador MACD.
Conclusão
Aqueles que desejam se conectar analiticamente à base Yandex.AppMetrica para seus bots, podem usar a fonte Botan . A idéia do serviço é enviar mensagens recebidas de usuários e solicitar indicadores como segmentação, acompanhamento, análise de corte, etc. Não há necessidade de sair do Messenger, porque as estatísticas serão enviadas pelo bot especial na forma de gráficos e um relatório mais detalhado estará disponível no site.
Espero que este artigo tenha inspirado você a usar o Telegram na negociação. Não era o meu objetivo cobrir todos os detalhes, porque eles já foram fornecidos na documentação para Bot API. Os códigos anexados a este artigo são adaptados à negociação em ambas as plataformas - MetaTrader 4 e MetaTrader 5.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/2355
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Perfect. Thanks.
I used to send me information about many accounts.