Использование вычислительных возможностей MATLAB 2018 в MetaTrader 5

Roman Korotchenko | 4 марта, 2019

Введение

Настоящая статья является развитием статьи А. Емельянова "Взаимодействие MetaTrader 5 И MATLAB", предоставляя информацию о решении подобной задачи для современных 64-х разрядных версий всех платформ, применяемых пользователями. За истекший период в пакете MATLAB существенно модернизирован  сам метод создания dll-библиотек совместного использования. Поэтому рассмотренный в исходной статье метод требует модификации. Это произошло потому, что теперь вместо MATLAB Compiler нужно применять MATLAB Compiler SDK или MATLAB Coder. Кроме того, изменилась практика работы с динамической памятью в MATLAB, что предполагает определенные корректировки программного кода, получающего доступ к библиотеке, написанной на языке MATLAB. 

Из названия статьи становится ясным, что данная работа направлена на то, чтобы облегчить разработчикам задачу сопряжения вычислительных возможностей MATLAB с программами, написанными на MQL5. Для этого в работе в качестве примера проводится создание прогностического индикатора на основе модели Seasonal Autoregression Integrated Moving Average (SARIMA) для временного ряда цен, где на MATLAB возложена задача подбора адекватной модели и экстраполирование данных. 

Чтобы продемонстрировать подробности подключения вычислительного потенциала среды MATLAB 2018 к MQL5 в данной статье рассматривается конкретно MATLAB Compiler SDK, а также создание библиотеки-адаптера на Visual C++ для сопряжения MATLAB-библиотеки к MQL5. Это позволяет получить краткое руководство для создания программ, чтобы избегать типичных ошибок, с которыми пришлось столкнуться. 

Простые и сложные типы данных, описанные в 1-й главе статьи А. Емельянова, не изменились, и чтобы не дублировать качественно изложенный материал, желательно ознакомиться с представленным там описанием. Различия начинаются на этапе создания общей С++ библиотеки из среды MATLAB. 

Изложение материала в статье построено по следующей схеме:

  1. На основании подготовленного для индикатора набора MATLAB-модулей формируется C++ Shared Library (dll-библиотека), которая содержит функционал калмановской фильтрации и прогнозирования данных на основе модели Seasonal Autoregression Integrated Moving Average
  2. Затем выполняется подключение расчетного модуля к MQL5-программе. Для этого дополнительно создается библиотека-посредник, которая решает задачу передачи данных между MQL5, с памятью организованной в стиле C/C++, и MATLAB с памятью, организованной в матричной форме.
  3. Описывается модель прогнозирования, заложенная в создаваемый индикатор и демонстрируется его работоспособность.

1. Создание общей библиотеки С++ из функций MATLAB с помощью MATLAB Compiler SDK

В 2015 году произошли изменения в процедуре создания DLL-библиотек в MATLAB. Что касается задачи интеграции с программами на MQL5, суть дела сводится к тому, что MATLAB Compiler больше не предназначен для создания библиотек, а ориентирован на генерацию автономных исполняемых файлов. Функционал создания dll-библиотек с 2015 года передан MATLAB Compiler SDK. MATLAB Compiler SDK расширил функциональные возможности MATLAB Compiler, позволяя создавать общие библиотеки C/C ++, сборки Microsoft.NET и классы Java из программ MATLAB.

Как и прежде, приложения, созданные с использованием программных компонентов из пакета MATLAB Compiler SDK, можно бесплатно распространять среди пользователей, которым не требуется MATLAB. Эти приложения используют MATLAB Runtime и набор общих библиотек, которые используют скомпилированные приложения или компоненты MATLAB.

Задача, которая возлагалась на приложение MATLAB Compiler, был делегирована программе Library Compiler. Для полноты картины рассмотрим процедуру создания C/C++ shared library из среды MATLAB. В zip-архиве, прилагаемом к статье, содержатся файлы с расширением .m, которые использовались для создания библиотеки. На MATLAB (на вкладке APPS) запускается приложение Library Compiler, открывается проект LibSARIMA.prj и организуется структура, подобная изображенной на рисунке.

Рис.1. Интерфейс Library Compiler

Рис.1. Интерфейс Library Compiler.

 

Здесь важно обратить внимание на позиции, выделенные на рис. 1 линиями и цифрами 1-4. 

  1. Создается общая библиотека стандарта С++
  2. Экспортируется функция, представленная в файле ForecastSARIMA.m, при этом другие функции не представлены к экспорту и доступу внешним программам.
  3. Генерируются файлы для линковки в стандартном интерфейсе (matlabsarima.dll, matlabsarima.h, matlabsarima.lib). 
  4. Используется интерфейс доступа к матричной памяти MATLAB посредством структур mwArray.

После нажатия на кнопку «Package» будет выполнена генерация библиотеки. Можно выбрать режим формирования библиотеки с запросом пользователем загрузки пакета MATLAB Engine из интернета, а можно изначально включить необходимые составляющие MATLAB Engine в содержание пакета. 

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

2. Создание библиотеки-посредника на Microsoft Visual С++

После создания основной библиотеки следующей задачей будет к ней подключиться, передать данные и забрать результаты после расчетов. Речь идет о создании библиотеки-адаптера, обеспечивающего трансляцию данных между MQL5, где память организована в стиле C/C++, и MATLAB с памятью, организованной в матричной форме.

В новых версиях MATLABx64 компилятор Visual C++ является одним из основных, для которого подготовлено все необходимое обеспечение. Поэтому наиболее быстрым, удобным и надежным способом подготовить вспомогательную библиотеку-адаптер является применение именно Visual C++ в Studio 2017.

 

Взаимодействие MetaTrader 5 с MATLAB 2018

Рис. 2. Блок-схема взаимодействия MetaTrader 5 с MATLAB 2018 посредством DLL-адаптера

Важным нововведением в 2017 году для создания и интеграции упакованных функций в приложения C++ стало внедрение в MATLAB таких структур как mwArray API. Произошла модернизация mxArray, который использовались ранее, на новый матричный интерфейс. Имеется еще один вариант интеграции совместно используемой библиотеки — интерфейс MATLAB Data API, но в нашем случае он не имеет значения.

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

  1. Первая переменная — MATLAB_2018 должна указывать на каталог с установленным MATLAB или MATLAB Runtime; 
  2. Вторая переменная — MATLAB_2018_LIB64 должна указывать на каталог с внешними библиотеками: <MATLAB_2018>\extern\lib\win64;
  3. Третья переменная — MATLIB_USER должна указывать на каталог, куда следует помещать оригинальные библиотеки. Этот каталог нужно также добавить в системную переменную Path, чтобы снять проблему поиска оригинальных библиотек пользователя.  

2.1 Программирование адаптера в Visual Studio 2017

После создания проекта библиотеки динамической компоновки в среде Visual Studio 2017, нужно установить ряд свойств. Чтобы было понятно, какие из них необходимо контролировать, приведем рисунки по которым легко настроить проект на сборку.

Adapter Project Options #0

Рис. 3. Страницы свойств (ABCD, E) где требуется внести изменения 

Adapter SArima Options #1

Рис. 4. Каталоги поиска необходимых файлов для проекта

На рис. 4 в поле, указанное стрелочкой "Каталоги библиотек", добавлен каталог $(MatLib_User). В эту директорию удобно помещать библиотеки общего предназначения, которые нужны и для программирования в Visual C/C++ и для расчетов в MetaTrader 5. В данном случае это matlabsarima.lib и matlabsarima.dll.

Страница макросов

Рис. 5. Установить определения препроцессора


Соглашение о вызовах

Рис. 6. Соглашение о вызовах согласно требованиям MQL5

Дополнительные зависимости (*.lib)

Рис. 7. Указать дополнительные зависимости (*.lib)

Перечислим необходимые изменения в настройках проекта:

  1. Указать каталоги, где располагаются файлы необходимых заголовков;
  2. Указать каталоги, где располагаются файлы необходимых библиотек;
  3. Установить определения препроцессора — макрос, функционал которого будет рассмотрен ниже;
  4. Указать конкретные библиотеки, необходимые для работы (подготовленные MATLAB).

Два сгенерированных с помощью MATLAB файла matlabsarima.lib и matlabsarima.dll нужно поместить в каталог общего доступа, обозначенного в системных переменных $(MATLIB_USER). А файл matlabsarima.h должен быть в директории где собирается проект. Его надо включить в состав "Файлов заголовков" проекта.

Для сборки адаптера останется создать несколько файлов, из которых стоит рассмотреть два.

1. Файл AdapterSArima.h 

#pragma once
#ifdef ADAPTERSARIMA_EXPORTS
#define _DLLAPI extern "C" __declspec(dllexport)  // для создания пары DLL и LIB - библиотек нужно такое определение
#else
#define _DLLAPI extern "C" __declspec(dllimport)  // для привязки DLL- библиотеки нужно такое определение
#endif
_DLLAPI int prepareSARIMA(void);
_DLLAPI int goSarima(double *Res, double *DataArray, int idx0, int nLoad, int iSeasonPriod = 28, int npredict = 25, int filterOn = 1, int PlotOn = 0);
_DLLAPI void closeSARIMA(void);

В файле AdapterSArima.h используется макрос, установленный в настройках, чтобы указать, что процедуры  prepareSARIMA(), closeSARIMA() и goSarima(...) доступны для связки с внешними программами

2. Файл GoSArima.cpp

#pragma once
#include "stdafx.h"
#include "matlabsarima.h"
#include "AdapterSArima.h"

bool  SArimaStarted = false;
bool  MLBEngineStarted = false;

//-----------------------------------------------------------------------------------
_DLLAPI int prepareSARIMA(void)
{
        if (!MLBEngineStarted)
        {
                MLBEngineStarted = mclInitializeApplication(nullptr, 0);
                if (!MLBEngineStarted)
                {
                        std::cerr << "Could not initialize the Matlab Runtime (MCR)" << std::endl;
                        return 0;
                }
        }       
        if (!SArimaStarted)
        {
                try
                {
                        SArimaStarted = matlabsarimaInitialize();
                        if (!SArimaStarted)
                        {
                                std::cerr << "Could not initialize the library properly" << std::endl;
                                return false;
                        }                       
                        return (SArimaStarted)?1:0;
                }
                catch (const mwException &e)
                {
                        std::cerr << e.what() << std::endl;
                        return -2;
                }
                catch (...)
                {
                        std::cerr << "Unexpected error thrown" << std::endl;
                        return -3;
                }
        }
        return 1;
}
//-----------------------------------------------------------------------------------

_DLLAPI void closeSARIMA(void)
{
        // Call the application and library termination routine 
        //if (SArimaStarted)
        {
                matlabsarimaTerminate();
                SArimaStarted = false;
        }
}
//-----------------------------------------------------------------------------------

_DLLAPI int goSarima(double *Res, double *DataSeries, int idx0, int nLoad, int iSeasonPeriod, int npredict, int filterOn, int PlotOn)
{       //
        // Память для результатов должна быть выделена заблаговременно с учетом прогноза в индикаторе
        // Memory for Res[] must be allocated. Length = nLoad+npredict !!!
        //
        if (!SArimaStarted)
        {
                SArimaStarted = (prepareSARIMA() > 0) ? true : false;
        }
        
        mwArray nSeries(1, 1, mxDOUBLE_CLASS), TimeHor(1, 1, mxDOUBLE_CLASS), MAlen(1, 1, mxDOUBLE_CLASS);
        mwArray SeasonLag(1, 1, mxDOUBLE_CLASS), DoPlot(1, 1, mxDOUBLE_CLASS), DoFilter(1, 1, mxDOUBLE_CLASS);

        if (SArimaStarted)
        {
                try
                {               
                    MAlen  = 20;         // окно усреднения MA                                          
                        DoFilter  = (filterOn != 0) ? 1 : 0;
                        TimeHor   = npredict; // точек предсказания
                        SeasonLag = iSeasonPeriod;     // период сезонности для модели SARIMA                   
                        
                        DoPlot = PlotOn;    // рисунок в режиме тестирования

                        nSeries = nLoad;    // фрагмент данных длиной nLoad
                                        
                        mwArray Series(nLoad,1, mxDOUBLE_CLASS, mxREAL);
                        mwArray Result; // результат (отфильтрованные (если задано filterOn!=0)) данные и прогноз
                        
                //      выполним загрузку данных в матрицу MATLAB
                        Series.SetData(&DataSeries[idx0], nLoad); // фрагмент DataSeries[idx0: idx+nLoad]
        
                        ForecastBySARIMA(1, Result, nSeries, TimeHor, Series, SeasonLag, DoFilter, MAlen, DoPlot);
                        size_t nres = Result.NumberOfElements();
                        Result.GetData(Res, nres);

                  return 0;
                }
                catch (const mwException& e)
                {
                        std::cerr << e.what() << std::endl;
                        return -2;
                }
                catch (...)
                {
                        std::cerr << "Unexpected error thrown" << std::endl;
                        return -3;
                }               
        }       
        return 0;
}

Для полноты картины в zip-архиве представлены все файлы для сборки библиотеки-посредника AdapterSArima.dll. Если будет необходимость, рекомендуется архив распаковать и пересобирать адаптер в директории C:\temp.

3. Создание индикатора

3.1 Постановка задачи и метод решения

Модель авторегрессии и скользящего среднего является исключительно полезной для описания некоторых встречающихся на практике временных рядов. Эта модель соединяет в себе НЧ-фильтр в виде скользящего среднего порядка q и авторегрессию фильтрованных значений процесса порядка p. Если в качестве входных данных использовать не сами значения временного ряда, а их разность d-порядка (на практике d необходимо определять, однако в большинстве случаев d ≤ 2), то модель носит название авторегрессии проинтегрированного скользящего среднего. Подобная модель — ARIMA(p,d,q) (autoregression integrated moving average) позволяет уменьшить влияние нестационарности оригинального ряда.

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

Чтобы снизить влияние шумовых факторов в поступающих биржевых котировках желательно предусмотреть возможность дополнительной фильтрации и очистки данных от погрешностей. Чем сильнее зашумлены данные, тем сложнее их обрабатывать. Фильтр Калмана —  эффективный алгоритм рекурсивной фильтрации, используемый в различных областях. Алгоритм состоит из двух повторяющихся фаз: предсказание и корректировка. На первом шаге рассчитывается предсказание состояния в следующий момент времени (с учетом неточности их измерения). Далее, с учетом новой информации, корректируется предсказанное значение (также с учетом неточности и зашумленности этой информации). 

3.2 Программа индикатора на MQL5

Необходимые для индикатора библиотеки AdapterSArima.dll и matlabsarima.dll должны быть помещены в директорию Libraries рабочего каталога MetaTrader 5.

Имеется некоторая специфика отладки и тестирования. В этом режиме MetaEditor запускает библиотеку из вспомогательных каталогов <MetaQuotes\Tester\....\Agent-127.0.0.1-300x>, где 300х принимает значения 3000, 3001, 3002 и т.д. При этом библиотека AdapterSArima.dll копируется автоматически, а matlabsarima.dll - нет. Чтобы это не влияло на работу индикатора, библиотека matlabsarima.dll должна быть в системном каталоге, где проводится поиск. Рекомендовалось обозначить такой каталог через $(MATLIB_USER) и указать в системном списке путей поиска или скопировать в Windows или Windows\System32. Тогда библиотека будет обнаруживаться, подключаться и индикатор запустится. 

Программа индикатора, в котором задействован прогноз по рассмотренной модели, содержится в файле ISArimaForecast.mq5 и прилагаемом архиве.

//+------------------------------------------------------------------+
//|                                              ISArimaForecast.mq5 |
//|                                                Roman Korotchenko |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "Roman Korotchenko"
#property link        "https://login.mql5.com/ru/users/Solitonic"
#property description "This indicator demonstrates forecast by model SARIMA(2,1,2)."
#property description "The program actively uses MATLAB with professionally developed toolboxes and the ability to scale."
#property version   "1.00"
#property indicator_chart_window 

#import "AdapterSArima.dll"
int  prepareSARIMA(void);
int  goSarima(double &Res[],double &DataArray[],int idx0,int nLoad,int iSeasonPeriod,int npredict,int filterOn,int PlotOn);
void closeSARIMA(void);
#import

#property indicator_buffers 2    //---- Buffers for calculating and drawing the indicator
#property indicator_plots   1    //---- graphic constructions
#property indicator_type1  DRAW_COLOR_LINE   
#property indicator_color1  clrChocolate, clrBlue // clrWhite, clrBlue
#property indicator_width1  3 
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_TIMERECALC
  {
   TimeRecalc05 = 5,   // 5 sec
   TimeRecalc10 = 10,  // 10 sec
   TimeRecalc15 = 15,  // 15 sec
   TimeRecalc30 = 30,  // 30 sec
   TimeRecalc60 = 60   // 60 sec
  };
//--- input parameters
input ENUM_TIMERECALC RefreshPeriod=TimeRecalc30;         // Recalculate period
input int      SegmentLength  = 450; // N: Data fragment
input int      BackwardShift  = 0;   // Backward shift (testing)
input int      ForecastPoints = 25;  // Point to forecast
input int      SeasonLag=32;         // Season lag of SARIMA(2,1,2)
input bool     DoFilter=true;        // Do Kalman filtering of Data Series

                                     // input string   _INTERFACE_   = "* INTERFACE *"; 
//input long     magic_numb=19661021777;       // Magic Number 

//--- indicator buffers
double   DataBuffer[],ColorBuffer[];
//double   LastTrend[],LastData[];

double   wrkResult[],wrkSegment[];
static int wRKLength;

uint CalcCounter;
//
uint calc_data;
uint start_data;    // Start time to build the chart
uint now_data;      // Current time

static int libReady=0,ErrorHFRange,ErrorDataLength;
static bool   IsCalcFinished;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
static int LengthWithPrediction;

static int PlotOn;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit()
  {
   closeSARIMA();
   Alert("SARIMA DLL - DeInit");
   Print("SARIMA DLL - DeInit");
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
      Alert("Check the connection permission in the terminal settings DLL!");
   else
     {
      libReady=prepareSARIMA();
      if(libReady<0)
        {
         Alert("Dll DOES NOT CONNECTED!");
         return(INIT_FAILED);
        }

     }

   LengthWithPrediction=SegmentLength+ForecastPoints;
//--- indicator buffers mapping
   SetIndexBuffer(0,DataBuffer,INDICATOR_DATA);            ArraySetAsSeries(DataBuffer,true);
   SetIndexBuffer(1,ColorBuffer,INDICATOR_COLOR_INDEX);    ArraySetAsSeries(ColorBuffer,true);
// SetIndexBuffer(2,LastTrend,   INDICATOR_CALCULATIONS);   ArraySetAsSeries(LastTrend,true);      //for Expert
// SetIndexBuffer(3,LastData,    INDICATOR_CALCULATIONS);   ArraySetAsSeries(LastData,true);       //for Expert

   PlotIndexSetInteger(0,PLOT_SHIFT,ForecastPoints-BackwardShift);

   wRKLength = ForecastPoints+ SegmentLength; // The number of elements in the array with the results
   ArrayResize(wrkResult,wRKLength,0);        // Allocates memory for function results
   ArrayResize(wrkSegment,SegmentLength,0);   // Allocates memory for input data.

//---   
   string shortname;
   StringConcatenate(shortname,"SARIMA(2,1,2). Season Lag: ",SeasonLag,"  // ");
//--- The label to display in DataWindow
   PlotIndexSetString(0,PLOT_LABEL,shortname);
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);

   now_data  = 0.001*GetTickCount();
   start_data= 0.001*GetTickCount();
   calc_data = 0;

   CalcCounter    = 1;
   IsCalcFinished = true;

   ErrorHFRange   = 0;
   ErrorDataLength= 0;

   PlotOn=0; // Auxiliary drawing, executed by MATLAB (for testing)

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[]
                )
  {
//---
   int ShiftIdx=rates_total-SegmentLength-BackwardShift; // The starting index for the work segment data 

   if(ShiftIdx<0)
     {
      if(!ErrorDataLength)
        {
         PrintFormat("SARIMA INDI FAULT: there are not enough data.");
         ErrorDataLength=1;
        }
      return(0);
     }

   ErrorDataLength=0;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

   now_data=0.001*GetTickCount();

   if(now_data-calc_data<RefreshPeriod || !IsCalcFinished) // calculation is not needed or not completed
     {
      // ReloadBuffers(prev_calculated,rates_total);
      return(prev_calculated);
     }
   if(prev_calculated!=0 && !IsCalcFinished)
     {
      return(prev_calculated);  // New data comes faster than current calculation finished 
     }
//---------------------------------------------------------------------------     

   IsCalcFinished=false; // Block the request a new calculation until the current one is executed

   int idx=0,iBnd2=ShiftIdx+SegmentLength;
   for(int icnt=ShiftIdx; icnt<iBnd2; icnt++)
     {
      wrkSegment[idx++]=price[icnt];
     }

   ErrorHFRange=0;
// MATLAB SUBROUTINE   
   goSarima(wrkResult,wrkSegment,0,SegmentLength,SeasonLag,ForecastPoints,DoFilter,PlotOn);

   ReloadBuffers(LengthWithPrediction,rates_total);

   ++CalcCounter;
   IsCalcFinished=true; // Ready to make new calculation 

   calc_data=0.001*GetTickCount();

   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EmptyBuffers(int n)
  {
   for(int i=0; i<n; i++)
     {
      DataBuffer[i] = EMPTY_VALUE;
      ColorBuffer[i]= EMPTY_VALUE;
     }
  }
//+------------------------------------------------------------------+ 

void ReloadBuffers(int npoint,int ntotal)
  {
   ResetLastError();
   EmptyBuffers(ntotal); // ntotal = rates_total

   if(npoint== 0) return;
   int k=0;//BackwardShift;
   for(int i=0; i<npoint; i++) // npoint = LengthWithPrediction
     {
      if(i>=ntotal) break;
      DataBuffer [k]=wrkResult[LengthWithPrediction-1-i];
      ColorBuffer[k]=(i<ForecastPoints)? 1:0;
      k++;
     }
  }
//=============================================================================

4. Иллюстрация работы индикатора

Работоспособность индикатора была опробована на данных торговли EURUSD H1, предоставленным платформой MetaTrader. Был выбран не слишком большой сегмент данных, размер которого 450 отсчетов, а варианты длиннопериодного "сезонного" лага опробованы 28, 30 и 32 отсчета, лучшим из них на рассмотренном периоде истории был лаг с периодом 32 отсчета.

Выполнялась серия расчетов для разных фрагментов истории. Длина сегмента данных в модели – 450, сезонный лаг 32 и длина прогноза 30 были установлены один раз и не менялись. Чтобы оценить качество прогноза полученные результаты для разных фрагментов сравнивались с фактическими данными.

Приведем рисунки, демонстрирующие результат работы индикатора. На всех рисунках шоколадным цветом отображено завершение фрагмента, по которому в MATLAB была подобрана модель SARIMA(2,1,2), а полученный на ее основании построен прогноз отрисован синим цветом.

EURUSDH1_450(32)-180

Рис. 8. Торговая сессия 30.12.2018. Фильтрация Калмана применяетсяМодель построена по данным со сдвигом в прошлое на 180 отсчетов 


 EURUSDH1_450(32)-170

Рис. 9. Дневная торговая сессия 30.12.2018. Фильтрация Калмана не используется. Модель построена по данным со сдвигом в прошлое на 170 отсчетов 


EURUSDH1_450(32)-140

Рис. 10. Торговая сессия 31.12.2018. Фильтрация Калмана применяется. Модель построена по данным со сдвигом в прошлое на 140 отсчетов 


EURUSDH1_450(32)-120

Рис. 11. Торговая сессия 1.02.2019. Фильтрация Калмана применяется. Модель построена по данным со сдвигом в прошлое на 120 отсчетов 


EURUSDH1_450(32)-100

Рис. 12. Торговая сессия 4.02.2019. Фильтрация Калмана применяется. Модель построена по данным со сдвигом в прошлое на 100 отсчетов 


EURUSDH1_450(32)-50

Рис. 13. Торговая сессия 6.02.2019. Фильтрация Калмана применяется. Модель построена по данным со сдвигом в прошлое на 50 отсчетов 


EURUSDH1_450(32)-20

Рис. 14. Торговая сессия 7.02.2019. Фильтрация Калмана применяется. Модель построена по данным со сдвигом в прошлое на 20 отсчетов 


EURUSDH1_450(32)-10

Рис. 15. Торговая сессия 8.02.2019. Фильтрация Калмана применяется. Модель построена по данным со сдвигом в прошлое на 10 отсчетов 

Результаты моделирования показывают неплохую вероятность совпадения значений спрогнозированных цен в первых 10-12 отсчетах и значений, наблюдавшихся в реальном времени. При чем, что интересно, от трейдера требуется немного труда для настройки модели. Для модели нужны два параметра — длина сегмента и период сезонности, которые можно выбрать методом прогонки на данных ближайшей истории. Остальная расчетная нагрузка достается MATLAB.  В дальнейшем можно рассмотреть оптимальный подбор параметров длины сегмента и период сезонности как направление для модернизации индикатора.

Заключение

В статье был продемонстрирован весь цикл разработки программного обеспечения с применением 64-х разрядных версий пакетов MQL5 и MATLAB 2018. Дополнительно показано применение Visual C++ 2017 (x64) для создания адаптера, обеспечивающего трансляцию данных между MetaTrader, где память организована в стиле C/C++, и MATLAB с памятью, организованной в матричной форме. 

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

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

В архиве к статье (MatlabSArima.zip) содержится директория MatlabSArima\LibSARIMA\for_redistribution, предполагающая установку из интернет MATLAB Runtime. Если стремиться уменьшить объем MATLAB Runtime информации для индикатора SARIMA, то для этого надо скачать набор из 10-ти файлов, затем их распаковать и объединить с помощью программы Total Commander.

Файл Путь загрузки
sarima_plusMCR00.zip 89.16 MB https://pinapfile.com/aKrU7 
sarima_plusMCR01.zip 94.75 MB https://pinapfile.com/fvZNS 
sarima_plusMCR02.zip 94.76 MB https://pinapfile.com/k7wB5 
sarima_plusMCR03.zip 94.76 MB https://pinapfile.com/jwehs 
sarima_plusMCR04.zip 94.76 MB https://pinapfile.com/dv8vK 
sarima_plusMCR05.zip 94.76 MB https://pinapfile.com/hueKe 
sarima_plusMCR06.zip 94.76 MB https://pinapfile.com/c4qzo 
sarima_plusMCR07.zip 94.76 MB https://pinapfile.com/eeCkr 
sarima_plusMCR08.zip 94.76 MB https://pinapfile.com/jDKTS 
 sarima_plusMCR09.zip 94.76 MB https://pinapfile.com/dZDJM