Создание бота для Telegram на языке MQL5

Создание бота для Telegram на языке MQL5

12 апреля 2016 года на конференции F8 в Сан-Франциско компания Facebook анонсировала внедрение API для ботов в свой мессенджер. В этот же день вышло большое обновление для платформы Telegram Bot Platform. Версия 2.0 порадовала новыми функциями. Похоже, что к хорошо забытому старому, а именно ботам, которые были популярны еще в эпоху ICQ, возвращается интерес. На новом витке спирали развития ботам дают более продуманную функциональность, открытый интерфейс для программирования, мультимедийную поддержку. В общем, теперь у них есть всё, чтобы они стали незаменимы, когда вы хотите что-то найти, посмотреть или купить.

Эта статья задумана как пошаговое руководство для создания ботов для Telegram на языке MQL5. Что же такое бот? Бот (сокращение от «робот») – это специальный аккаунт в Telegram, для которого предусмотрена возможность программно обмениваться сообщениями. Бот работает на вашей (клиентской) стороне, и взаимодействует с сервером Telegram посредством специального набора команд, входящих в Bot API. Прежде чем мы приступим к созданию непосредственно самого бота, пожалуйста, установите Telegram и авторизуйтесь в этом сервисе. Регистрация привязана к номеру телефона, но помимо этого, у вас может быть ник @username, по которому вас можно будет найти через поиск. Теперь пришло время познакомиться с папкой всех ботов.

Регистрация нового бота

За регистрацию и настройку ботов отвечает специальный бот @BotFather. Найдем его через поиск. После добавления в список контактов начнем общение с ним командой /start. В ответ он пришлет список всех доступных команд, как показано на рисунке 1.

Рис.1. Список команд @BotFather.

Командой /newbot начнем регистрацию нового бота. Необходимо придумать два названия. Первое – имя (name) бота, которое можно задать на вашем родном языке. Второе - имя пользователя бота (username) на латинице, заканчивающееся на приставку “bot”. В результате мы получим токен – ключ доступа для работы с ботом через API. Пример регистрации приведен на рисунке 2.

Рис.2. Регистрация нового бота.

  • /setcommands – задание списка поддерживаемых команд. Этот список будет показываться пользователям в виде всплывающей подсказки при вводе символа "/" в окне чата.
  • /setuserpic – установка фотографии профиля. Без фото бот выглядит несолидно.
  • /setdescription – текст, который будет отображаться в качестве приветствия при добавлении бота в мессенджер. Обычно здесь в нескольких предложениях указывается назначение бота.

Итак, бот зарегистрирован. Поговорим о том, в каких режимах его можно использовать.

Режимы работы ботов

В Telegram есть три схемы взаимодействия ботов с пользователями. Первая - это приватные чаты. Каждый пользователь общается с ботом в режиме запрос-ответ независимо друг от друга, как показано на рисунке 3.

Рис.3. Бот и приватные чаты.

Пользователи присылают сообщения боту. Эти сообщения хранятся на сервере не больше суток, затем удаляются. У бота есть время, чтобы запросить эти сообщения и ответить на них. Это основной режим, в котором будут работать наши боты.

Второй режим — это групповые чаты. Здесь сообщение, отосланное любым из участников группы, видят все (рисунок 4).

Рис.4. Бот в групповом чате.

Что касается ботов, то им через команду /setjoingroups можно разрешить вступать в группы. Если бот добавлен в группу, то ему командой /setprivacy можно задать возможность либо получать все сообщения, либо только те, которые начинаются с признака команды символа “/”. Честно говоря, мне удалось придумать только одно назначение для бота в этом режиме – это сбор статистики сообщений для последующего анализа.

Третий режим – это работа на канале. Каналы в Telegram – это аккаунты для трансляции сообщений для широкой аудитории, которые поддерживают неограниченное количество подписчиков. Важной особенностью каналов является невозможность пользователей оставлять комментарии и лайки в ленте сообщений (связь только односторонняя). Создавать сообщения на ленте могут только администраторы канала (рисунок 5).

Рис.5. Бот в качестве администратора канала.

В список администраторов можно также добавлять и ботов. Таким образом это делает канал идеальным инструментом для раздачи торговых сигналов. Чуть позже мы напишем простого бота, публикующего сигналы от стандартного индикатора MACD. Создать новый публичный канал можно через меню “New Channel” мессенджера. Не забудьте внести вашего бота в список администраторов канала. Это делается через окно свойств самого канала. На этом подготовительные работы завершены, и мы можем приступить к программированию.

Обработка потока сообщений

В процессе написания этой статьи стояла задача создать класс, который возьмет на себя рутину обработки сообщений и позволит сосредоточиться на логике работы самого бота. В результате был написан класс CCustomBot, который реализует минимально необходимый функционал для работы.

Общение с сервером происходит посредством POST запросов с использованием функции WebRequst. Для каждой команды предусмотрен свой URL:

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

где, TOKEN – токен зарегистрированного бота; METHOD_NAME — список поддерживаемых методов.

Ответы от сервера приходят в JSON формате, поэтому понадобился хороший JSON парсер. Я применил нативный парсер JSON Serialization and Deserialization. Хочу поблагодарить Алексея (sergeev) за проделанную им работу. Также применена панель для отображения некоторых параметров. Класс CComment, взятый из Codebase подошел для этой задачи. Для универсальности наименования публичных методов класса были заимствованы из документации по Bot API. Список методов, которые удалось реализовать в классе, приведен ниже:

Углубимся в программирование, чтобы понять как пользоваться этими функциями.

GetMe

Так как токен отсылается в каждом запросе, прежде всего реализована функция GetMe, которая проверяет его на достоверность. Эту проверку желательно делать при старте эксперта и в случае неудачи информировать пользователя об этом.

Возвращаемое значение код ошибки

В случае успеха GetMe возвращает 0, и через метод Name() можно узнать имя (username) бота. Это имя в работе не участвует. Однако оно будет выведено на панель в качестве информации. Такой адрес как telegram.me/<botname> позволяет воспользоваться Web-версией мессенджера и будет служить ссылкой для рекламы вашего бота. Эксперт с проверкой токена в OnInit может иметь следующий вид:

GetUpdates

Главная функция GetUpdates читает массив сообщений, хранящихся на сервере. Ее необходимо будет вызывать по таймеру. Период обновления таймера нежелательно ставить меньше 1 секунды, чтобы не нагружать сервера.

Возвращаемое значение код ошибки

Рассмотрим подробнее внутреннее содержание этой функции. При её вызове происходит чтение и парсинг всех непрочитанных сообщений от пользователей. Пример одного из таких сообщений приведен ниже:

Пользователь с ником avaticks прислал боту команду /start. Задача состоит в том, чтобы сохранять такие сообщения и в дальнейшем отвечать на них. При этом уникальным идентификатором является номер чата chat[id]. Один и тот же пользователь, общающийся с ботом через разные устройства, имеет разные идентификаторы чатов. Этот параметр подходит в качестве уникального ключа для построения списка чатов. В процессе работы бот будет накапливать массив чатов и обновлять в каждом из них последнее присланное сообщение. Если мы ответили на него, то такое сообщение считается обработанным и для него устанавливается флаг done. Тип чата также известен. Он может быть либо приватным (private), либо групповым (group).

Для написания своего бота нам необходимо все лишь наследоваться от CCustomBot и переопределить в своем классе виртуальную функцию ProcessMessage, которая предусмотрена для того, чтобы реализовать в ней свою логику работы. Полноценный бот, согласно документации Telegram, должен уметь отвечать на две команды "/start" и "/help". Давайте же напишем первого бота, который будет отвечать на эти команды.

Результат его работы представлен на рисунке 6.

Рис.6. Бот с минимальным набором команд.

Работа с клавиатурой

Для интерактивного общения с пользователем для ботов придумали “клавиатуры”. При отправке сообщения для каждого чата можно отображать “клавиатуру” с заранее заданным набором клавиш. Нажимая на клавишу пользователь отправляет сообщение с текстом, указанным на ней. Таким образом заметно упрощается взаимодействие бота с пользователем.

В классе имеются три функции для работы с клавиатурой. Первая из них создает объект клавиатуры.

keyboard строка, задающая расположение клавиш resize разрешение на изменение размеров клавиатуры one_time показывать клавиатуру только один раз. После нажатия на клавишу клавиатура исчезает. Возвращаемое значение строка (JSON объект), которую необходимо передать в качестве параметра reply_markup при отправке сообщения с помощью SendMessage

Вторая функция прячет клавиатуру.

Возвращаемое значение строка (JSON объект), которую необходимо передать в качестве параметра reply_markup при отправке сообщения с помощью SendMessage

Третья функция позволяет прислать небольшую панель, вид которой указывает на то, что бот ожидает от вас ответа в текстовом виде (клавиатура не показывается).

Возвращаемое значение строка (JSON объект), которую необходимо передать в качестве параметра reply_markup при отправке сообщения с помощью SendMessage

Теперь перейдем к рассмотрению того, как пользоваться этими функциями.

SendMessage

Клавиатура не может быть отображена или спрятана сама по себе. Действие присылается вместе с сообщением. Функция SendMessage для отправки сообщений в чат имеет следующий вид:

chat_id номер чата text текст сообщения reply markup клавиатура (JSON объект) Возвращаемое значение код ошибки

В данном случае клавиатура является опциональной. Мы можем отправлять простые текстовые сообщения из наших MQL-программ. На мой взгляд, эта функция более интересна, чем нативная SendNotification. Во-первых, мы можем отправлять сообщения чаще (примерно раз в секунду). Во вторых, поддерживается формат HTML. Также немаловажным бонусом является возможность отправлять смайлики.

Тelegram поддерживает большое число смайликов (Emoji) таблицу которых можно посмотреть здесь. Как вы можете заметить, подавляющее большинство кодов смайликов находится в диапазоне (1F300 – 1F700). Их разрядность выходит за пределы двухбайтовой кодировки строк, принятой в MQL5. Если же убрать старшие разряды так, чтобы осталось двухбайтовое число, то полученный диапазон (F300 – F700) попадает в область (E000— F8FF), которая в таблице Unicode зарезервирована для частного использования. Таким образом, нам ничто не мешает для отправки смайлика использовать два младших байта. Строка сообщения с классическим улыбающимся смайликом с кодом U+1F642 может иметь следующий вид:

Это же справедливо и для клавиш, ведь они, по сути, являются текстом. Ничто не мешает нам использовать смайлики на клавишах. Давайте напишем пример для отображения трех клавиш с обработчиком событий.

В результате мы получим сообщение с клавиатурой, показанное на рисунке 7.

Рис.7. Сообщение с клавиатурой.

Теперь попробуем реализовать аналог элементов управления RadioButton и CheckBox. Например, нам нужно выбрать одну из трех опций, а также включить или выключить определенную опцию. Изменения коснутся только нашего класса, поэтому остальной код эксперта остается неизменным из предыдущего примера.

В результате мы получим окно вот такого вида (рисунок 8).

Рис.8. Элементы управления RadioButton и CheckBox

Как видите, здесь смайлики придают настройкам большую наглядность. Кроме этих элементов управления, мы также легко можем реализовывать иерархические меню с навигацией в каждое подменю. В общем, все будет зависеть от того функционала, который вы придумаете и захотите реализовать.

Стоит отметить, что в этих примерах в качестве получателя сообщения мы передаем номер чата chat_id. Мы не можем знать его заранее, чтобы отослать сообщение пользователю, пока он первым не начнет общение с ботом. Обратиться к пользователю по его номеру мобильного телефона или @username также нет возможности. Это сделано, очевидно, в целях безопасности, чтобы боты не рассылали спам. А вот публиковать сообщения на канале боты могут, обращаясь по его имени используя второй вариант SendMessage.

channel_name имя канала в виде @name text текст сообщения. Поддерживаются теги HTML. Возвращаемое значение код ошибки

Результат работы этой функции можно увидеть ниже, на рисунке 9.

Работа с мультимедиа

Боты умеют обмениваться фотографиями, аудио- и видеофайлами, а также голосовыми сообщениями, стикерами и координатами местоположения. На момент написания статьи вышла новая версия Bot API 2.0, в которую добавлена возможность обмена контактными данными и приглашениями на встречу. Из всего перечня для наших ботов актуально обмениваться только фотографиями.

SendPhoto

В классе реализована возможность отправки фото с двумя вариантами использования.

chat_id номер чата local_path локальный путь к файлу в папке <каталог данных>\MQL5\Files photo_id идентификатор загруженной на сервер фотографии caption текст подписи под фото common_flag флаг расположения файла в общей папке всех клиентских терминалов \Terminal\Common\Files timeout таймаут операции в миллисекундах

Пример кода, отправляющего фото:

Думаю, у вас будут случаи, когда возникнет необходимость отправить фото нескольким пользователям либо отправлять одну и ту же фото повторно. В этом случае будет рациональнее загрузить фото однократно, а для повторной отправки использовать идентификатор photo_id вместе со вторым вариантом функции SendPhoto:

chat_id номер чата photo_id идентификатор загруженной на сервер фотографии caption текст подписи под фото

SendChartAction

Представьте, что вы обрабатываете ответ от пользователя и уже готовы выдать ему результат. Но на создание ответа у вас уходит несколько секунд. Было бы хорошим тоном оповестить пользователя о том, что вы в процессе. Для этого существуют события. Например, пока происходит формирование скриншота графика, чтобы отправить его пользователю, вы можете отослать событие "отправка фото". Делается это с помощью SendChatAction.

chat_id номер чата action идентификатор события Все описанные выше функции были реализованы в трех демонстрационных ботах, о которых речь пойдет далее.

Примеры ботов

Первый бот Telegram_Bot_EA позволяет получить информацию о состоянии счета, котировки и скриншоты графиков. Его работа показана в этом видео.

Второй бот Telegram_Search_EA присылает результаты поиска на сайте MQL5.com. Наверняка вам будет интересно посмотреть, как это работает, в следующем видео.

Третий бот Telegram_Signal_EA публикует на канале сигналы от стандартного индикатора MACD. Думаю, вы с легкостью сможете заменить MACD на свой любимый индикатор и задействовать этот код для себя.

В результате вы будете получать сообщения, показанные на рисунке 9.

Рис.9. Сигналы индикатора MACD.

Заключение

Те кто хочет подключить аналитику на базе Yandex.AppMetrika для своего бота, могут воспользоваться ресурсом Botan. Суть сервиса в том, что вы присылаете им сообщения, получаемые от пользователей и можете запросить такие показатели как сегментация, трекинг, когортный анализ и прочее. При этом не нужно покидать экосистему мессенджера, т.к. статистика будет присылаться специальным ботом в виде графиков, а более детализированный отчет будет доступен через сайт.

Надеюсь, эта статья побудила вас использовать Telegram в трейдинге. Я не ставил своей целью останавливаться на подробностях, так как они хорошо изложены в документации по Bot API. Коды, прикрепленные к статье, адаптированы для работы на обеих платформах — и MetaTrader 4, и MetaTrader 5.

📎📎📎📎📎📎📎📎📎📎