Как вызвать C++ DLL в MQL5: Ускорение расчетов для Квантов

Как вызвать C++ DLL в MQL5: Ускорение расчетов для Квантов MQL4 / MQL5 (MetaTrader)
Практическое руководство по интеграции внешних C++ DLL библиотек в торговые роботы MQL5 для ускорения тяжелых математических расчетов с примерами кода.
Суть: Для интеграции C++ DLL в MQL5 необходимо экспортировать функции с соглашением о вызовах __stdcall и отключенным декорированием имен (extern 'C'). В MQL5 импорт осуществляется через директиву #import 'Имя.dll', где массивы передаются по ссылке как указатели на непрерывные блоки памяти. Это позволяет использовать OpenMP, AVX-инструкции и сторонние математические библиотеки для кратного ускорения расчетов.

При разработке сложных торговых систем на платформе MetaTrader 5 разработчики часто сталкиваются с ограничениями производительности MQL5. При работе со сложными структурами данных, такими как в статье MQL5: Индикатор тепловой карты корреляции валютных пар с многомерными массивами, вычисления на стороне MQL5 могут стать узким горлышком. Перенос расчетов в C++ решает эту проблему.

Аналогично, тяжелые адаптивные алгоритмы фильтрации, подобные тем, что описаны в Реализации адаптивного скользящего среднего Кауфмана (KAMA) в MQL4, при оптимизации на миллионах тиков требуют максимальной производительности процессора, которую может дать только оптимизированный C++ код с поддержкой векторных инструкций (AVX/SSE).

Если для ваших задач машинного обучения C++ кажется избыточным, рассмотрите альтернативный вариант: Интеграция MQL5 с Python через сокеты для TensorFlow моделей. Однако для низкозадержечных (low-latency) расчетов связка MQL5 + C++ DLL остается непревзойденным стандартом.

Исходный код

Ниже представлен исходный код библиотеки на C++ (компилируется в DLL) и скрипта на MQL5, который вызывает экспортируемую функцию для параллельного вычисления математического ряда на массиве данных.

Код C++ (файл MyMathLib.cpp):

#define WIN32_LEAN_AND_MEAN
#include 
#include 
#include 

// Обязательно используем extern "C" для предотвращения декорирования (mangling) имен функций
// и __stdcall — стандартное соглашение о вызовах для MQL5
extern "C" __declspec(dllexport) void __stdcall ParallelVectorMath(
    const double* inputArray,
    double* outputArray,
    const int size,
    const double multiplier
)
{
    // Распараллеливание цикла с помощью OpenMP для ускорения расчетов
    #pragma omp parallel for
    for (int i = 0; i < size; ++i)
    {
        // Имитация тяжелых тригонометрических расчетов
        double temp = std::sin(inputArray[i]) * std::cos(inputArray[i]);
        outputArray[i] = std::exp(temp) * multiplier;
    }
}

Код MQL5 (файл CallDllExample.mq5):

#property strict
#property description "Пример вызова функций из внешней C++ DLL"

// Импортируем функцию из DLL. Файл должен лежать в MQL5\Libraries\
#import "MyMathLib.dll"
void ParallelVectorMath(const double &inputArray[], double &outputArray[], const int size, const double multiplier);
#import

void OnStart()
{
    const int arraySize = 1000000;
    double inputs[];
    double outputs[];
    
    ArrayResize(inputs, arraySize);
    ArrayResize(outputs, arraySize);
    
    // Заполнение тестовыми данными
    for(int i = 0; i < arraySize; i++)
    {
        inputs[i] = i * 0.0001;
    }
    
    Print("Начало расчета в C++ DLL...");
    uint startTicks = GetTickCount();
    
    // Вызов функции из DLL. Массивы передаются по ссылке
    ParallelVectorMath(inputs, outputs, arraySize, 2.5);
    
    uint endTicks = GetTickCount();
    PrintFormat("Расчет завершен за %d мс. Результат [0]: %f, [999999]: %f", 
                (endTicks - startTicks), outputs[0], outputs[arraySize - 1]);
}

Разбор параметров

  • const double* inputArray (в C++) / const double &inputArray[] (в MQL5): Входной массив данных. В MQL5 массивы простых типов передаются по ссылке. В C++ они принимаются как обычные указатели на первый элемент непрерывного блока памяти.
  • double* outputArray (в C++) / double &outputArray[] (в MQL5): Выходной массив, куда C++ запишет результаты вычислений. Память под него должна быть заранее выделена на стороне MQL5 с помощью функции ArrayResize.
  • const int size: Размер массивов. Необходим для безопасного итерирования внутри C++ кода, так как чистый указатель не хранит информацию о размере выделенной памяти.
  • const double multiplier: Скалярный коэффициент для демонстрации передачи обычных переменных по значению.

Как запустить

Для успешного запуска выполните следующие шаги:

1. Создайте проект динамической библиотеки (DLL) в Microsoft Visual Studio. Скопируйте код MyMathLib.cpp в проект.

2. В настройках проекта Visual Studio (Свойства -> C/C++ -> Язык) включите поддержку OpenMP (/openmp) для параллельных вычислений.

3. Скомпилируйте проект в конфигурации Release x64 (MetaTrader 5 работает исключительно в 64-битной среде).

4. Скопируйте полученный файл MyMathLib.dll из папки сборки в директорию терминала [Каталог данных]\MQL5\Libraries\.

5. В MetaEditor создайте новый скрипт, вставьте код CallDllExample.mq5 и скомпилируйте его.

6. В настройках терминала MetaTrader 5 (Сервис -> Настройки -> Советники) обязательно установите галочку 'Разрешить импорт DLL', иначе терминал заблокирует вызов внешних функций из соображений безопасности.

7. Накиньте скрипт на любой график и контролируйте вывод результатов во вкладке 'Эксперты'.

Оцените статью
FinFluct