English Русский 中文 Español Deutsch 日本語
LibMatrix: Biblioteca de Álgebra Matricial (Parte I)

LibMatrix: Biblioteca de Álgebra Matricial (Parte I)

MetaTrader 4Exemplos | 29 setembro 2015, 09:43
1 014 0
Evgeniy Logunov
Evgeniy Logunov

Introdução

As aplicações de vários ramos da matemática são essenciais para escrever sistemas complexos de negociação automatizada. Um desses ramos é álgebra linear.

Atualmente não existem extensas bibliotecas acessíveis ao público em MQL4 que implementam vários métodos de álgebra linear (particularmente, a teoria de matrizes e determinantes).

Este artigo descreve a biblioteca LibMatrix em MQL4 que inclui a execução das operações mais comuns com matrizes.

"Matriz" é um array retangular finito e preenchido com alguns objetos matemáticos (por exemplo, números).

Quatro meses depois de escrever todo o código em C++, reescrevi em MQL4 com algumas modificações.


1. Estrutura da Biblioteca

Vamos primeiro considerar algumas peculiaridades do trabalho com matrizes nesta proposta de biblioteca.

Em primeiro lugar, as matrizes são armazenadas em arrays unidimensionais, isto tem a ver com o fato da lingagem MQL4 oferecer características para a criação de arrays multidimensionais, onde apenas é possível alterar o tamanho da primeira dimensão. Para armazenar uma matriz de N linhas e M colunas, precisamos de um array unidimensional N*M. A matriz é embutida num array linha por linha, ou seja, os primeiros elementos de linha no array de dados são seguidos pelos segundos elementos de linha e assim por diante.

Em segundo lugar, durante a criação da biblioteca foi decidido não armazenar informações suplementares sobre o tamanho da matriz no array de dados, pois os tamanhos são valores inteiros, enquanto que os elementos são números reais (tamanhos de armazenamento como números reais podem afetar dramaticamente a operação da biblioteca).

Assim, uma matriz no formato processado pela proposta desta biblioteca consiste de três variáveis: a array unidimensional do tipo double e duas variáveis inteiras (por exemplo, do tipo int) para armazenar informações relativas ao número de linhas e colunas da matriz.

A biblioteca possue dois arquivos: LibMatrix.mqh e LibMatrix.mq4. O primeiro arquivo é para ser incluído quando necessário, ele contém protótipos de funções que podem ser importados a partir da biblioteca. O segundo arquivo contém implementações das funções (códigos de programa), nas próximas linhas mais abaixo, estaremos comentando mais sobre ele.

As funções executadas na biblioteca podem ser divididas em vários grupos:

  • funções matemáticas genéricas (MathLerp, MathInRangeRandom, MathDoublesEqual)
  • funções auxiliares para trabalhar com matrizes (MatrIndiciesToOffset, MatrCopy, MatrSetSize, MatrResize)
  • funções para trabalhar com linhas e colunas (MatrSwapRows, MatrSwapCols, MatrCopyRow, MatrCopyCol, MatrRowIsZero, MatrColIsZero)
  • funções para verificação geral de condições (MatrIsSquare, MatrIsElemOnMainDiagonal, MatrCompatiblityCheckAdd, MatrCompatiblityCheckMul)
  • funções de inicialização de conteúdo (MatrLoadZero, MatrLoadIdentity, MatrLoadInRangeRandom)
  • funções para verificar as condições por tipo de conteúdo (MatrIsZero, MatrIsDiagonal, MatrIsIdentity, MatrIsSymmetric, MatrIsAntisymmetric, MatrEqual)
  • funções para "element-wise" das operações de escalar (MatrAddScalar, MatrSubScalar, MatrMulByScalar, MatrDivByScalar)
  • funções para operações básicas com matrizes (MatrAddMatr, MatrSubMatr, MatrMulMatr, MatrTrace, MatrTranspose)
  • outras funções (MatrGaussianElimination, MatrGJBatchSolve, MatrMinor, MatrAlgebraicComplement, MatrInvertUsingMinors, MatrInvertUsingGJ, MatrDet, MatrDetTriang, MatrRank, MatrRankTriang, MatrComputeConnectedMatr, MatrLerpMatr)
  • funções de entrada/saída (MatrPrint, FileWriteMatr, FileReadMatr)

Vamos dar uma olhada em cada um destes grupos.


2. Descrição das Funções


2.1. Funções Matemáticas Genéricas

Vamos primeiro considerar o grupo de funções matemáticas genéricas, inclui funções que não estão diretamente relacionadas com as matrizes, mas são usados na biblioteca.

double MathLerp(double rangeLowLimit, double rangeHighLimit, double balance);

Esta função executa a interpolação linear entre dois valores, utilizando a seguinte fórmula: rangeLowLimit + equilíbrio * (rangeHighLimit - rangeLowLimit). O valor do parâmetro balance deve estar dentro do intervalo [0; 1].

double MathInRangeRandom(double rangeLowLimit, double rangeHighLimit);

Esta função retorna distribuindo números aleatórios uniformemente a partir do intervalo [rangeLowLimit;rangeHighLimit]. A função padrão MathRand é utilizada para formação.

bool MathDoublesEqual(double value1, double value2, double tolerance);

Esta função é usada para comparar dois valores, value1 e value2, do tipo double com a precisão especificada (tolerance). Comparações aproximadas são necessárias devido a possível perda de precisão, o valor do parâmetro tolerance não deve ser negativo (como o valor padrão, você pode usar a constante DEFAULT_TOLERANCE, definida na biblioteca).


2.2. Funções Auxiliares para Trabalhar com Matrizes

Vamos ao grupo de funções auxiliares para trabalhar com matrizes. Este grupo abrange funções destinadas à simplificação das operações relacionadas a matrizes embutidas em arrays unidimensionais.

int MatrIndiciesToOffset(int row, int col, int numRows, int numCols)

Esta função calcula o deslocamento de um elemento em relação ao início do array no qual a matriz é embutida. Entre os parâmetros recebidos estão os números das linhas (row) e colunas (col), na intersecção onde o elemento se encontra, bem como o tamanho de matriz (numRows - número de linhas da matriz, numCols - número de colunas da matriz), os valores row e col devem estar dentro dos intervalos [0;numRows-1] e [0;numCols-1], respectivamente.

void MatrCopy(double& src[], double& dst[]);

Esta função copia todos os elementos da matriz src à matriz dst, após a conclusão da cópia, o tamanho da matriz dst torna-se igual ao tamanho de matriz src. O array de dados das matrizes são os únicos parâmetros transmitidos.

void MatrSetSize(double& matr[], int numRows, int numCols);

Esta função altera o tamanho do array de dados matr, podendo assim armazenar uma matriz de linhas, numRows, e colunas, numCols. A integridade dos dados da matriz não é garantida, os valores dos parametros numRows e numCols devem ser obrigatoriamente positivos.

void MatrResize(double& matr[], int numRowsOld, int numColsOld, int numRowsNew, int numColsNew);

Esta função altera o tamanho do array de dados matr da matriz existente, os parâmetros numRowsOld e numColsOld devem ser iguais ao tamanho inicial da matriz. A nova dimensão é definida pelos parâmetros numRowsNew e numColsNew. A integridade dos dados da matriz é garantida e sujeita a novo tamanho, exceto para os casos onde uma ou ambas as dimensões da matriz são diminuídas. Novos elementos são inicializados com zeros.


2.3. Funções para Trabalhar com Linhas e Colunas

Vamos dar uma olhada nas funções para trabalhar com linhas e colunas da matriz.

void MatrSwapRows(double& matr[], int numRows, int numCols, int row1, int row2);

Esta função troca o conteúdo das linhas row1 e row2 à matriz matr que consiste de linhas numRows e colunas numCols, os valores dos parâmetros row1 e row2 devem estar dentro do intervalo [0;numRows-1].

void MatrSwapCols(double& matr[], int numRows, int numCols, int col1, int col2);

Esta função troca o conteúdo das colunas col1 e col2, os valores dos parâmetros col1 e col2 devem estar dentro do intervalo [0;numCols-1].

void MatrCopyRow(double& matr[], int numRows, int numCols, int rowToCopy, int rowToReplace);

Esta função copia o conteúdo da linha rowToCopy para a linha rowToReplace, os valores dos parâmetros rowToCopy e rowToReplace devem estar dentro do intervalo [0;numRows-1].

void MatrCopyCol(double& matr[], int numRows, int numCols, int colToCopy, int colToReplace);

Esta função copia o conteúdo da coluna colToCopy à coluna colToReplace, os valores dos parâmetros colToCopy e colToReplace devem estar dentro do intervalo [0;numCols-1].

bool MatrRowIsZero(double& matr[], int numRows, int numCols, int row, double tolerance);

Esta função verifica se a linha row é nula com o grau de precisão tolerance, se a linha for nula, o valor retornado será true.

bool MatrColIsZero(double& matr[], int numRows, int numCols, int col, double tolerance);

Esta função verifica se a coluna col é nula com o grau de precisão tolerance, se a coluna for nula, o valor retornado será true.


2.4. Funções para Verificação Geral de Condições

O grupo de funções para verificação geral de condições destina-se à melhoria da legibilidade do código.

bool MatrIsSquare(int numRows, int numCols);

Esta função verifica se a matriz das linhas numRows e colunas numCols é quadrada (ou seja, verifica se numRows=numCols). Retorna true para matrizes quadradas.

bool MatrIsElemOnMainDiagonal(int row, int col);

Esta função verifica se o elemento com os índices [row] [col] são na diagonal principal da matriz. Retorna true aos elementos na diagonal principal.

bool MatrCompatiblityCheckAdd(int numRows1, int numCols1, int numRows2, int numCols2);

Esta função verifica a compatibilidade de duas matrizes para fins de operações de dependência semelhante. As dimensões são verificadas em pares por igualdade (numRows1=numRows2 e numCols1=numCols2); true é devolvido em caso de igualdade.

bool MatrCompatiblityCheckMul(int numRows1, int numCols1, int numRows2, int numCols2);

Esta função verifica a compatibilidade de duas matrizes para fins de multiplicação, verifica se o número de colunas da primeira matriz ( numRows1 por numCols1) são iguais ao número de linhas na segunda matriz (numRows2 por numCols2). A multiplicação é possível se retornar true.


2.5. Funções de Inicialização de Conteúdo

O grupo de funções de inicialização de conteúdo da matriz destina-se a carregar as matrizes usadas com freqüência (por exemplo, nulos e matrizes de identidade). Como a memória não é alocada, as funções MatrSetSize ou MatrResize devem ser chamadas antes de chamar as funções de grupo.

void MatrLoadZero(double& matr[], int numRows, int numCols);

Essa função inicializa o array de dados matr para zeros, criando assim uma matriz nula de linhas numRows e colunas numCols.

void MatrLoadIdentity(double& matr[], int numRows, int numCols);

Esta função inicializa todos os elementos do array de dados matr para zeros, exceto para aqueles que estão na diagonal principal da matriz, a matriz inicializada de linhas numRows e colunas numCols deve ser quadrada.

void MatrLoadInRangeRandom(double& matr[], int numRows, int numCols, double rangeLowLimit, double rangeHighLimit);

Esta função inicializa o array de dados da matriz matr para de números aleatórios a partir do intervalo [rangeLowLimit;rangeHighLimit] (números aleatórios são gerados usando a função MathInRangeRandom).


2.6. Funções para Verificar as Condições por Tipo de Conteúdo

Vamos agora considerar o grupo de funções para verificar as condições por tipo de conteúdo. As funções deste grupo efetuam uma comparação com o grau de precisão da tolerance (o valor deste parâmetro não deve ser negativo) e retorna true se a condição em questão é verdadeira.

bool MatrIsZero(double& matr[], int numRows, int numCols, double tolerance);

Esta função verifica se a matriz é nula.

bool MatrIsDiagonal(double& matr[], int numRows, int numCols, double tolerance);

Esta função verifica se a matriz é diagonal, a matriz será considerada diagonal se é quadrada e todos os elementos fora da diagonal principal são iguais a zero.

bool MatrIsIdentity(double& matr[], int numRows, int numCols, double tolerance);

Esta função verifica se a matriz é identidade.

bool MatrIsSymmetric(double& matr[], int numRows, int numCols, double tolerance);

Essa função verifica se a matriz é simétrica (ou seja, a[i][j]=a[j][i] é verdadeiro para qualquer i e j).

bool MatrIsAntisymmetric(double& matr[], int numRows, int numCols, double tolerance);

Esta função verifica se a matriz é de inclinação simétrica/assimétrica (isto é, a[i][j]=-a[j][i] é verdadeiro para qualquer i e j e a[K][k]=0 é válido para qualquer k).

bool MatrEqual(double& matr1[], double& matr2[], int numRows, int numCols, double tolerance);

Esta função verifica a igualdade do element-wise entre as matrizes com as mesmas dimensões.


2.7. Funções para "Element-wise" das Operações de Escalar

Vamos prosseguir ao grupo de funções para o element-wise das operações de escalar. Este grupo é peculiar onde aqueles resultados de função não são colocados no array inicial da matriz matr, mas sim um novo array de resultado. No entanto, se o mesmo array é transmitido tanto como os parâmetros result e matr, os resultados serão colocados à matriz inicial.

void MatrAddScalar(double& matr[], int numRows, int numCols, double scalar, double& result[]);

Essa função adiciona o valor scalar para cada elemento da matriz.

void MatrSubScalar(double& matr[], int numRows, int numCols, double scalar, double& result[]);

Essa função subrai o valor scalar para cada elemento da matriz.

void MatrMulByScalar(double& matr[], int numRows, int numCols, double scalar, double& result[]);

Esta função multiplica cada elemento da matriz pelo valor scalar.

void MatrDivByScalar(double& matr[], int numRows, int numCols, double scalar, double& result[]);

Esta função divide cada elemento da matriz pelo valor scalar.


2.8. Funções para Operações Básicas com Matrizes

O grupo de operações básicas com matrizes consiste em funções para executarem as ações elementares - cálculos de soma, produto e rastreamento, bem como operações de transposição. Os resultados das operações da função (exceto MatrTrace) são devolvidos para o array resultado.

void MatrAddMatr(double& matr1[], double& matr2[], int numRows, int numCols, double& result[]);

Esta função acrescenta duas matrizes com as mesmas dimensões.

void MatrSubMatr(double& matr1[], double& matr2[], int numRows, int numCols, double& result[]);

Esta função subtrai a matriz matr2 da matriz matr1, as matrizes devem ter o mesmo tamanho.

void MatrMulMatr(
      double& matr1[], int numRows1, int numCols1,
      double& matr2[], int numRows2, int numCols2,
      double& result[], int& numRowsRes, int& numColsRes);

Esta função multiplica a matriz matr1 pela matriz matr2, as matrizes devem ser compatíveis com a multiplicação, isto é, o número de colunas (numCols1) na primeira matriz deve ser igual ao número de linhas (numRows2) na segunda matriz, o tamanho da matriz resultante é retornado em variáveis cujas referências são transmitidos nos parâmetros numRowsRes e numColsRes.

double MatrTrace(double& matr[], int numRows, int numCols);

Esta função calcula o rastreamento da matriz (soma dos elementos na diagonal), a matriz deve ser quadrada.

void MatrTranspose(double& matr[], int numRows, int numCols, double& result[], int& numRowsRes, int& numColsRes);

Esta função transpõe a matriz (troca colunas com linhas), o novo tamanho da matriz é retornado em variáveis cujas referências são transmitidas nos parâmetros numRowsRes e numColsRes.


2.9. Outras Funções

Este grupo oferece outras possibilidades, tais como: de inversão de matriz, cálculo de fileiras, determinantes, etc.

int MatrGaussianElimination(double& matr[], int numRows, int numCols, double& result[], double tolerance);

Esta função representa a implementação da eliminação de Gauss com pivoteamento. A matriz inicial matr de linhas numRows e colunas numCols é reduzida a uma forma trapezoidal (triangular), com os resultados que estão sendo colocados no array result.

O valor retornado é o número linear de linhas independentes da matriz (ou seja, a sua classificação). Uma vez que os cálculos podem levar a erros de arredondamentos na função, ela é obrigada a transmitir um valor não negativo ao parâmetro tolerance que define o grau de precisão da comparação.

bool MatrGJBatchSolve(
      double& matr[], int numRows, int numCols,
      double& rhs[], int numRowsRHS, int numColsRHS,
      double& roots[], int& numRowsRoots, int& numColsRoots,
      double tolerance
      );

Esta função representa a implementação de eliminação de Gauss-Jordan, destina-se a resolver os vários conjuntos de sistemas de equações com uma mesma matriz de sistema.

A matriz de sistema comum é transmitida na matr (array de dados), parâmetros numRows e numCols (dimensões). Um conjunto de vetores do lado direito também é transmitido como uma matriz (o parâmetro rhs), onde cada coluna representa um lado direito do sistema em consideração.

Em outras palavras, o parâmetro numRowsRHS contém o número de equações no sistema (número de linhas na matriz do sistema), enquanto o parâmetro numColsRHS contém o número de vetores à direita (número de sistemas a ser resolvido).

Os resultados retornam na forma da matriz roots das linhas numRowsRoots e colunas numColsRoots. A solução para cada sistema de equações é colocado na matriz de coluna, correspondendo a matriz de sistema em questão e a coluna com o número correspondente da matriz rhs. A função retorna true se for encontrado a solução para o conjunto de sistemas das equações.

void MatrMinor(
      double& matr[], int numRows, int numCols,
      int rowToExclude, int colToExclude,
      double& result[], int& numRowsRes, int& numColsRes);

Esta função encontra o menor da matriz na interseção da linha rowToExclude e a coluna colToExclude. Os elementos da matriz resultantes retornam no array result, enquanto as dimensões retornam em variáveis cujas referências são transmitidas nos parâmetros numRowsRes e numColsRes.

double MatrAlgebraicComplement(double& matr[], int numRows, int numCols, int elemRow, int elemCol, double tolerance);

Esta função calcula o cofator algébrico (menor com um sinal de local) para o elemento que encontra-se ma intersecção da linha elemRow e coluna elemCol. Para calcular o determinante, usamos a eliminação de Gauss (sob a forma da função MatrGaussianElimination) com o grau de precisão definido pelo parâmetro tolerance.

bool MatrInvertUsingMinors(double& matr[], int numRows, int numCols, double& result[], double tolerance);

Esta função calcula a inversão do quadrado da matriz matr usando uma matriz de união (gerada a partir de cofatores algébricos dos elementos da matriz correspondente). Complexidade assintótica do algoritmo empregado: O(n^5). A matriz de união é calculada utilizando a função MatrAlgebraicComplement (que por sua vez emprega a eliminação de Gauss) e por esta razão a função precisa transmitir um valor não negativo de parâmetro tolerance que define o grau de precisão. Os elementos da matriz resultante são colocados no array resultado. Se a inversão da matriz é calculada com sucesso (o determinante é diferente de zero), a função retorna true.

bool MatrInvertUsingGJ(double& matr[], int numRows, int numCols, double& result[], double tolerance);

Esta função calcula a inverso do quadrado dado da matriz matr por uma matriz adjacente e de identidade, ou seja, através da solução de sistemas de equações lineares N (N=numRows=numCols), usando a função MatrGJBatchSolve (a matriz do lado direito é identidad, o grau de precisão é definido por um valor não negativo do parâmetro tolerance ). Complexidade assintótica do algoritmo empregado: O(n^3). Os elementos da matriz resultante são colocados no array result. Se a inversão da matriz é calculado com sucesso (o determinante é diferente de zero), a função retorna true.

double MatrDet(double& matr[], int numRows, int numCols, double tolerance);

Esta função calcula o determinante da matriz quadrada matr, sendo reduzida a uma forma trapezoidal (triangular), para este fim usamos a eliminação de Gauss com um grau de precisão tolerance (este parâmetro deve ser não negativo). Complexidade assintótica do algoritmo: O(n^3).

double MatrDetTriang(double& matr[], int numRows, int numCols);

Esta função calcula o determinante da matriz triangular matr.

double MatrRank(double& matr[], int numRows, int numCols, double tolerance);

Esta função calcula a classificação da matriz matr, sendo reduzida a uma forma trapezoidal (triangular), para este fim usamos a eliminação de Gauss com um grau de precisão tolerance (este parâmetro deve ser não negativo). Complexidade assintótica do algoritmo: O(n^3).

double MatrRankTriang(double& matr[], int numRows, int numCols, double tolerance);

Esta função calcula a classificação da matriz matr. A matriz deve ser reduzida a uma forma trapezoidal (triangular), linha por linha (por exemplo, chamando a função MatrGaussianElimination). O valor não negativo tolerance define o grau de precisão do primeiro cálculo de linha nula.

void MatrComputeConnectedMatr(double& matr[], int numRows, int numCols, double& result[], double tolerance);

Esta função calcula uma matriz de união para a matriz quadrada matr, os elementos da matriz resultante são colocados no array result. O valor não negativo tolerance define o grau de precisão no cálculo dos cofatores algébricos.

void MatrLerpMatr(double& matr1[], double& matr2[], int numRows, int numCols, double balance, double& result[]);

Esta função executa a interpolação linear "elemento-wise" entre as matrizes matr1 e matr2 de mesmo tamanho, o parâmetro balance representa o coeficiente de interpolação linear e deve estar dentro do intervalo [0;1]. Os elementos da matriz resultante retornam no array result.


2.10. Entrada/Saída das Funções

O grupo entrada/saída das funções é destinado para o salvamento/carregamento das matrizes, bem como escrever a saída da depuração de uma matriz no registro (log).

void MatrPrint(double& matr[], int numRows, int numCols);

Esta função tem o objetivo de escrever no registro (log) a saída da depuração (guia Expert Advisors no painel do Terminal), tem como saída a matriz linha por linha, levando em consideração que o registro (log) é exibido no terminal na ordem inversa (ou seja, novas entradas aparecem na parte superior; a função imprime as linhas a partir do final por praticidade na análise visual das matrizes no registro).

void FileWriteMatr(double& matr[], int numRows, int numCols, int handle);

Esta função salva uma matriz (incluindo as suas dimensões) ao arquivo cujo manipulador é transmitido no parâmetro handle, o arquivo deve ser aberto no modo FILE_BIN|file_write.

void FileReadMatr(double& matr[], int& numRows, int& numCols, int handle);

Esta função carrega uma matriz a partir de um arquivo. Em primeiro lugar, as dimensões da matriz são lidas nas variáveis cujas referências são transmitidas nos parâmetros numRows e numCols, em seguida, o array matr é redimensionado de acordo com o tamanho da matriz, seguido pelo carregamento do conteúdo do array "matr" a partir do arquivo. O manipulador do arquivo a partir do qual os dados são lidos é transmitido no parâmetro handle; o arquivo deve ser aberto no modo FILE_BIN|file_read.

Agora que o leitor se familiarizou com as descrições das funções, podemos prosseguir para a resolução de questões práticas na utilização da biblioteca.


3. Exemplo de Uso

Vamos dar uma olhada num exemplo para criação de uma regressão polinomial sobre uma série de valores dos preços usando a biblioteca proposta.

O processo para criação de uma regressão polinomial consiste em encontrar coeficientes polinomiais: f(x)=a[0]+a[1]*x+...+a[degree]*x^degree. Isto é realizado através da resolução de um sistema de equações algébricas lineares, onde os elementos da matriz de sistema, A[degree+1][degree+1], são definidos da seguinte fórmula: A[i][j]=(x[0]^(i+j)+x[1]^(i+j)+...+x[numPoints]^(i+j))/numPoints. Enquanto os elementos do vetor lateral direito, B[degree+1][1], são definidos usando a seguinte fórmula: B[i]=(y[0]*x[0]^i+y[1]*x[1]^i+...+y[numPoints]*x[numPoints]^i)/numPoints.

Para resolver a tarefa em mãos, nós temos um script (o arquivo LibMatrixEx.mq4 anexado no artigo) que cria um polinômio e exibe no intervalo inicial e à sua direita (ou seja, extrapolação). Valores polinomiais no intervalo de extrapolação podem ser utilizados para prever a direção do movimento preço.

O script é controlado através de três linhas verticais: duas delas estão destinadas a seleção do intervalo a ser analisado, a terceira define o ponto mais à direita até que o polinômio seja exibido.

Para ativar a operação do script, você precisa arrastá-lo ao gráfico e definir os parâmetros necessários: delay - taxa de atualização do gráfico (em ms), degree - Grau de polinômio, linesMargin - distância inicial entre as linhas de controle, linesWidth - largura da linha do gráfico polinomial. Você também pode selecionar cores para as linhas de controle verticais (parâmetros colVLineInt e colVLineExt) e linhas de gráfico (parâmetros colInt e colExt).


Exemplo de operação do Script

Vamos rever a função "key" do script que lida com matrizes.

// Criando uma regressão polinomial
bool Regression(double& x[], double& y[], int numPoints, int polyDegree, double& poly[]) {
   // criando matriz de sistema
   double A[];
   int numRowsA = polyDegree + 1;
   int numColsA = polyDegree + 1;
   MatrSetSize(A, numRowsA, numColsA);
   // preenchendo a matriz
   for (int row = 0; row < numRowsA; row++) {
      for (int col = 0; col < numColsA; col++) {
         int offset = MatrIndiciesToOffset(row, col, numRowsA, numColsA);
         A[offset] = SXY(x, y, numPoints, row + col, 0);
      }
   }
   // criando um vetor lateral direito
   double B[];
   int numRowsB = polyDegree + 1;
   int numColsB = 1;
   MatrSetSize(B, numRowsB, numColsB);
   // preenchendo um vetor lateral direito
   for (row = 0; row < numRowsB; row++) {
      offset = MatrIndiciesToOffset(row, 0, numRowsB, numColsB);
      B[offset] = SXY(x, y, numPoints, row, 1);
   }
   // resolvendo sistema de equações algébricas lineares
   int numRowsX, numColsX;
   bool status =
      MatrGJBatchSolve(
         A, numRowsA, numColsA,
         B, numRowsB, numColsB,
         poly, numRowsX, numColsX,
         DEFAULT_TOLERANCE
      );
   if (!status) {
      Print("Error solving the system");
   }
   return (status);
}

A função usa 5 argumentos: Os dois primeiros são arrays x e y destinados a armazenar as coordenadas dos pontos através do qual o polinômio é plotado. O número de pontos é transmitido no parâmetro numPoints. O quarto argumento define o grau do polinômio sob consideração (que deve ser menor do que o número de pontos, pelo menos no valor igual a 1). O quinto argumento é a referência ao array que recebe os coeficientes polinomiais.

No início da função, a matriz A é criada, redimensionada e preenchida usando as fórmulas acima indicadas. Para referenciar os elementos da matriz através de índices bidimensionais, usamos a função MatrIndiciesToOffset que calcula o deslocamento unidimensional em relação ao início do array.

A coluna de vetor B é então preenchida de uma maneira semelhante. Esta é seguida por uma chamada da função MatrGJBatchSolve que resolve o sistema criado, encontrando os coeficientes polinomiais.

O resto do código verifica as posições da linha e gera o polinômio que não deve ter qualquer dificuldade ao leitor.


Conclusão

O artigo apresentou uma biblioteca para trabalhar com matrizes e discursa sobre as funções implementadas e suas peculiaridades.

O uso da biblioteca foi demonstrado com um exemplo na criação de uma regressão polinomial sobre uma série de velas (candles), nos valores de fechamento dos preços.

O código foi cuidadosamente verificado, mas pode haver erros. Se acontecer de você encontrar algum erro, por favor me avise.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1365

Arquivos anexados |
LibMatrix.zip (14.03 KB)
Lendo Feeds de Notícias RSS Via MQL4 Lendo Feeds de Notícias RSS Via MQL4
Este artigo mostra um exemplo da leitura de RSS via MQL4 utilizando as funções para análise de tags HTML. Vamos tentar fazer uma peça de trabalho que pode então ser transformada num indicador de notícias ou apenas um leitor na linguagem MQL4.
Sistema de Negociação Mecânica "Triângulo de Chuvashov's" Sistema de Negociação Mecânica "Triângulo de Chuvashov's"
Deixe-me oferecer-lhe uma visão geral e um código de programa do sistema de negociação mecânica baseado nas ideias de Stanislav Chuvashov. A construção do triângulo é baseada na intersecção de duas linhas de tendência construídas pelos fractais de alta e de baixa.
Controle Gráfico dos Parâmetros Externos dos Indicadores Controle Gráfico dos Parâmetros Externos dos Indicadores
Variáveis externas de indicadores são controladas usando uma janela especial, onde os parâmetros podem ser alterados e então o indicador é executado novamente. O inconveniente óbvio destas manipulações deu origem à necessidade de exibir os parâmetros na tela e controlar o indicador graficamente.
Expert Advisor MetaTrader 4 para Intercâmbio de Informações com o Mundo Exterior Expert Advisor MetaTrader 4 para Intercâmbio de Informações com o Mundo Exterior
Uma solução simples, universal e confiável de intercâmbio de informações entre um Expert Advisor МetaТrader 4 e o mundo exterior. Fornecedores e consumidores de informações podem estar localizados em diferentes computadores, a conexão é realizada através dos endereços IPs globais.