Отправка торговых сигналов в Telegram из индикаторов MT4/MT5 без сторонних DLL: пошаговая инструкция

Введение

Одной из распространенных задач при автоматизации трейдинга является отправка торговых сигналов или уведомлений в Telegram. Однако многие программисты сталкиваются с серьезным ограничением: в индикаторах MetaTrader 4 и 5 запрещено использовать функцию WebRequest(), без которой невозможно напрямую взаимодействовать с внешними API, включая Telegram Bot API.

В этой статье я расскажу об элегантном решении этой проблемы без использования сторонних DLL, основанном на механизме кастомных событий терминала MetaTrader.

Проблема и ограничения

При разработке индикаторов для MT4/MT5 разработчики сталкиваются с рядом ограничений безопасности:

  1. В индикаторах запрещено использовать функцию WebRequest()
  2. Нельзя напрямую подключать внешние DLL для обхода этого ограничения (это небезопасно и есть ограничения)
  3. Индикаторы и DLL работают в одном потоке , поэтому введены ограничения на DLL, чтобы не завис терминал.

Решение: Механизм кастомных событий

MetaTrader предоставляет механизм пользовательских событий CHARTEVENT_CUSTOM, который позволяет обмениваться данными между разными элементами платформы — индикаторами, советниками и скриптами.

Суть решения:

  1. Индикатор генерирует кастомное событие с необходимыми данными
  2. Советник (эксперт), установленный на любом графике, перехватывает это событие
  3. Советник использует WebRequest для отправки сообщения в Telegram Bot API

Шаг 1: Реализация отправки событий из индикатора

Для отправки сигналов из индикатора в советник нам понадобится универсальная функция SendEvent():

//+------------------------------------------------------------------+
//| Отправка кастомного события всем открытым графикам               |
//+------------------------------------------------------------------+
#define MSG_TELEGRAM_TEXT CHARTEVENT_CUSTOM+2

void SendEvent(ushort broadcastEventID, long lparam, double dparam, string sparam)
{
   // CHARTEVENT_CUSTOM начинается с 1000, поэтому вычитаем это значение
   // Максимальный ID события может быть 65534
   ushort eventID = (ushort)(broadcastEventID - CHARTEVENT_CUSTOM); 

   long currChart = ChartFirst();
   int i = 0;
   const int CHARTS_MAX = 100; // Максимальное количество графиков для обработки

   while(i < CHARTS_MAX)
   {
      EventChartCustom(currChart, eventID, lparam, dparam, sparam);
      currChart = ChartNext(currChart);
      if(currChart == 0)
         break;
      i++;
   }
}

Эта функция отправляет кастомное событие всем открытым в терминале графикам. Теперь в коде индикатора при необходимости отправить сообщение в Telegram достаточно вызвать:

// Пример отправки сигнала в Telegram из индикатора
SendEvent(MSG_TELEGRAM_TEXT, ChatID, 0.0, "Обнаружен сигнал на покупку по паре EURUSD H1");

Шаг 2: Создание советника-посредника TelegramBridge

Советник будет принимать кастомные события и отправлять сообщения в Telegram. Полный код советника:

//+------------------------------------------------------------------+
//|                                               TelegramBridge.mq5 |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2007 - 2025, Trading Shop"
#property link      "https://trading-shop.ru"
#property version   "1.000"
#property description "Посредник для отправки сообщений из индикаторов в Telegram"

input string InpToken   =  ""; // Token Bot, format: XXXXXXXXXX:HHHHHHHHHHHHHHH
input long   InpUserID  =  0;  // User ID по умолчанию

// Определяем идентификатор события для Telegram сообщений
#define MSG_TELEGRAM_TEXT CHARTEVENT_CUSTOM+2

#include <TelegramAPI\\Telegram.mqh>

CTelegramAPI bot;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Проверяем наличие токена
   if(InpToken == "" || StringLen(InpToken) < 10)
   {
      Alert("TelegramBridge: Необходимо указать токен бота в настройках!");
      return(INIT_FAILED);
   }

   // Проверяем наличие ID пользователя
   if(InpUserID == 0)
   {
      Alert("TelegramBridge: Необходимо указать User ID в настройках!");
      return(INIT_FAILED);
   }

   // Инициализация Telegram бота
   bot.OnInit(InpToken);

   Print("TelegramBridge успешно инициализирован. Готов принимать сообщения.");

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Очистка ресурсов при необходимости
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // В данном случае не требуется обработка тиков
}
//+------------------------------------------------------------------+
//| Обработчик событий                                               |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // идентификатор события
                  const long& lparam,   // параметр события типа long
                  const double& dparam, // параметр события типа double
                  const string& sparam) // параметр события типа string
{
   // Проверяем, является ли событие сообщением для Telegram
   if(id == MSG_TELEGRAM_TEXT)
   {
      // Если в lparam указан конкретный ChatID (не 0), используем его
      // Иначе используем ID по умолчанию из настроек
      long chatID = (lparam > 0) ? lparam : InpUserID;

      // Отправляем сообщение в Telegram
      int result = bot.sendMessage(chatID, sparam);

      if(result == 0) {
         Print("Сообщение успешно отправлено в Telegram: ", sparam);
      } else {
         Print("Ошибка отправки в Telegram (код ", result, "): ", GetLastError());
      }
   }
}
//+------------------------------------------------------------------+
Отправка торговых сигналов в Telegram из индикаторов MT4/MT5 без сторонних DLL: пошаговая инструкция

Шаг 3: Библиотека Telegram API

Для взаимодействия с Telegram Bot API используется библиотека TelegramAPI.mqh, код которой приведен в начале статьи. Эта библиотека реализует все необходимые функции для отправки сообщений и медиафайлов в Telegram.

Шаг 4: Настройка Telegram бота

  1. Создайте бота в Telegram через BotFather
  2. Скопируйте токен бота (формата XXXXXXXXX:YYYYYYYYYYYYYYYYYYYYY)
  3. Узнайте ваш User ID:
  • В Telegram найдите и запустите бота @userinfobot
  • Он автоматически сообщит ваш ID
  • Альтернативный варианты: Web telegram для каналов и групп и MacOS, где в настройках включается отображать ID.
  1. Установите советник на любой график в терминале MT4/MT5
  2. В настройках советника укажите токен бота и ваш User ID

Преимущества данного подхода

  1. Безопасность: Не используются сторонние DLL, что исключает риски безопасности
  2. Простота интеграции: Для отправки сообщения из индикатора достаточно вызвать одну функцию
  3. Гибкость: Можно настроить несколько советников для разных целей или чатов, код открытый.
  4. Надежность: Механизм кастомных событий является встроенным в MetaTrader и работает стабильно
  5. Универсальность: Решение работает как в MT4, так и в MT5 без изменения кода.

Заключение

Предложенный подход позволяет обойти ограничения платформы MetaTrader на использование WebRequest в индикаторах, предоставляя разработчикам возможность отправлять торговые сигналы и уведомления в Telegram без компромиссов с безопасностью.

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

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

Готовое решение и исходный код для МТ4 и МТ5

Есть вопрос?

У вас есть вопрос, предложение или вы хотите высказаться? Напишите его в Комментариях.

Добавить комментарий