Использование динамических библиотек (DLL) в индикаторах MQ4

В языке MQL4/5 поддерживается вызов функций из динамических библиотек (DLL). Это позволяет реализовать пользовательский индикатор MQ4 или MQ5 частично или полностью на любом другом языке программирования, в котором возможно создание DLL (например, на языке C/C++). Кроме ощутимого увеличения быстродействия, такое решение позволяет защитить исходный код индикатора, использовать все возможности операционной системы и, при необходимости, специализированные библиотеки; а ещё появляется возможность привязать индикатор к “железу” (для предотвращения несанкционированного копирования и использования на других компьютерах).

Приведём пример классического индикатора (простая скользящая средняя), реализованного на языке C++.

Файл MySMA.cpp:

#define WIN32_LEAN_AND_MEAN  // Не включать редко используемые функции, макросы и типы Windows.

// #include "stdafx.h" // Если компилятор MSVC и в свойствах проекта включено использование
// предкомпилированных заголовочных файлов
// (пункт меню Проект | Свойства, группа "C/C++", подгруппа "Предварительно откомпилированные заголовки",
// параметр "Предварительно откомпилированный заголовок",
// в раскрывающемся списке выбрать "Не использовать предварительно скомпилированные заголовки").

#include <windows.h> // Нужен для MinGW; при использовании MSVC можно не включать.
// #include <stdlib.h> // В данном проекте не требуется.
// #include <stdio.h>

#ifdef __cplusplus  // Если компилятор C++, а не C
extern "C" {        // (чтобы отключить декорирование имён функций).
#endif

#define MT4_EXPFUNC __declspec(dllexport)

#pragma pack(push,1) // Отключили выравнивание полей структур.
struct RateInfo {    // Структура для хранения котировок.
   __int64           ctm;       // Дата/время.
   double            open;      // Цена открытия.
   double            high;      // Максимум.
   double            low;       // Минимум.
   double            close;     // Цена закрытия.
   unsigned __int64  vol_tick;  // Тиковый объём.
   int               spread;    // Спред.
   unsigned __int64  vol_real;  // Реальный объём.
};
// В старых версиях Metatrader 4 определяли другую структуру:
/* struct RateInfo {
     unsigned int ctm;
     double open;
     double low;
     double high;
     double close;
     double vol; }; */

// Если нужны строковые переменные:
// struct MqlStr  { int len; char * string; };
#pragma pack(pop)  // Вернули предыдущую настройку выравнивания.

// Экспортируемая функция для заполнения индикаторного буфера значениями простой скользящей средней:
// rates - котировки, полученные из терминала MT4;
// m - число баров в массиве rates;
// n - период скользящей средней;
// buffer - указатель на индикаторный буфер терминала.
MT4_EXPFUNC void __stdcall Calculate(const RateInfo* rates, unsigned int m, unsigned int n, double* buffer){
   for(unsigned int i = 0; i <= m-n; i++) {
      double sum = 0.0;
      for( unsigned int k = 0; k < n ; k++ ) {
         sum += rates[m-i-1-k].close;
      }
      buffer[m-i-1] = sum / n ;  // Значение скользящей средней.
   }
   // Можно опустить, т.к. мы запретим в индикаторе показ первых баров:
   // for(unsigned int i = m-n; i < m; i++)
   //   buffer[m-i-1] = -1; // -1 = EMPTY  - очистили значения индикаторного буфера для первых баров.
}

#ifdef __cplusplus
}
#endif

Важно помнить, что в MQL4/5 самый правый бар на графике имеет номер 0, но в программе на языке C/C++ нулевой индекс соответствует самому левому бару, поэтому мы “переворачиваем” нумерацию.

Проект можно копилировать в Microsoft Visual Studio или с помощью любого другого компилятора, например, MinGW.

Сам индикатор на языке MQL4 (файл MySMA.mq4):

//+------------------------------------------------------------------+
//|                                                       MySMA.mq4  |
//|                                Copyright 2015, ProfiTraders.com  |
//|                                          http://profitraders.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, ProfiTraders.com"
#property link      "http://profitraders.com"
#property version   "1.00"
#property strict
#property indicator_chart_window // Индикатор в отдельном окне.
#property  indicator_buffers 1
#property  indicator_color1  Red
#property  indicator_width1  2

#import "MySMA.dll"
void Calculate(const MqlRates& rates[], unsigned int m,
               unsigned int n, double& buffer[]);
// для старых версий MT4: double rates[][6]
#import

unsigned int nDrawBeginBar; // C какого бара начинается показ индикатора
                            // (на первых барах он не определён).

double buffer[];   // Индикаторный буфер.
extern int n = 10; // Период.

int OnInit() { // Инициализация индикатора.
   SetIndexBuffer(0, buffer);
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID);
   IndicatorShortName("MySMA("+IntegerToString(n)+")" );
   SetIndexLabel(0, "MySMA");
   nDrawBeginBar = n; // Начинать показ индикатора с n-го бара.
   SetIndexDrawBegin(0, nDrawBeginBar);
   return(INIT_SUCCEEDED);
}

void start(){        // Функция, вызываемая на каждом тике.
   MqlRates rates[]; // Для старых версий MT4: double rates[][6].
   // Получим указатель на массив котировок:
   int m = ArrayCopyRates( rates, Symbol(), 0 );
   // Если бы мы не очистили первые бары в самой Calculate:
   // for( int i = m-1; i >= 0; i-- ) { buffer[i] = EMPTY; }
   Calculate( rates, m, n, buffer ); // Вызов функции из DLL.
}

Приведённая здесь реализация имеет очевидный недостаток: на каждом тике пересчитывается всё содержимое индикаторного буфера. Чтобы оптимизировать вычисления, надо учесть, какие бары уже были рассчитаны ранее, во время предыдущих вызовов функции start(). Вы узнаете, как это реализовать, во время обучения на нашем курсе “Видеокурс: Разработка торговых систем на языке MQL4/5 и автоматизированная торговля в Metatrader4/5”.



Комментарии

Комментариев пока нет.

* Обязательные поля
(Не публикуется)
 
Жирный Курсив Подчеркнутый Перечеркнутый Степень Индекс Код PHP Код Кавычки Вставить линию Вставить маркированный список Вставить нумерованный список Вставить ссылку Вставить e-mail Вставить изображение Вставить видео
 
Улыбка Печаль Удивление Смех Злость Язык Возмущение Ухмылка Подмигнуть Испуг Круто Скука Смущение Несерьёзно Шокирован
 
1000
Captcha
Refresh
 
Введите код:
 
Запомнить информацию введенную в поля формы.