Usando os recursos computacionais do MATLAB 2018 no MetaTrader 5

Roman Korotchenko | 30 abril, 2019

Introdução

Este artigo é uma continuação do artigo de Andrey Emelyanov "Interação entre o MetaTrader 5 e MATLAB", fornecendo informações sobre como resolver um problema semelhante para as atuais versões de 64 bits de todas as plataformas usadas pelos usuários. Durante a existência do pacote MATLAB, o método de criação de bibliotecas dll compartilhadas tem sido significativamente atualizado. Por essa razão, o método discutido no artigo original requer modificações. Agora, em vez do MATLAB Compiler, é preciso usar o MATLAB Compiler SDK ou o MATLAB Coder. Além disso, mudou a maneira de trabalhar com a memória dinâmica no MATLAB, implicando certos ajustes no código do programa que obtém acesso à biblioteca escrita na linguagem MATLAB. 

A partir do título do artigo, entende-se que este trabalho visa facilitar a ligação dos recursos computacionais do MATLAB com programas escritos em MQL5. Para este fim, como exemplo, é criado um indicador preditivo baseado no modelo autorregressivo integrado de médias móveis sazonal (SARIMA) para uma série temporal de preços, em que o MATLAB tem a tarefa de selecionar o modelo adequado e extrapolar dados. 

Para apresentar os pormenores de como ligar o potencial computacional do ambiente MATLAB 2018 à MQL5, este artigo considera especificamente o MATLAB Compiler SDK, a criação de uma biblioteca de adaptadores em Visual C++ para conectar a biblioteca MATLAB com a MQL5. Isso permite obter um guia rápido para criar programas, evitando erros comuns que qualquer um teria que enfrentar. 

Tipos de dados simples e complexos, descritos no capítulo 1 do artigo de Andrey Emelyanov, não mudaram e, para não aumentar o material aqui apresentado, é aconselhável para se familiarizar com a descrição apresentada nele. As diferenças começam na etapa de criação de uma biblioteca C++ comum a partir do ambiente MATLAB. 

O material mostrado no artigo se baseia no seguinte esquema:

  1. Com base no conjunto de módulos do MATLAB preparados para o indicador, é formada uma Biblioteca Compartilhada C++ (biblioteca dll) contendo o filtro de Kalman e predição de dados com base no modelo Autorregressivo Integrado de Médias Móveis Sazonal
  2. Em seguida, o módulo de cálculo é conectado ao programa MQL5. Para isso, adicionalmente é criada uma biblioteca intermediária, resolvendo o problema de transferência de dados entre a MQL5 (com memória em estilo C/C++) e MATLAB (com memória em forma de matriz).
  3. É descrito um modelo de previsão embutido no indicador gerado e é apresentado seu desempenho.

1. Criando uma biblioteca compartilhada C++ a partir de funções do MATLAB usando o MATLAB Compiler SDK

Em 2015, houve alterações no procedimento para criar bibliotecas DLL no MATLAB. Quanto à integração com programas em MQL5, agora o MATLAB Compiler está focado na geração de arquivos executáveis independentes, e não na criação de bibliotecas, como antigamente. Desde 2015, a criação de bibliotecas de DLLs foi transferida para o MATLAB Compiler SDK. O MATLAB Compiler SDK expandiu a funcionalidade do MATLAB Compiler, permitindo criar bibliotecas compartilhadas C/C ++, assemblies Microsoft.NET e classes Java a partir de programas MATLAB.

Como no passado, os aplicativos criados usando os componentes de software do pacote MATLAB Compiler SDK podem ser distribuídos gratuitamente entre usuários que podem dispensar o MATLAB. Esses aplicativos usam o MATLAB Runtime e um conjunto de bibliotecas compartilhadas que usam aplicativos compilados ou componentes do MATLAB.

A tarefa que era conferida ao aplicativo MATLAB Compiler é delegada ao programa Library Compiler. Para completar, consideramos o procedimento para criar uma biblioteca compartilhada C/C++ a partir do MATLAB. O arquivo zip anexado ao artigo contém arquivos com a extensão .m usados para criar a biblioteca. No MATLAB (na guia APPS), é iniciado o aplicativo Library Compiler, é aberto o projeto LibSARIMA.prj e é formada uma estrutura semelhante à mostrada na imagem.

Fig. 1. Interface do Library Compiler

Fig. 1. Interface do Library Compiler.

 

Aqui é importante prestar atenção às posições destacadas na fig. 1 com linhas e números 1-4. 

  1. Criada uma biblioteca compartilhada padrão em C++.
  2. Exportada uma função apresentada no arquivo ForecastSARIMA.m, além disso, outras funções não são para exportação e acesso a programas externos.
  3. Gerados arquivos para ligação com a interface padrão (matlabsarima.dll, matlabsarima.h, matlabsarima.lib). 
  4. Utilizada a interface de acesso à matriz de memória do MATLAB através de estruturas mwArray.

Depois de clicar no botão «Package», é gerada a biblioteca. Pode-se selecionar o modo de geração de biblioteca com o usuário solicitando o download do pacote MATLAB Engine da Internet, ou pode-se incluir inicialmente os componentes necessários do MATLAB Engine no conteúdo do pacote. 

Nesta etapa, é criada uma biblioteca com um programa projetado para filtrar as séries temporais, para construir o modelo SARIMA e a previsão. O arquivo MatlabSArima.zip contém um conjunto de fontes e o resultado da montagem da biblioteca.

2. Criando uma biblioteca intermediária em Microsoft Visual C ++

Depois de criar a biblioteca principal, a próxima tarefa é conectar-se a ela, transferir dados e coletar resultados após os cálculos. Trata-se de criar uma biblioteca adaptador fornecendo tradução de dados entre o MQL5, com memória usada em estilo C/C++ e o MATLAB com memória em forma de matriz.

Nas novas versões do MATLABx64, o compilador Visual C++ é um para os quais foi preparado todo o software necessário. Portanto, a maneira mais rápida, mais conveniente e confiável de preparar a biblioteca adaptador auxiliar é usar o Visual C++ no Studio 2017.

 

Interação do MetaTrader 5 com o MATLAB 2018

Fig. 2. Diagrama de blocos da interação do MetaTrader 5 com o MATLAB 2018 através de um adaptador DLL

Uma inovação importante em 2017 para a criação e integração de funções empacotadas em aplicativos C++ foi a introdução de estruturas em MATLAB como a API mwArray. Foi atualizado mxArray, usado anteriormente, na nova interface de matriz. Há outra opção de integração juntamente com a biblioteca usada, isto é, a interface MATLAB Data API mas no nosso caso isso não importa.

Para iniciar a programação direta do adaptador para dados, é bom preparar e registrar três variáveis de ambiente do sistema no sistema operacional. Isto pode ser feito, por exemplo, com a ajuda do Explorador de Arquivos através das «propriedades do computador», indo para os «parâmetros adicionais do sistema» e «variáveis de ambiente».

  1. Primeira variável — MATLAB_2018 deve apontar para um diretório com MATLAB ou MATLAB Runtime instalado; 
  2. Segunda variável — MATLAB_2018_LIB64 deve apontar para um diretório com bibliotecas externas: <MATLAB_2018>\extern\lib\win64;
  3. Terceira variável — MATLIB_USER deve apontar para o diretório em que as bibliotecas originais devem ser colocadas. Esse diretório também deve ser adicionado à variável de sistema Path para resolver o problema de localizar as bibliotecas originais de usuários.  

2.1 Programando adaptadores no Visual Studio 2017

Depois de criar o projeto da biblioteca no Visual Studio 2017, é preciso definir várias propriedades. Para deixar claro quais delas precisam ser monitoradas, fornecemos imagens que facilitam a configuração da montagem do projeto.

Adapter Project Options #0

Fig. 3. Página de propriedades (ABCD, E) em que é necessário realizar alterações 

Adapter SArima Options #1

Fig. 4. Diretórios de arquivos necessários para o projeto

Na Fig. 4 ao campo, indicado pela seta "Catálogos de bibliotecas", adicionado o catálogo $(MatLib_User). Neste diretório é conveniente colocar bibliotecas de propósito geral que também são necessárias para programação em Visual C/C++ e para cálculos no MetaTrader 5, neste caso, matlabsarima.lib e matlabsarima.dll.

Array de macros

Fig. 5. Definições do pré-processador


Convenção de chamada

Fig. 6. Convenção de chamada de acordo com os requisitos MQL5

Dependências adicionais (*.lib)

Fig. 7. Especificando dependências adicionais (*.lib)

Listamos as alterações necessárias nas configurações do projeto:

  1. Especificar os diretórios onde estão localizados os arquivos dos cabeçalhos necessários;
  2. Especificar os diretórios onde estão localizadas as bibliotecas necessárias;
  3. Especificar as definições do pré-processador— macro cuja funcionalidade será discutida abaixo;
  4. Especificar bibliotecas necessárias para o trabalho (preparadas pelo MATLAB).

matlabsarima.lib e matlabsarima.dll, dois arquivos gerados usando MATLAB, precisam ser colocados no diretório de compartilhamento designado nas variáveis do sistema $(MATLIB_USER). Já o arquivo matlabsarima.h deve estar no diretório onde o projeto está sendo juntado. Ele deve ser incluído nos arquivos de cabeçalho do projeto.

Para montar o adaptador, resta criar vários arquivos, dos quais vale a pena considerar dois.

1. Arquivo AdapterSArima.h 

#pragma once
#ifdef ADAPTERSARIMA_EXPORTS
#define _DLLAPI extern "C" __declspec(dllexport)  // para criar um par DLL e LIB - as bibliotecas precisam de tal definição
#else
#define _DLLAPI extern "C" __declspec(dllimport)  // para ligar a biblioteca DLL- as bibliotecas precisam de tal definição
#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);

O arquivo AdapterSArima.h usa uma macro definida nas configurações, para indicar que os precedimentos prepareSARIMA(), closeSARIMA() e goSarima(...) podem ser vinculados a programas externos

2. Arquivo 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)
{       //
        // A memória para os resultados deve ser alocada antecipadamente, levando em conta a previsão no indicador
        // 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;         // janela de média MA                                          
                        DoFilter  = (filterOn != 0) ? 1 : 0;
                        TimeHor   = npredict; // pontos de previsão
                        SeasonLag = iSeasonPeriod;     // período de sazonalidade para o modelo SARIMA                   
                        
                        DoPlot = PlotOn;    // plotagem no modo de teste

                        nSeries = nLoad;    // fragmento de dados de larguras nLoad
                                        
                        mwArray Series(nLoad,1, mxDOUBLE_CLASS, mxREAL);
                        mwArray Result; // resultados (filtrados (se definido filterOn!=0)) dados e previsão
                        
                //      carregamos os dados no array MATLAB
                        Series.SetData(&DataSeries[idx0], nLoad); // fragmento 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;
}

Para completar, o arquivo zip contém todos os arquivos para montar a biblioteca intermediária AdapterSArima.dll. Se necessário, recomenda-se descompactar o arquivo e reconstruir o adaptador no diretório C:\temp.

3. Criação do indicador

3.1 Problema e solução

O modelo de autorregressão e o de média móvel são extremamente úteis para descrever algumas das séries temporais encontradas na prática. Este modelo combina um filtro passa-baixo na forma de média móvel de ordem q e autorregressão dos valores filtrados do processo de ordem p. Se como dados de entrada não são usados os próprios valores de séries temporais, mas, sim, sua diferença d-ordem (na prática, é necessário determinar d, no entanto, na maioria dos casos d ≤ 2), o modelo é chamado de autorregressão da média móvel integrada. Um modelo semelhante - ARIMA(p,d,q) (autoregression integrated moving average) - permite reduzir a não estacionariedade da série original.

Para simular os efeitos da variabilidade de longo período, há uma modificação chamada ARIMA sazonal. Este modelo corresponde às séries temporais expostas a fatores periódicos. Nas cotações de ações há influência de fatores de sazonalidade, portanto, é apropriado incluí-la no modelo para criar uma previsão de preço no indicador. 

Para reduzir a influência dos fatores de ruído nas cotações de ações recebidas, é bom providenciar uma filtragem adicional e uma limpeza de dados. Quanto mais ruido tiverem os dados, mais difícil será processá-los. O filtro de kalman é um algoritmo de filtragem recursiva eficaz usado em vários campos. O algoritmo consiste em duas fases repetidas: previsão e ajuste. No primeiro passo, calcula-se a previsão do estado no momento seguinte (tendo em conta a imprecisão da sua medição). Além disso, o valor previsto é ajustado tendo em conta a nova informação (também tendo em conta a imprecisão e o ruído desta informação). 

3.2 Programa do indicador em MQL5

As bibliotecas AdapterSArima.dll e matlabsarima.dll necessárias para o indicador devem ser colocadas no diretório Libraries do diretório de trabalho do MetaTrader 5.

Há alguma especificidade de depuração e de teste. Neste modo, o MetaEditor executa a biblioteca a partir dos diretórios auxiliares <MetaQuotes\Tester\....\Agent-127.0.0.1-300x>, onde 300х assumem os valores 3000, 3001, 3002, etc. Nesse caso, a biblioteca AdapterSArima.dll é copiada automaticamente, enquanto a matlabsarima.dll, não. Para que isso não afete a operação do indicador, a biblioteca matlabsarima.dll deve estar no diretório de pesquisa do sistema. Foi recomendado designar um diretório como $(MATLIB_USER)e indicar na lista de caminhos de pesquisa do sistema ou copiar para Windows ou Windows\System32. Em seguida, a biblioteca é detectada, conectada e o indicador é iniciado. 

O programa do indicador, que usa a previsão do modelo considerado, está contido no arquivo ISArimaForecast.mq5 e no arquivo anexado.

//+------------------------------------------------------------------+
//|                                              ISArimaForecast.mq5 |
//|                                                Roman Korotchenko |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "Roman Korotchenko"
#property link        "https://login.mql5.com/pt/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. Demonstração do indicador

A eficiência do indicador foi testada com base em dados de negociação fornecidos pela plataforma MetaTrader, EURUSD H1. Foi selecionado um segmento de dados de 450 contagens (não muito grande), enquanto foram testados atrasos de longo período "sazonal" de 28, 30, e 32 contagens, no período analisado o melhor entre eles foi o atraso com um período de 32 contagens.

Foi realizada uma série de cálculos para diferentes fragmentos do histórico. No modelo, o comprimento do segmento de dados (450), o atraso sazonal (32), o comprimento da previsão (30) foram definidos uma vez e sem alterações posteriores. Para avaliar a qualidade da previsão, os resultados de diferentes fragmentos foram comparados com os dados reais.

Apresentamos imagens mostrando o resultado do indicador. Em todas as imagens, a cor de chocolate indica a conclusão do fragmento, segundo o qual o modelo SARIMA(2,1,2) foi selecionado no MATLAB, enquanto a previsão obtida, construída com base nele, é plotada a azul.

EURUSDH1_450(32)-180

Fig. 8. Pregão de 30.12.2018. Aplica-se filtragem de Kalman O modelo é construído de acordo com dados com um deslocamento no passado em 180 contagens 


 EURUSDH1_450(32)-170

Fig. 9. Sessão de negociação diária 30.12.2018. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 170 contagens 


EURUSDH1_450(32)-140

Fig. 10. Pregão de 31.12.2018. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 140 contagens 


EURUSDH1_450(32)-120

Fig. 11. Pregão de 1.02.2019. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 120 contagens 


EURUSDH1_450(32)-100

Fig. 12. Pregão de 4.02.2019. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 100 contagens 


EURUSDH1_450(32)-50

Fig. 13. Pregão de 6.02.2019. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 50 contagens 


EURUSDH1_450(32)-20

Fig. 14. Pregão de 7.02.2019. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 20 contagens 


EURUSDH1_450(32)-10

Fig. 15. Pregão de 8.02.2019. Aplica-se filtragem de Kalman. O modelo é construído de acordo com dados com um deslocamento no passado em 10 contagens 

Os resultados da simulação mostram uma boa probabilidade de correspondência entre valores previstos nas primeiras 10-12 contagens e valores observados em tempo real. Além disso, é interessante que o trader precisa apenas de fazer um pequeno esforço para configurar o modelo. O modelo requer dois parâmetros, isto é, o comprimento do segmento e o período de sazonalidade, que podem ser selecionados pelo método de varredura nos dados do histórico mais recente. O restante da carga calculada vai para o MATLAB. No futuro, pode-se analisar o conjunto ideal de parâmetros para o comprimento do segmento e para o período de sazonalidade, a fim de modernizar o indicador.

Fim do artigo

O artigo apresentou todo o ciclo de desenvolvimento de software usando versões de 64 bits dos pacotes MQL5 e MATLAB 2018. Adicionalmente, mostrou o uso do Visual C++ 2017 (x64) para criar um adaptador fornecendo envio de dados entre MetaTrader com memória em estilo de C/C++ e MATLAB, em forma de array. 

O indicador apresentado com previsão baseada no modelo SARIMA e no filtro de Kalman é uma demonstração das possibilidades de utilização do MATLAB em aplicativos econométricos. Ele tem um grande potencial de desenvolvimento adicional se o MATLAB desenvolver o processamento de dados e automatizar a determinação de componentes sazonais, para otimizar o modelo de trabalho de previsão. 

O exemplo do indicador é uma ilustração do uso do pacote MATLAB, permitindo conectar os sistemas de negociação MetaTrader a redes neurais, a algoritmos de lógica difusa e a outros métodos complexos e modernos de processamento de cotações de ações, com eficiência e rapidez.

O arquivo do artigo (MatlabSArima.zip) contém o diretório MatlabSArima\LibSARIMA\for_redistribution, para instalar a partir do MATLAB Runtime da Internet. Se você quiser reduzir a quantidade de informações de tempo de execução do MATLAB para o indicador SARIMA, você precisa baixar um conjunto de 10 arquivos, depois descompactá-los e combiná-los usando o Total Commander.

Arquivo Caminho de download
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