Die Erstellung des Bots für Telegram in der Sprache MQL5

24 Juni 2016, 13:44
Andrey Voytenko
0
1 386

Einführung

Am 12. April 2016 auf der Konferenz F8 in San Francisco hat das Unternehmen Facebook die Einführung des API für Bots in seinem Messenderer angekündigt. Am selben Tag kam eine große Upgrade für den Plattform Telegram Bot Platform. Die Version 2.0 hat mit den neuen Funktionen gefreut. Es scheint, dass für die gut vergessenen alten Dinge, nämlich für Bots, wieder Interessen erwachen, die in der Ära der ICQ beliebt waren. In der neuen Entwicklungsphase wird den Bots besser gedachte Funktionalität, eine offene Interface für die Programmierung, Multimedia-Unterstützung gegeben. Im Allgemeinen haben sie jetzt alles, damit sie nicht ersetzbar sein könnten, wenn Sie etwas finden, sehen oder kaufen möchten.

Dieser Artikel wurde als eine Anleitung gedacht, um Schritt um Schritt Bots für Telegramm in MQL5 zu erstellen. Was ist denn das ein Bot? Ein Bot (Kurzform für "Roboter") – ein Sonderprofil im Telegram, für das die Möglichkeit vorgesehen ist, um die Nachrichten über Software auszutauschen. Der Bot läuft auf Ihrer (Client) Seite und interagiert mit dem Telegramm-Server über einen speziellen Satz von Befehlen, die in Bot API enthalten sind. Bevor wir anfangen, den Bot direkt zu erstellen, bitte installieren Sie Telegramm und melden Sie sich an diesem Server an. Die Anmeldung wird mit Handynummer verbunden, aber zusätzlich können Sie einen Spitznamen @username haben, dass man Sie durch den Namen finden kann. Jetzt ist es die Zeit, den Ordner aller Bots kennen zu lernen.

Die Registrierung eines neuen Bots

Für die Registrierung und Einstellung der Bots ist ein besonderer Bot @BotFather verantwortlich. Wir finden ihn über die Suche. Nach dem Hinzufügen zur Kontakt-Liste beginnen wir mit ihm zur unternehmen, durch den Befehl/start. Als Reaktion darauf wird er eine Liste aller verfügbaren Befehle senden, wie es in Abbildung 1 dargestellt ist.


Die Befehle-Liste @BotFather.

Abb.1. Die Befehle-Liste @BotFather.

Mit dem Befehl/newbot beginnen wir den neuen Bot zu registrieren. Es müssen zwei Namen ausgedacht werden. Der erste – Name (name) des Bots, den Sie in Ihrer Muttersprache eingeben können. Der zweite - der Name vom Bot-Benutzer (username) auf lateinisch, der mit dem Präfix “bot” endet. Als Ergebnis erhalten wir einen Token - der Zugriffsschlüssel für die Arbeit mit dem Bot durch die API. Das Beispiel der Registrierung wurde in Abbildung 2 aufgeführt.


Die Registrierung eines neuen Bots

Abb.2.  Die Registrierung eines neuen Bots.

Einige Einstellungen können nach freiem Ermessen geändert werden. Die Inline-Modus-Einstellungen würde ich nicht berühren. Unsere Bots werden mit ihm nicht zusammenarbeiten. Ich empfehle nur die kosmetischen Eigenschaften zu setzen:
  • /setcommands – die Referenzliste der unterstützten Befehle. Diese Liste wird Benutzer in einem Popup-Fenster angezeigt, wenn Sie das Zeichen "/" im Chat-Fenster eingeben.
  • /setuserpic – die Einstellung des Profilbildes. Ohne Foto sieht ein Bot würdelos aus.
  • /setdescription – Der Text, der als Gruß erscheinen wird, wenn Sie einen Bot zum Messenger hinzufügen werden. Normalerweise zeigt man hier in wenigen Sätzen den Zweck des Bots.

Also, so wird der Bot registriert. Lassen Sie uns jetzt darüber reden, in welchen Modi er verwendet werden kann.

Bots Modi

Das Telegramm hat drei Schema der Interaktion zwischen Bots und den Benutzern. Erstens - es sind private Chats. Jeder Benutzer kommuniziert mit dem Bot in einem Anfrage-Antwort-Modus unabhängig voneinander, wie es in Abbildung 3 dargestellt ist.


Bot und private Chats

Abb.3.  Bot und private Chats.

Benutzer senden eine Nachricht an den Bot. Diese Nachrichten bleiben auf dem Server nicht länger als ein Tag gespeichert, und dann werden sie entfernt. Der Bot hat Zeit, diese Nachrichten anzufordern und auf sie zu reagieren. Dies ist der Hauptmodus, in dem unsere Bots arbeiten.

Der zweite Modus - sind Gruppen-Chats. Hier sind die Nachrichten, die von einem der Mitglieder der Gruppe geschickt wurden, die sehen alle (Abbildung 4).

der Bot und das Gruppen-Chat

Abb.4. Der Bot im Gruppen-Chat.

Bezüglich der Bots, sie dürfen durch den Befehl / setjoingroups in der Gruppe beitreten. Wenn der Bot zu der Gruppe hinzugefügt wurde, dann kann ihm durch den Befehl/setprivacy die Option ermöglicht werden, entweder alle Nachrichten empfangen zu können oder nur diejenigen, die mit dem Symbol "/" Tag-Team beginnen. Ehrlich gesagt, es ist mir gelungen, nur einen Zweck für den Bot in diesem Modus auszudenken - eben die Statistiken der Meldungen für die spätere Analyse zu sammeln.

Der dritte Modus - das ist die Arbeit auf dem Kanal. Die Kanäle im Telegramm - es sind die Accounts für die Broadcast der Nachrichten an ein großes Publikum, die eine unbegrenzte Anzahl von Abonnenten unterstützen. Ein wichtiges Merkmal des Kanals ist die Unfähigkeit der Nutzer, Kommentare und Daumen im den Nachrichten-Kanal hinterzulassen (nur einseitige Kommunikation). Die Nachrichten im Kanal dürfen nur Administratoren des Kanals hinterlassen (siehe Abbildung 5).

Bot als Kanal-Administrator

Abb.5. Bot als Kanal-Administrator.

Zu der Liste der Administratoren kann man auch Bots hinzufügen. So macht es vom Kanal ein perfektes Werkzeug für die Verteilung der Handelssignalen. Später werden wir einen einfachen Bot schreiben, der die Signale vom standarten MACD-Indikator veröffentlichen wird. Die Erstellung eines neuen öffentlichen Kanals ist über das Menü "Neuer Kanal" des Messengers möglich. Vergessen Sie nicht, Ihren Bot zur Liste der Administratoren des Kanals hinzufügen. Dies wird durch die Kanal-Eigenschaften durchgeführt. Damit sind die Vorbereitungen abgeschlossen, und wir können mit der Programmierung beginnen.


Die Verarbeitung der Nachrichten

Während des Schreibens dieses Artikels hatte ich die Aufgabe, eine Klasse zu erstellen, welche die Verarbeitungsroutine der Nachrichten übernimmt und ermöglicht Ihnen auf die Arbeitslogik des Bots zu konzentrieren. Dadurch wurde die Klasse CCustomBot geschrieben, welche die minimale benötigte Funktionalität für die Arbeit realisiert.

Die Kommunikation mit dem Server erfolgt über POST-Anfragen mit der Funktion WebRequst. Für jeder Befehl ist seine eigene URL vorgesehen:

https://api.telegram.org/bot< TOKEN >/ METHOD_NAME

wo, TOKEN – das Token des registrierten Bots; METHOD_NAME — eine Liste der unterstützten Methoden.

Die Antworten kommen aus dem Server im JSON-Format, deswegen wurde einen guten JSON-Parser benötigt. Ich verwendete einen nativen Parser JSON Serialization and Deserialization. Ich möchte Alexei, (sergeev) für seine Arbeit bedanken. Das Feld wurde auch für die Anzeige einige Parameter verwendet. Die Klasse CComment, die aus Codebase ist, passte zu dieser Aufgabe. Für die Universalität der öffentlichen Klassenmethoden wurden die Namen aus der Dokumentation für die Bot-API gelehnt. Die Liste der Methoden, die in der Klasse realisiert wurden, ist unten dargestellt:

Wir betrachten gründlicher die Programmierung, um zu verstehen, wie man diese Funktionen verwenden soll.


GetMe

Da das Token bei jeder Anfrage gesendet wird, wurde vor allem die Funktion GetMe realisiert, die ihn auf Echtheit überprüft. Diese Überprüfung soll beim Start des EAs durchgeführt werden, und falls ein Fehler auftritt, muss der Benutzer darüber informiert werden.

int GetMe()
 Rückgabewert  Der Code des Fehlers

Falls alles erfolgreich läuft, setzt GetMe 0 zurück, und durch die Methode Name() kann man den Name des Bots (username) erfahren. Dieser Name wird in der Arbeit nicht teilnehmen. Jedoch wird es auf dem Bildschirm als Information angezeigt. Eine solche Adresse wie telegram.me/ <botname> ermöglicht Ihnen die Web-Version des Messengers zu verwenden, und es wird als Werbungslink für Ihren Bot dienen. Der Expert mit der Tokens Überprüfung in der OnInit kann folgendermaßen aussehen:

//+------------------------------------------------------------------+
//|                                               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()
  {
//--- set token
   bot.Token(InpToken);
//--- check token
   getme_result=bot.GetMe();
//--- run timer
   EventSetTimer(3);
   OnTimer();
//--- done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|   OnDeinit                                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|   OnTimer                                                        |
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- show error message end exit
   if(getme_result!=0)
     {
      Comment("Error: ",GetErrorDescription(getme_result));
      return;
     }
//--- show bot name
   Comment("Bot name: ",bot.Name());

//---{ insert your code here }
  }
//+------------------------------------------------------------------+

GetUpdates

Die Hauptfunktion GetUpdates liest eine Reihe von Nachrichten, die auf dem Server gespeichert bleiben. Die muss über Timeframe aufgerufen werden. Die Aktualisierungszeit des Timers ist besser, nicht weniger als 1 Sekunde zu setzen, um den Server nicht zu belasten.

int GetUpdate()
 Rückgabewert  Der Code des Fehlers

Betrachten wir besser den Inhalt dieser Funktion. Wenn sie aufgerufen wird, werden alle ungelesenen Nachrichten von Benutzern gelesen und analysiert. Ein Beispiel einer dieser Nachrichten wird unten dargestellt:

{ 
   "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"
         }
      }
   ]
}

Der Benutzer mit dem Nickname avaticks hat dem Bot den Befehl / start gegeben. Das Ziel ist, solche Nachrichten zu halten, und weiter auf sie zu reagieren. Dabei ist diese eindeutige Nummer des Charts chat[id] ist der Identifikator. Der gleiche Benutzer, der mit dem Bot durch verschiedene Geräte kommuniziert, hat unterschiedliche Chats-Identifikator. Diese Einstellung passt als eindeutiger Schlüssel für die Erstellung der Chat-Liste. Während der Arbeit wird der Bot eine Reihe von Chats speichern und bei jedem von ihnen die letzte gesendete Nachricht aktualisieren. Wenn wir darauf reagieren, wird diese Nachricht als bearbeitete angenommen und er wird durch die Flagge done gekennzeichnet. Der Typ des Chats ist ebenfalls bekannt. Es kann entweder ein privates Chart (privat) sein, oder ein Gruppen-Chart (Gruppe).

Um einen eigenen Bot zu schreiben, sollten wir nur CCustomBot fortsetzen und in seiner Klasse die virtuelle Funktion ProcessMessage neu zu definieren, die dafür vorgesehen ist, um Ihren eigenen Logik da zu realisieren. Ein kompletter Bot nach der Telegramms Dokumentation muss in der Lage sein, auf zwei Befehle "/start" und "/help" zu reagieren. Lassen Sie uns den ersten Bot schreiben, der auf diese Befehle reagieren wird.

//+------------------------------------------------------------------+
//|                                          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);
         //--- if the message is not processed
         if(!chat.m_new_one.done)
           {
            chat.m_new_one.done=true;
            string text=chat.m_new_one.message_text;

            //--- start
            if(text=="/start")
               SendMessage(chat.m_id,"Hello, world! I am bot. \xF680");

            //--- help
            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()
  {
//--- set token
   bot.Token(InpToken);
//--- check token
   getme_result=bot.GetMe();
//--- run timer
   EventSetTimer(3);
   OnTimer();
//--- done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|   OnDeinit                                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|   OnTimer                                                        |
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- show error message end exit
   if(getme_result!=0)
     {
      Comment("Error: ",GetErrorDescription(getme_result));
      return;
     }
//--- show bot name
   Comment("Bot name: ",bot.Name());
//--- reading messages
   bot.GetUpdates();
//--- processing messages
   bot.ProcessMessages();
  }
//+------------------------------------------------------------------+
Das Ergebnis seiner Arbeit wurde in Abb.6. dargestellt.

Der Bot mit einem minimalen Satz von Befehlen

Abb.6. Der Bot mit einem minimalen Satz von Befehlen.

Die Arbeit mit der Tastatur

Für die interaktive Kommunikation mit dem Benutzer wurde für Bots eine "Tastatur" ausgedacht. Bei der Sendung einer Nachricht kann man für jedes Chat eine “Tastatur” mit einem vorgegebenen Satz von Buchstaben anzeigen. Durch das Drücken auf die Taste sendet der Benutzer eine Nachricht mit dem Text. So wird die Interaktion zwischen einem Bot und einem Benutzer viel einfacher.

Die Klasse hat drei Funktionen für die Arbeit mit der Tastatur. Die erste erzeugt ein Tastatur-Objekt.

string ReplyKeyboardMarkup(const string keyboard,
                           const bool resize,
                           const bool one_time)
 keyboard  die Zeile, die die Anordnung der Tasten bestimmt
 resize  die Erlaubnis für die Änderung der Tasten-Größe
 one_time  zeigt die Tastatur nur einmal. Nach dem Drücken auf die Taste verschwindet die Tastatur.
 Rückgabewert Die Zeile (JSON Objekt), die als Parameter reply_markup bei der Sendung der Nachricht mit SendMessage gesendet werden muss

Die zweite Funktion verbirgt die Tastatur.

string ReplyKeyboardHide()
 Rückgabewert Die Zeile (JSON Objekt), die als Parameter reply_markup bei der Sendung der Nachricht mit SendMessage gesendet werden muss

Die dritte Funktion ermöglicht eine kleines Feld zu schicken, deren Form anzeigt, dass der Bot von Ihnen in Textform auf eine Antwort wartet (Die Tastatur wird nicht gezeigt).

string ForceReply()
 Rückgabewert Die Zeile (JSON Objekt), die als Parameter reply_markup bei der Sendung der Nachricht mit SendMessage gesendet werden muss

Wir wenden jetzt betrachten, wie man diese Funktionen verwenden soll.

SendMessage

Die Tastatur kann in nicht sich selbst angezeigt oder verborgen werden. Die Aktion wird zusammen mit der Nachricht gesendet. Die Funktion SendMessage für die Sendung der Nachricht ins Chat sieht so aus:

int SendMessage(const long chat_id,
                const string text,
                const string reply_markup=NULL)
 chat_id  Die Nummer des Chats
 text  Nachricht
 reply markup  Tastatur (JSON Objekt)
 Rückgabewert  Der Code des Fehlers

In diesem Fall ist die Tastatur optional. Wir können einfache Textnachrichten von unseren MMS-Programmen senden. Meiner Meinung nach ist diese Funktion noch interessanter als die native SendNotification. Zum einen können wir Nachrichten häufiger senden (etwa einmal pro Sekunde). Zweitens wird das HTML-Format unterstützt. Ebenfalls ist wichtig der Vorteil, Icons zu senden.

Der Telegramm unterstützt eine große Anzahl von Icons (Emoji), deren Tabelle man hier sehen kann. Wie Sie sehen können, die überwiegende Mehrheit von Icons Codes ist im Bereich von (1F300 - 1F700) zu sehen. Ihre Fähigkeit geht über die Double-Byte-Zeichenketten, die in MQL5 angenommen sind. Wenn Sie die oberen Bits entfernen, so dass nur eine Zwei-Byte-Zahl bleibt, dann wird der resultierende Bereich (F300 - F700) in den Bereich (E000- F8FF) fällt, der in der Unicode-Tabelle für den privaten Verbrauch reserviert ist. Somit hindert uns nichts, für die Sendung der Icons, die beiden Bytes zu verwenden. Die Meldungszeile mit dem klassischen Smiley-Gesicht und mit dem Code U + 1F642 kann folgendermaßen aussehen:

string text="Have a nice day.\xF642";//Der Text der Nachricht mit dem Smiley U+1F642

Dasselbe gilt für Taten, da sie im wesentlichen ein Text sind. Nichts hindert uns, die Icons auf den Tasten zu verwenden. Lassen Sie uns ein Beispiel schreiben, das drei Tasten mit Ereignisverarbeiter angezeigt.

//+------------------------------------------------------------------+
//|                                         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;

            //--- start or help commands
            if(text=="/start" || text=="/help")
               bot.SendMessage(chat.m_id,"Click on the buttons",bot.ReplyKeyboardMarkup(GetKeyboard(),false,false));

            //--- on click event
            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()
  {
//--- set token
   bot.Token(InpToken);
//--- check token
   getme_result=bot.GetMe();
//--- run timer
   EventSetTimer(1);
   OnTimer();
//--- done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|   OnDeinit                                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|   OnTimer                                                        |
//+------------------------------------------------------------------+
void OnTimer()
  {
//--- show error message end exit
   if(getme_result!=0)
     {
      Comment("Error: ",GetErrorDescription(getme_result));
      return;
     }
//--- show bot name
   Comment("Bot name: ",bot.Name());
//--- reading messages
   bot.GetUpdates();
//--- processing messages
   bot.ProcessMessages();
  }
//+------------------------------------------------------------------+

Als Ergebnis erhalten wir eine Nachricht von der Tastatur, wie in Abb. 7 gezeigt ist.

Eine Nachricht mit der Tastatur

Abb.7. Eine Nachricht mit der Tastatur.

Jetzt werden wir versuchen, eine Analoge der Steuerungselementen RadioButton- und CheckBox zu realisieren. Zum Beispiel müssen wir eine von drei Optionen wählen, sowie eine bestimmte Option aktivieren oder deaktivieren. Die Änderungen betreffen nur unsere Klasse, so dass der Rest des Experten Codes aus dem vorherigen Beispiel bleibt gleich.
//+------------------------------------------------------------------+
//|                                         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;

            //--- start
            if(text=="/start" || text=="/help")
              {
               bot.SendMessage(chat.m_id,"Click on the buttons",bot.ReplyKeyboardMarkup(GetKeyboard(),false,false));
              }

            //--- Click on a RadioButton
            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));
                 }
              }

            //--- Unlock
            if(text==LOCK_CODE+" "+LOCK_TEXT)
              {
               m_lock_state=false;
               bot.SendMessage(chat.m_id,UNLOCK_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false));
              }

            //--- Lock
            if(text==UNLOCK_CODE+" "+UNLOCK_TEXT)
              {
               m_lock_state=true;
               bot.SendMessage(chat.m_id,LOCK_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false));
              }

            //--- Unmute
            if(text==MUTE_CODE+" "+MUTE_TEXT)
              {
               m_mute_state=false;
               bot.SendMessage(chat.m_id,UNMUTE_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false));
              }

            //--- Mute
            if(text==UNMUTE_CODE+" "+UNMUTE_TEXT)
              {
               m_mute_state=true;
               bot.SendMessage(chat.m_id,MUTE_TEXT,bot.ReplyKeyboardMarkup(GetKeyboard(),false,false));
              }
           }
        }
     }
  };

Als Ergebnis erhalten wir ein Fenster in dieser Form (in Abb.8).

Abb.8. Die Steuerungselementen RadioButton und CheckBox

Wie Sie sehen können, geben hier Icons größere Sichtbarkeit an Einstellungen. Zusätzlich zu diesen Steuerungselementen können wir auch leicht ein hierarchisches Menü mit der Navigation in jedem Untermenü. In der Regel hängt alles von der Funktionalität ab, die Sie ausdenken und realisieren möchten.

Wenn wir eine Nachricht im Kanal veröffentlichen wollen, dann gibt es dafür eine zweite Variante SendMessage.

int SendMessage(const string channel_name,
                const string text)
 channel_name  Der Kanal-Name in Form von @name
 text  Der Text der Meldung. Es werden Tegs HTML unterstützt.
 Rückgabewert  Der Code des Fehlers

Das Ergebnis der Arbeit dieser Funktion wird in Abb.9. dargestellt

Die Arbeit mit Multimedia

Die Bots sind in der Lage, Bilder, Audio- und Videodateien, sowie Sprachnachrichten , Aufkleber und Standortkoordinaten auszutauschen. Im Moment des Schreibens dieses Artikels wurde eine neue Version des Bot-API 2.0 veröffentlicht, welche die Möglichkeit hat, die Kontaktinformationen und Einladungen zu einem Treffen auszutauschen. Von der gesamten Liste ist für unsere Bots aktuell, nur mit Fotografien auszutauschen.

SendPhoto

In der Klasse wurde die Möglichkeit realisiert, die Fotos mit den zwei Anwendungsfällen zu senden.

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  Die Nummer des Chats
 local_path  der lokale Weg zur Datei in Ordner <Datenverzeichnis>\MQL5\Files
 photo_id  Der Identifikator der Fotos, die im Server geladen sind
 caption  Die Textunterschrift unter dem Foto
 common_flag  Die Flagge des Speicherorts in einem öffentlichen Ordner für alle Client-Terminals \Terminal\Common\Files
 timeout  Der Timeout der Operationen in Millisekunden

Das Beispielcode, das ein Foto sendet:

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));

Ich denke, Sie werden Gelegenheiten haben, wenn Sie ein Foto an mehreren Benutzern senden müssen oder das gleiche Foto immer wieder senden. In diesem Fall ist es sinnvoll, ein Foto einmal hochzuladen und für die wiederholende Sendung den Identifikator photo_id zusammen mit der zweiten Variante der Funktion SendPhoto zu verwenden:

int SendPhoto(const long chat_id,
              const string photo_id,
              const string caption=NULL)
 chat_id  Die Nummer des Chats
 photo_id  Der Identifikator der Fotos, die im Server geladen sind
 caption  Die Textunterschrift unter dem Foto

SendChartAction

Stellen Sie sich vor, dass Sie eine Antwort vom Benutzer verarbeiten, und sind schon bereit, ihm das Ergebnis zu geben. Aber für die Erstellung der Antwort haben Sie ein paar Sekunden verbracht. Es wäre brav, den Benutzer zu warnen, dass Sie im Prozess sind. Dafür gibt es ein Ereignis. Zum Beispiel, während das Screenshot des Charts sich bildet, um dies dem Benutzer zu senden, können Sie das Ereignis senden "Foto Senden". Das wird mit SendChatAction durchgeführt.

int SendChatAction(const long chat_id,
                   const ENUM_CHAT_ACTION actiona)
 chat_id  Die Nummer des Chats
 action  Der Identifikator des Ereignis
Alle obigen Funktionen werden in drei Demonstrations Bots realisiert, die weiter erwähnt werden.

Bots Beispiele

Der erste Bot Telegram_Bot_EA ermöglicht die Information über das Konto zu bekommen, auch über Notierungen und Screenshots der Chats. Seine Arbeit ist in diesem Video gezeigt.


Der zweite Bot Telegram_Search_EA sendet die Suchergebnisse auf der Web-Seite MQL5.com. Sicherlich wird es Ihnen interessant sein, wie es im folgenden Video arbeiten wird.

Der dritte Bot Telegram_Signal_EA veröffentlicht auf dem Kanal die Signale vom standarten Indikator MACD. Ich denke, man kann leicht den MACD-Indikator um seinen Lieblingsindikator ersetzen und diesen Code für sich selbst verwenden.

//+------------------------------------------------------------------+
//|                                        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"

//+------------------------------------------------------------------+
//|   Includes                                                       |
//+------------------------------------------------------------------+
#include <Telegram.mqh>

//--- Input parameters
input string InpChannelName="@forexsignalchannel";//Channel Name
input string InpToken="177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";//Token

//--- Global variables
CCustomBot bot;
int macd_handle;
datetime time_signal=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   time_signal=0;

//--- set token
   bot.Token(InpToken);

//--- get an indicator handle
   macd_handle=iMACD(NULL,0,12,26,9,PRICE_CLOSE);
   if(macd_handle==INVALID_HANDLE)
      return(INIT_FAILED);

//--- done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//--- get time
   datetime time[1];
   if(CopyTime(NULL,0,0,1,time)!=1)
      return;

//--- check the signal on each bar
   if(time_signal!=time[0])
     {
      //--- first calc
      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];

      //--- Send signal 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));
        }

      //--- Send signal 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));
        }
     }
  }
//+------------------------------------------------------------------+

Als Ergebnis erhalten Sie die Meldung, die in Abbildung 9 gezeigt ist.

Die Signale des Indikators MACD

Abb.9. Die Signale des Indikators MACD.

Fazit

Für diejenige, welche die Analyse basierend auf Yandex.AppMetrika für seinen Bot beteiligen wollen, können die Ressource Botan verwenden. Das Wesen des Dienstes ist, dass man an ihnen von Benutzern empfangen Nachrichten senden kann, und solche Indikatoren wie Segmentierung, Tracking, Kohortenanalyse und vieles mehr verlangen. Es gibt keine Notwendigkeit, das Messenger-Ökosystem zu verlassen, da die Statistik durch einen speziellen Bot in Form von Charts gesendet wird und ein mehr detaillierter Bericht wird in der Website erreichbar.

Ich hoffe, dieser Artikel wird Sie ermutigen, den Telegramm im Handeln zu verwenden. Ich hatte kein Ziel, ins Detail zu gehen, weil sie schon gut in der API-Dokumentation für den Bot beschrieben sind. Die Codes, die zum Artikel hinzugefügt wurden, wurden auf beiden Plattformen - und MetaTrader 4 und MetaTrader 5 angepasst.

Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/2355

Beigefügte Dateien |
telegram.zip (31.56 KB)
Signalrechner Signalrechner

Der Signalrechner funktioniert direkt aus dem Terminal MetaTrader 5, und das ist sein größter Vorteil, denn das Terminal führt eine Vorwahl durch und sortiert Signale. Auf diese Weise sieht der Benutzer im MetaTrader 5 Terminal nur die Signale, die maximal auf sein Trading-Konto angepasst sind.

Rezepte MQL5 - Programmierung der gleitenden Kanäle Rezepte MQL5 - Programmierung der gleitenden Kanäle

In diesem Artikel wird eine Weise angeboten, das System der gleich entfernten Kanäle zu programmieren. Es werden einige Nuancen des Zeichens der Kanäle betrachtet. Es wird eine Typisierung der Kanäle durchgeführt, eine Weise des universellen Typs von Gleitkanälen angeboten. Es werden bei der Realisierung des Codes die OOP-Werkzeuge verwendet.

Reguläre Ausdrücke für Trader Reguläre Ausdrücke für Trader

Reguläre Ausdrücke (eng. regular expressions) stellen eine spezielle Sprache für die Textverarbeitung nach einer vorbestimmten Regel dar, die auch als Muster bezeichnet wird oder die Maske eines regulären Ausdrucks. In diesem Artikel zeigen wir Ihnen, wie Sie den Handelsbericht mit Hilfe von der Bibliothek RegularExpressions für MQL5 verarbeiten können, auch werden die Ergebnisse der Optimierung mit ihrer Anwendung demonstriert.

Das MQL5-Kochbuch: Implementierung Ihrer eigenen Markttiefe Das MQL5-Kochbuch: Implementierung Ihrer eigenen Markttiefe

Dieser Beitrag führt vor, wie die Markttiefe (Depth of Market, DOM) programmatisch verwendet wird, und beschreibt das Arbeitsprinzip der Klasse CMarketBook, durch die die Standardbibliothek von MQL5-Klassen erweitert werden kann und die praktische Methoden für die Verwendung der DOM liefert.