Исходный код
Передача данных между MetaTrader 5 (MT5) и Python является ключевой задачей для многих количественных разработчиков и трейдеров, желающих использовать мощь Python для анализа, машинного обучения или интеграции с другими системами. ZeroMQ (ZMQ) — это высокопроизводительная асинхронная библиотека обмена сообщениями, которая идеально подходит для этой цели, обеспечивая быструю и надежную передачу данных.
В этом руководстве мы рассмотрим, как настроить MQL5-скрипт в MT5 для отправки данных (например, текущих котировок) через ZMQ-сокет типа Publisher (PUB) и как создать Python-скрипт для приема этих данных с помощью ZMQ-сокета типа Subscriber (SUB).
MQL5 (MetaTrader 5) — Publisher
Для работы с ZMQ в MQL5 вам потребуется библиотека Zmq.mqh и соответствующая libzmq.dll. Эти файлы обычно можно найти в репозиториях сообщества MQL5 или на GitHub. Убедитесь, что Zmq.mqh находится в папке MQL5/Include, а libzmq.dll — в MQL5/Libraries. Также необходимо разрешить импорт DLL в настройках эксперта/скрипта MT5.
Этот MQL5-скрипт будет отправлять текущую цену Bid и Ask для символа, на котором он запущен, каждые 500 миллисекунд.
#property copyright "Finfluct"
#property version "1.00"
#include // Путь к библиотеке Zmq.mqh
//--- Параметры ZMQ
#define ZMQ_PORT 5555 // Порт для ZMQ сокета
CZmqContext zmq_context;
CZmqSocket zmq_publisher;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Инициализация ZMQ контекста
if (!zmq_context.Create())
{
Print("Ошибка: Не удалось создать ZMQ контекст");
return INIT_FAILED;
}
//--- Создание ZMQ сокета типа Publisher
if (!zmq_publisher.Create(zmq_context, ZMQ_PUB))
{
Print("Ошибка: Не удалось создать ZMQ Publisher сокет");
zmq_context.Destroy();
return INIT_FAILED;
}
//--- Привязка сокета к порту
string address = "tcp://*" + IntegerToString(ZMQ_PORT);
if (!zmq_publisher.Bind(address))
{
Print("Ошибка: Не удалось привязать ZMQ Publisher сокет к ", address);
zmq_publisher.Destroy();
zmq_context.Destroy();
return INIT_FAILED;
}
Print("ZMQ Publisher успешно запущен на ", address);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Закрытие сокета и уничтожение контекста
zmq_publisher.Destroy();
zmq_context.Destroy();
Print("ZMQ Publisher остановлен.");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
static datetime last_send_time = 0;
datetime current_time = TimeCurrent();
// Отправляем данные не чаще, чем раз в 500 мс
if (current_time - last_send_time < 0.5) // Проверка на интервал в секундах
{
return;
}
last_send_time = current_time;
//--- Получение текущих цен
MqlTick tick;
if (!SymbolInfoTick(_Symbol, tick))
{
Print("Ошибка: Не удалось получить тиковые данные для ", _Symbol);
return;
}
//--- Формирование сообщения (например, в формате JSON)
string message = StringFormat("{\"symbol\":\"%s\", \"bid\":%.5f, \"ask\":%.5f, \"time\":%d}",
_Symbol, tick.bid, tick.ask, tick.time);
//--- Отправка сообщения
if (zmq_publisher.Send(message))
{
// Print("Отправлено: ", message); // Раскомментируйте для отладки
}
else
{
Print("Ошибка: Не удалось отправить сообщение через ZMQ");
}
}
Python - Subscriber
Python-скрипт будет подключаться к ZMQ-сокету, запущенному в MT5, и выводить полученные данные в консоль. Убедитесь, что у вас установлен пакет pyzmq (pip install pyzmq).
import zmq
import json
import datetime
#--- Параметры ZMQ
ZMQ_PORT = 5555
ZMQ_ADDRESS = f"tcp://localhost:{ZMQ_PORT}"
def main():
context = zmq.Context()
print(f"Подключение к ZMQ Publisher на {ZMQ_ADDRESS}...")
# Создание ZMQ сокета типа Subscriber
socket = context.socket(zmq.SUB)
socket.connect(ZMQ_ADDRESS)
# Подписка на все сообщения (пустая строка означает подписку на все топики)
socket.setsockopt_string(zmq.SUBSCRIBE, "")
print("Успешно подключено. Ожидание данных...")
try:
while True:
# Получение сообщения
message_raw = socket.recv()
message_str = message_raw.decode('utf-8')
try:
# Попытка распарсить как JSON
data = json.loads(message_str)
timestamp = datetime.datetime.fromtimestamp(data['time'])
print(f"[{timestamp}] {data['symbol']} Bid: {data['bid']:.5f}, Ask: {data['ask']:.5f}")
except json.JSONDecodeError:
print(f"Получено не-JSON сообщение: {message_str}")
except KeyError as e:
print(f"Получено JSON, но отсутствует ключ {e}: {message_str}")
except KeyboardInterrupt:
print("\nПолучено прерывание от пользователя. Закрытие сокета...")
finally:
socket.close()
context.term()
print("ZMQ сокет и контекст закрыты.")
if __name__ == "__main__":
main()
Разбор параметров
ZMQ_PORT: Определяет номер порта, который будет использоваться для ZMQ-соединения. Этот порт должен быть одинаковым как в MQL5-скрипте (Publisher), так и в Python-скрипте (Subscriber). Убедитесь, что порт не занят другими приложениями.#include: Директива препроцессора в MQL5, указывающая на путь к заголовочному файлу библиотеки ZeroMQ для MQL5. Путь может отличаться в зависимости от того, куда вы поместили файлZmq.mqh.zmq_context.Create()/zmq.Context(): Инициализирует контекст ZeroMQ. Контекст управляет всеми сокетами и потоками в ZMQ.zmq_publisher.Create(zmq_context, ZMQ_PUB)/context.socket(zmq.SUB): Создает ZMQ-сокет. В MQL5 это сокет типаZMQ_PUB(Publisher), который отправляет сообщения. В Python это сокет типаzmq.SUB(Subscriber), который принимает сообщения.zmq_publisher.Bind("tcp://*:5555"): В MQL5 (Publisher) привязывает сокет к указанному адресу и порту.*означает, что сокет будет слушать входящие соединения на всех доступных сетевых интерфейсах.socket.connect("tcp://localhost:5555"): В Python (Subscriber) подключает сокет к указанному адресу и порту, где ожидает Publisher.localhostуказывает на текущую машину.socket.setsockopt_string(zmq.SUBSCRIBE, ""): В Python (Subscriber) подписывает сокет на получение сообщений. Пустая строка""означает подписку на все топики. Если Publisher отправляет сообщения с топиками (например,zmq_publisher.Send("EURUSD", message)), Subscriber должен подписаться на конкретный топик.zmq_publisher.Send(message)/socket.recv(): Методы для отправки и получения сообщений. В MQL5 отправляется строка. В Pythonrecv()возвращает байты, которые затем декодируются в строку (decode('utf-8')).StringFormat()/json.loads(): В MQL5 используется для форматирования данных в строку (в данном случае, JSON-строку). В Pythonjson.loads()используется для парсинга полученной JSON-строки в Python-словарь.
Как запустить
Выполните следующие шаги для запуска и тестирования передачи данных:
1. Подготовка MQL5 окружения
- Установка ZMQ библиотеки для MQL5: Скачайте
Zmq.mqhиlibzmq.dll. ПоместитеZmq.mqhв папкуMQL5/Include/Zmq(или простоMQL5/Include, если вы измените путь в#include), аlibzmq.dll— вMQL5/Libraries. - Создание MQL5-скрипта: Откройте MetaEditor (F4 в MT5), создайте новый Expert Advisor (Файл -> Новый -> Expert Advisor (шаблон)). Скопируйте и вставьте MQL5 код, приведенный выше. Сохраните его (например, как
ZmqPublisher.mq5). - Компиляция: Нажмите F7 для компиляции скрипта. Убедитесь, что нет ошибок.
- Разрешение импорта DLL: В MetaTrader 5 откройте меню
Сервис -> Настройки -> Советникии установите флажокРазрешить импорт DLL. - Запуск MQL5-скрипта: Перетащите скомпилированный Expert Advisor
ZmqPublisherиз окнаНавигаторна график любого торгового инструмента (например, EURUSD). Убедитесь, что в правом верхнем углу графика появился смайлик, а в журнале экспертов (вкладкаЭкспертыв окнеТерминал) отображается сообщениеZMQ Publisher успешно запущен на tcp://*:5555.
2. Подготовка Python окружения
- Установка
pyzmq: Откройте терминал или командную строку и выполните команду:pip install pyzmq. - Создание Python-скрипта: Создайте новый файл (например,
zmq_subscriber.py) и скопируйте в него Python код, приведенный выше.
3. Запуск и проверка
- Запустите Python-скрипт: В терминале перейдите в директорию, где вы сохранили
zmq_subscriber.py, и выполните:python zmq_subscriber.py. - Проверка данных: Вы должны увидеть, как в консоли Python начинают появляться сообщения с текущими котировками, отправленными из MT5.
Дополнительные возможности и ссылки
Используя ZMQ, вы можете передавать не только котировки, но и информацию о сделках, позициях, а также отправлять команды из Python в MT5 (используя другие типы сокетов, например, REQ/REP). Это открывает широкие возможности для автоматизации и создания сложных торговых систем.
Например, вы можете использовать полученные данные для анализа проскальзываний, как в статье MQL5: Скрипт для сбора статистики проскальзываний Market ордеров, или для принятия решений о массовом изменении параметров позиций, что может быть реализовано с помощью скриптов, подобных описанным в MQL5: Массовое изменение Stop Loss и Take Profit по Magic Number или MQL5: Скрипт для массового закрытия убыточных позиций по Magic Number.
ZeroMQ — это мощный инструмент для построения распределенных систем, и его интеграция с MetaTrader 5 значительно расширяет возможности для разработки торговых стратегий и инструментов.




