English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Aprendizagem de máquina: como as máquinas de vetores de suporte podem ser utilizadas nas negociações

Aprendizagem de máquina: como as máquinas de vetores de suporte podem ser utilizadas nas negociações

MetaTrader 5Negociação | 18 março 2014, 14:23
7 337 0
Josh Readhead
Josh Readhead

O que é uma máquina de vetores de suporte?

Uma máquina de vetores de suporte (SVM) é um método de aprendizagem de máquina que tenta tomar dados de entrada e classificá-los em uma entre duas categorias. Para que uma máquina de vetores de suporte seja eficaz, primeiramente é necessário utilizar um conjunto de dados de entrada e de saída de treinamento para construir o modelo de máquina de vetores de suporte que pode ser utilizado para classificação de novos dados.

Uma máquina de vetores de suporte desenvolve esse modelo tomando as entradas de treinamento, mapeando elas no espaço multidimensional e utilizando regressão para encontrar um hiperplano (um hiperplano é uma superfície em espaço de n dimensões que o separa em duas metades de espaço) que melhor separa duas classes de entradas. Uma vez que a máquina de vetores de suporte tenha sido treinada, ela é capaz de avaliar novas entradas em relação ao hiperplano divisor e classificá-las em uma entre duas categorias.

Uma máquina de vetores de suporte é essencialmente uma máquina de entrada/saída. Um usuário é capaz de inserir uma entrada e, com base no modelo desenvolvido através de treinamento, ela devolverá uma saída. O número de entradas para qualquer máquina de vetores de suporte especificada, teoricamente, varia de um a infinito. Entretanto, em termos práticos, a capacidade computacional limita a quantidade de entradas que pode ser utilizada. Se, por exemplo, N entradas são utilizadas para uma máquina de vetores de suporte específica (o valor inteiro de N pode variar de um a infinito), a máquina deve mapear cada conjunto de entradas no espaço de N dimensões e encontrar um hiperplano de N-1 dimensões que melhor separa os dados de treinamento.

Máquina de entrada/saída

Figura 1. Máquinas de vetores de suporte são máquinas de entrada/saída

A melhor forma de conceituar o funcionamento de uma máquina de vetores de suporte é considerar o caso bidimensional. Suponha que desejamos criar uma máquina de vetores de suporte de duas entradas e que retorne uma saída única que classifique o ponto de dados como pertencente a uma entre duas categorias. Podemos visualizar isso fazendo uma representação em um gráfico bidimensional como o que segue abaixo.

Hiperplano divisor

Figura 2. Esquerda: Máquina de vetores de suporte representada em gráfico bidimensional. Os círculos vermelhos e cruzes azuis são utilizados para indicar as duas classes de entradas

Figura 3. Direita: Máquina de vetores de suporte representada em gráfico bidimensional. Os círculos vermelhos e cruzes azuis são utilizados para indicar as duas classes de entradas com uma linha preta indicando o hiperplano divisor

Neste exemplo, as cruzes azuis indicam pontos de dados que pertencem à categoria 1 e os círculos vermelhos representam pontos de dados que pertencem à categoria 2. Cada um dos pontos de dados individuais possui um valor de entrada 1 único (representado por sua posição no eixo x) e um valor de entrada 2 único (representado por sua posição no eixo y) e todos esses pontos foram mapeados no espaço bidimensional.

Uma máquina de vetores de suporte é capaz de classificar dados criando um modelo desses pontos no espaço bidimensional. A máquina de vetores de suporte observa os dados no espaço bidimensional e utiliza um algoritmo de regressão para encontrar um hiperplano unidimensional (também conhecido como linha) que separa com maior precisão os dados entre suas duas categorias. Essa linha divisória é então utilizada pela máquina de vetores de suporte para classificar novos pontos de dados ou na categoria 1 ou na categoria 2.

A animação abaixo ilustra o processo de treinamento de uma nova máquina de vetores de suporte. O algoritmo iniciará fazendo uma suposição aleatória para encontrar um hiperplano divisor e reiteradamente melhorar a precisão deste hiperplano. Como você pode ver, o algoritmo inicia de forma bastante agitada, mas desacelera à medida que começa a se aproximar da solução desejada.

Algoritmo de regressão da máquina de vetores de suporte encontrando o hiperplano divisor ótimo

Figura 4. Uma animação exibindo o treinamento da máquina de vetores de suporte. O hiperplano progressivamente converge para a geometria ideal para separar as duas classes de dados

Maiores dimensões

O cenário bidimensional apresentado acima permite visualizarmos o processo de uma máquina de vetores de suporte. Entretanto, ele só é capaz de classificar um ponto de dados utilizando duas entradas. E se quisermos utilizar mais entradas? Felizmente, o algoritmo da máquina de vetores de suporte permite fazermos o mesmo em maiores dimensões, embora isso se torne muito mais difícil de conceituar.

Suponha que você deseja criar uma máquina de vetores de suporte que tome 20 entradas e possa classificar qualquer ponto de dados utilizando essas entradas ou na categoria 1 ou na categoria 2. Para fazer isso, a máquina de vetores de suporte precisa modelar os dados em um espaço de 20 dimensões e utilizar um algoritmo de regressão para encontrar um hiperplano de 19 dimensões que separe os pontos de dados em duas categorias. Isso se torna excessivamente complicado de visualizar visto que é difícil compreendermos qualquer coisa acima de 3 dimensões. Entretanto, você apenas precisa saber que isso funciona exatamente da mesma forma que o caso bidimensional.


Como funcionam as máquinas de vetores de suporte? Exemplo: é um schnick?

Imagine um cenário hipotético em que você é um pesquisador estudando um animal raro, chamado schnick, que apenas é encontrado nas profundezas do Ártico. Devido ao distanciamento desses animais, apenas uma pequena quantidade foi encontrada (vamos dizer, cerca de 5000). Como pesquisador, você está preso à pergunta... como posso identificar um schnick?

Tudo o que você tem à sua disposição são pesquisas anteriormente publicadas por estudiosos que alguma vez viram os animais. Nesses artigos, os autores descrevem determinadas características relativas aos schnicks que encontraram, ou seja, altura, peso, número de patas, etc. Mas todas essas características variam entre os artigos sem qualquer padrão discernível...

Como podemos utilizar esses dados para identificar um novo animal como um schnick?

Uma possível solução para o nosso problema é utilizar uma máquina de vetores de suporte para identificar os padrões nos dados e criar uma estrutura que pode ser utilizada para classificar os animais como schnick ou não. O primeiro passo é criar um conjunto de dados que pode ser utilizado para treinar a sua máquina de vetores de suporte para identificar schnicks. Os dados de treinamento são um conjunto de entradas e saídas correspondentes para que a máquina de vetores de suporte analise e extraia um padrão.

Assim, devemos decidir quais e quantas entradas serão utilizadas. Teoricamente, podemos ter quantas entradas desejarmos. Entretanto, isso geralmente pode levar a um treinamento lento (quanto mais entradas, maior o tempo que a máquina de vetores de treinamento leva para extrair padrões). Além disso, você quer escolher valores de entrada que tenderão a ser relativamente consistentes para todos os schnicks. Por exemplo, a altura ou o peso do animal seria um bom exemplo de entrada porque se espera que isso seja relativamente consistente para todos os schnicks. Entretanto, a idade média de um animal seria uma má escolha de entrada, porque se espera que a idade dos animais identificados varie consideravelmente.

Por essa razão, as seguintes entradas foram escolhidas:

  • Altura;
  • Peso;
  • Número de patas;
  • Número de olhos;
  • Comprimento dos braços do animal;
  • Velocidade média dos animais;
  • A frequência do chamado de acasalamento dos animais.

Com as entradas escolhidas, podemos começar a compilar nossos dados de treinamento. Dados efetivos de treinamento para uma máquina de vetores de suporte devem cumprir certos requisitos:

  • Os dados devem conter exemplos de animais que são schnicks
  • Os dados devem conter exemplos de animais que não são schnicks

Nesse caso, temos os artigos de pesquisa dos cientistas que identificaram schnicks com sucesso e listaram suas características. Assim, podemos ler os artigos e extrair os dados em relação a cada uma das entradas e alocar uma saída verdadeira ou falsa para cada um dos exemplos. Os dados de treinamento, nesse caso, poderão ser similares à tabela abaixo.

Amostras de treinamento altura [mm] peso [kg] N_pernas N_olhos L_braço [mm] veloc_média [m/s] f_chamado [Hz] Schnick (verdadeiro/falso)
Exemplo 1 1030 45 8 3 420 2,1 14000 VERDADEIRO
Exemplo 2 1010 42 8 3 450 2,2 14000 VERDADEIRO
Exemplo 3 900 40 7 6 600 6 13000 FALSO
Exemplo 4 1050 43 9 4 400 2,4 12000 VERDADEIRO
Exemplo 5 700 35 2 8 320 21 13500 FALSO
Exemplo 6 1070 42 8 3 430 2,4 12000 VERDADEIRO
Exemplo 7 1100 40 8 3 430 2,1 11000 VERDADEIRO
Exemplo N ... ... ... ... ... ... ... ...

Tabela 1. Tabela de exemplo de observações de schnick

Uma vez que reunimos os dados para todas as nossas entradas e saídas de treinamento, podemos utilizá-los para treinar nossa máquina de vetores de suporte. Durante o processo de treinamento, a máquina de vetores de suporte criará um modelo em espaço de sete dimensões que pode ser utilizado para classificar todos os exemplos de trainamento como verdadeiro ou falso. A máquina de vetores de suporte continuará a fazer isso até que obtenha um modelo que representa precisamente os dados de treinamento (dentro da tolerância de erro especificada). Quando o treinamento for finalizado, esse modelo pode ser utilizado para classificar novos pontos de dados como verdadeiros ou falsos.


A máquina de vetores de suporte realmente funciona?

Utilizando o cenário dos schnicks, escrevi um script que verifica quão bem uma máquina de vetores de suporte pode realmente identificar novos schnicks. Para fazer isso, utilizei a biblioteca da função “ferramenta de aprendizagem da máquina de vetores de suporte” cujo download pode ser feito no Mercado.

Para modelar esse cenário eficazmente, primeiro precisamos decidir quais são as reais características de um schnick. As características que considerei neste caso foram listadas na tabela abaixo. Se um animal satisfaz todos os critérios abaixo, então ele é um schnick...

Parâmetro Limite mínimo Limite máximo
altura [mm] 1000 1100
peso [kg] 40 50
N_pernas 8 10
N_olhos 3 4
L_braço [mm] 400 450
veloc_média [m/s] 2 2,5
f_chamado [Hz] 11000 15000

Tabela 2. Sumário de parâmetros que definem um schnick

Agora que definimos o nosso schnick, podemos utilizar essa definição para fazer testes com máquinas de vetores de suporte. O primeiro passo é criar uma função que seja capaz de tomar sete entradas para qualquer animal especificado e retornar a real classificação do animal, se ele é um schnick ou não. Essa função será utilizada para gerar dados de treinamento para a máquina de vetores de suporte bem como para avaliar o desempenho dela no final. Isso pode ser feito com a utilização da função abaixo:

//+------------------------------------------------------------------+
//| This function takes the observation properties of the observed 
//| animal and based on the criteria we have chosen, returns true/false whether it is a schnick
//+------------------------------------------------------------------+
bool isItASchnick(double height,double weight,double N_legs,double N_eyes,double L_arm,double av_speed,double f_call)
  {
   if(height   < 1000  || height   > 1100)  return(false);   // If the height is outside the parameters > return(false)
   if(weight   < 40    || weight   > 50)    return(false);   // If the weight is outside the parameters > return(false)
   if(N_legs   < 8     || N_legs   > 10)    return(false);   // If the N_Legs is outside the parameters > return(false)
   if(N_eyes   < 3     || N_eyes   > 4)     return(false);   // If the N_eyes is outside the parameters > return(false)
   if(L_arm    < 400   || L_arm    > 450)   return(false);   // If the L_arm  is outside the parameters > return(false)
   if(av_speed < 2     || av_speed > 2.5)   return(false);   // If the av_speed is outside the parameters > return(false)
   if(f_call   < 11000 || f_call   > 15000) return(false);   // If the f_call is outside the parameters > return(false)
   return(true);                                             // Otherwise > return(true)
  }

A próxima etapa no processo é criar uma função que pode gerar as entradas e saídas de treinamento. As entradas, neste caso, serão geradas criando números aleatórios dentro de um intervalo de definição para cada um dos sete valores de entrada. Então, para cada um dos conjuntos de entradas aleatórias geradas, a função isItASchnick() acima será usada para gerar a saída correspondente desejada. Isso é feito na função abaixo:

//+------------------------------------------------------------------+
//| This function takes an empty double array and an empty boolean array,
//| and generates the inputs/outputs to be used for training the SVM
//+------------------------------------------------------------------+ 
void genTrainingData(double &inputs[],bool &outputs[],int N)
  {
   double in[];                    // Creates an empty double array to be used for temporarily storing the inputs generated
   ArrayResize(in,N_Inputs);       // Resize the in[] array to N_Inputs
   ArrayResize(inputs,N*N_Inputs); // Resize the inputs[] array to have a size of N*N_Inputs 
   ArrayResize(outputs,N);         // Resize the outputs[] array to have a size of N 
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);      // Random input generated for height
      in[1]=    randBetween(38,52);         // Random input generated for weight
      in[2]=    randBetween(7,11);          // Random input generated for N_legs
      in[3]=    randBetween(3,4.2);         // Random input generated for N_eyes
      in[4]=    randBetween(380,450);       // Random input generated for L_arms
      in[5]=    randBetween(2,2.6);         // Random input generated for av_speed
      in[6]=    randBetween(10500,15500);   // Random input generated for f_call
      ArrayCopy(inputs,in,i*N_Inputs,0,N_Inputs);                         // Copy the new random inputs generated into the training input array
      outputs[i]=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); // Assess the random inputs and determine if it is a schnick
     }
  }
//+------------------------------------------------------------------+
//| This function is used to create a random value between t1 and t2
//+------------------------------------------------------------------+ 
double randBetween(double t1,double t2)
  {
   return((t2-t1)*((double)MathRand()/(double)32767)+t1);
  }

Agora que temos um conjunto de entradas e saídas de treinamento, é hora de criar nossas máquinas de vetores de suporte utilizando a "ferramenta de aprendizagem da máquina de vetores de suporte" disponível no Mercado. Uma vez que uma nova máquina de vetores de suporte tenha sido criado, é necessário transferir as entradas e saídas de treinamento para ela e executar o treinamento.

void OnStart()
  {
   double inputs[];              // Empty double array to be used for creating training inputs
   bool   outputs[];             // Empty bool array to be used for creating training inputs
   int    N_TrainingPoints=5000; // Defines the number of training samples to be generated
   int    N_TestPoints=5000;     // Defines the number of samples to be used when testing

   genTrainingData(inputs,outputs,N_TrainingPoints); //Generates the inputs and outputs to be used for training the SVM

   int handle1=initSVMachine();             // Initializes a new support vector machine and returns a handle
   setInputs(handle1,inputs,7);             // Passes the inputs (without errors) to the support vector machine
   setOutputs(handle1,outputs);             // Passes the outputs (without errors) to the support vector machine
   setParameter(handle1,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5%
   training(handle1);                       // Trains the support vector machine using the inputs/outputs passed
  }

Agora temos uma máquina de vetores de suporte que foi treinada com êxito para a identificação de schnicks. Para verificar isso, podemos testar a máquina de vetores de suporte final pedindo que ela classifique novos pontos de entrada. Isso é feito primeiramente através da geração de entradas aleatórias e, após, pelo uso da função isItASchnick() para determinar se essas entradas correspondem a um schnick real e então pelo uso da máquina de vetores de suporte para classificar as entradas e determinar se o resultado previsto corresponde ao resultado real. Isso é feito na função abaixo:

//+------------------------------------------------------------------+
//| This function takes the handle for the trained SVM and tests how
//| successful it is at classifying new random inputs
//+------------------------------------------------------------------+ 
double testSVM(int handle,int N)
  {
   double in[];
   int atrue=0;
   int afalse=0;
   int N_correct=0;
   bool Predicted_Output;
   bool Actual_Output;
   ArrayResize(in,N_Inputs);
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);      // Random input generated for height
      in[1]=    randBetween(38,52);         // Random input generated for weight
      in[2]=    randBetween(7,11);          // Random input generated for N_legs
      in[3]=    randBetween(3,4.2);         // Random input generated for N_eyes
      in[4]=    randBetween(380,450);       // Random input generated for L_arms
      in[5]=    randBetween(2,2.6);         // Random input generated for av_speed
      in[6]=    randBetween(10500,15500);   // Random input generated for f_call
      Actual_Output=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); // Uses the isItASchnick fcn to determine the actual desired output
      Predicted_Output=classify(handle,in);                                  // Uses the trained SVM to return the predicted output.
      if(Actual_Output==Predicted_Output)
        {
         N_correct++;   // This statement keeps count of the number of times the predicted output is correct.
        }
     }

   return(100*((double)N_correct/(double)N));   // Returns the accuracy of the trained SVM as a percentage
  }

Recomendo experimentar os valores dentro das funções acima para ver como é o desempenho da máquina de vetores de suporte sob condições diferentes.


Por que a máquina de vetores de suporte é tão útil?

O benefício de utilizar uma máquina de vetores de suporte para extrair um padrão complexo dos dados é que não é necessário um conhecimento prévio acerca do comportamento dos dados. Uma máquina de vetores de suporte é capaz de analisar os dados e extrair somente discernimentos e relações. Dessa forma, ela funciona de maneira similar a uma caixa preta, recebendo entradas e gerando uma saída que pode ser muito útil para encontrar padrões em dados que são muito complexos e não óbvios.

Uma das melhores características das máquinas de vetores de suporte é que elas são capazes de lidar muito bem com erros e ruídos nos dados. Elas são geralmente capazes de perceber o padrão de fundo nos dados e filtrar valores de dados atípicos e outras complexidades. Considere o seguinte cenário: ao fazer a sua pesquisa sobre schnicks, você encontra diversos artigos científicos que descrevem esses animais com características excessivamente diferentes (tal como um schnick de 200 kg e 15000mm de altura).

Erros como esse podem levar a distorções no seu modelo de schnick, o que possivelmente poderia fazer com que você cometesse um erro ao classificar novas descobertas de schnick. O benefício da máquina de vetores de suporte é que ela desenvolverá um modelo que concorda com o padrão de fundo em vez de um modelo que engloba todos os pontos de dados de treinamento. Isso é feito através da definição de um certo nível de erro no modelo para permitir que a máquina de vetores de treinamento ignore quaisquer erros nos dados.

No caso da máquina de vetores de suporte dos schnicks, se permitirmos uma tolerância de erro de 5%, o treinamento apenas tentará desenvolver um modelo que concorda com 95% dos dados de treinamento. Isso pode ser útil porque permite que o treinamento ignore o pequeno percentual de valores atípicos.

Podemos investigar essa propriedade da máquina de vetores de suporte mais a fundo ao modificar nosso script de schnicks. A função abaixo foi adicionada para introduzir erros aleatórios deliberados em nosso conjunto de dados de treinamento. Esta função selecionará pontos de treinamento aleatoriamente e substituir as entradas e saída correspondentes com variáveis aleatórias.

//+------------------------------------------------------------------+
//| This function takes the correct training inputs and outputs generated
//| and inserts N random errors into the data
//+------------------------------------------------------------------+ 
void insertRandomErrors(double &inputs[],bool &outputs[],int N)
  {
   int    nTrainingPoints=ArraySize(outputs); // Calculates the number of training points
   int    index;                              // Creates new integer 'index'
   bool   randomOutput;                       // Creates new bool 'randomOutput'
   double in[];                               // Creates an empty double array to be used for temporarily storing the inputs generated
   ArrayResize(in,N_Inputs);                  // Resize the in[] array to N_Inputs
   for(int i=0;i<N;i++)
     {
      in[0]=    randBetween(980,1120);        // Random input generated for height
      in[1]=    randBetween(38,52);           // Random input generated for weight
      in[2]=    randBetween(7,11);            // Random input generated for N_legs
      in[3]=    randBetween(3,4.2);           // Random input generated for N_eyes
      in[4]=    randBetween(380,450);         // Random input generated for L_arms
      in[5]=    randBetween(2,2.6);           // Random input generated for av_speed
      in[6]=    randBetween(10500,15500);     // Random input generated for f_call

      index=(int)MathRound(randBetween(0,nTrainingPoints-1)); // Randomly chooses one of the training inputs to insert an error
      if(randBetween(0,1)>0.5) randomOutput=true;             // Generates a random boolean output to be used to create an error
      else                     randomOutput=false;

      ArrayCopy(inputs,in,index*N_Inputs,0,N_Inputs);         // Copy the new random inputs generated into the training input array
      outputs[index]=randomOutput;                            // Copy the new random output generated into the training output array
     }
  }

Esta função permite introduzirmos erros deliberados em nossos dados de treinamento. Utilizando esses dados cheios de erros, podemos criar e treinar uma nova máquina de vetores de suporte e comparar o seu desempenho com o da máquina original.

void OnStart()
  {
   double inputs[];              // Empty double array to be used for creating training inputs
   bool   outputs[];             // Empty bool array to be used for creating training inputs
   int    N_TrainingPoints=5000; // Defines the number of training samples to be generated
   int    N_TestPoints=5000;     // Defines the number of samples to be used when testing

   genTrainingData(inputs,outputs,N_TrainingPoints); // Generates the inputs and outputs to be used for training the svm

   int handle1=initSVMachine();             // Initializes a new support vector machine and returns a handle
   setInputs(handle1,inputs,7);             // Passes the inputs (without errors) to the support vector machine
   setOutputs(handle1,outputs);             // Passes the outputs (without errors) to the support vector machine
   setParameter(handle1,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5%
   training(handle1);                       // Trains the support vector machine using the inputs/outputs passed

   insertRandomErrors(inputs,outputs,500);  // Takes the original inputs/outputs generated and adds random errors to the data

   int handle2=initSVMachine();             // Initializes a new support vector machine and returns a handle
   setInputs(handle2,inputs,7);             // Passes the inputs (with errors) to the support vector machine
   setOutputs(handle2,outputs);             // Passes the outputs (with errors) to the support vector machine
   setParameter(handle2,OP_TOLERANCE,0.05); // Sets the error tolerance parameter to <5%
   training(handle2);                       // Trains the support vector machine using the inputs/outputs passed

   double t1=testSVM(handle1,N_TestPoints); // Tests the accuracy of the trained support vector machine and saves it to t1
   double t2=testSVM(handle2,N_TestPoints); // Tests the accuracy of the trained support vector machine and saves it to t2

   Print("The SVM accuracy is ",NormalizeDouble(t1,2),"% (using training inputs/outputs without errors)");
   Print("The SVM accuracy is ",NormalizeDouble(t2,2),"% (using training inputs/outputs with errors)");
   deinitSVMachine();                       // Cleans up all of the memory used in generating the SVM to avoid memory leak
  }

Quando o script é executado, ele produz os seguintes resultados no Registro do Expert. Dentro de um conjunto de dados de treinamento com 5000 pontos de treinamento, foi possível introduzir 500 erros aleatórios. Ao comprar o desempenho dessa máquina de vetores de suporte cheia de erros com a máquina original, o desempenho apenas foi reduzido em <1%. Isso acontece porque a máquina de vetores de suporte é capaz de ignorar os valores atípicos do conjunto de dados durante o treinamento e ainda assim é capaz de produzir um modelo impressivamente exato dos dados verdadeiros. Isso sugere que as máquinas de vetores de suporte podem ser potencialmente uma ferramenta mais útil para extrair padrões e discernimentos complexos de conjuntos de dados com ruídos.

Registro do Expert

Figura 5. O registro do Expert resultante após a execução do script "Schnick" no MetaTrader 5.


Versões de demonstração

Uma versão completa do código acima pode ser baixada na Base de Códigos, entretanto, esse script somente poderá ser executado em seu terminal se você tiver comprado uma versão completa da ferramenta de aprendizagem da máquina de vetores de suporte do Mercado. Se você apenas baixou uma versão de demonstração dessa ferramenta, você estará limitado ao uso da ferramenta através do provador de estratégia. Para permitir o teste do código "Schnick" utilizando a versão de demonstração da ferramenta, eu reescrevi uma cópia do script em um Expert Advisor que pode ser implementado utilizando o provador de estratégia. Essas duas versões do código podem ser baixadas através dos links abaixo:

  • Versão completa - Utilizando um Script que é implementado no terminal MetaTrader 5 (requer uma versão comprada da ferramenta de aprendizagem da máquina de vetores de suporte)

  • Versão de demonstração- Utilizando um Expert Advisor que é implementado no provador de estratégia do MetaTrader 5 (requer apenas uma versão de demonstração da ferramenta de aprendizagem da máquina de vetores de suporte)


Como as máquinas de vetores de suporte podem ser utilizadas no Mercado?

Reconhecidamente, o exemplo dos schnicks discutido acima é muito simples. Entretanto, há diversas semelhanças que podem ser encontradas entre esse exemplo e o uso de máquinas de vetores de suporte para análise técnica de mercado.

A análise técnica está fundamentalmente relacionada ao uso de dados históricos de mercado para prever movimentos futuros de preço. Da mesma forma que em nosso exemplo dos schnicks, estávamos utilizando observações feitas por cientistas anteriores para predizer se um novo animal era um schnick ou não. Além disso, o mercado está infestado de ruídos, erros e valores estatísticos atípicos que fazem com que o uso de uma máquina de vetores de suporte seja um conceito interessante.

A base para o número significativo de abordagens de negociação de análise técnica envolve os seguintes passos:

  1. Monitoramento de diversos indicadores.
  2. Identificação de quais condições para cada indicador estão correlacionadas a uma negociação potencialmente exitosa.
  3. Observar cada um dos indicadores e avaliar quando todos eles (ou a maioria deles) estão sinalizando uma negociação.

É possível adotar uma abordagem parecida para utilizar máquinas de vetores de suporte para sinalizar novas negociações de maneira similar. A ferramenta de aprendizagem de máquina de vetores de suporte foi desenvolvida levando-se isso em consideração. Uma descrição completa de como utilizar essa ferramenta pode ser encontrada no Mercado, razão pela qual apenas apresentarei um breve resumo. O processo de utilização dessa ferramenta é o seguinte:

Diagrama de blocos

Figura 6. O diagrama de blocos que exibe o processo de implementação da ferramenta máquina de vetores de suporte em um Expert Advisor

Antes de começar a utilizar a ferramenta de aprendizagem da máquina de vetores de suporte, é importante entender primeiro como as entradas e saídas de treinamento são geradas.

Como são geradas as entradas de treinamento?

Então, os indicadores que você deseja utilizar como entradas já foram inicializados, assim como a sua nova máquina de vetores de suporte. O próximo passo é transferir os handles do indicador para a sua nova máquina de vetores de suporte e instruí-la sobre como gerar os dados de treinamento. Isso é feito chamando a função setIndicatorHandles(). Essa função permite que você transfira os handles dos indicadores inicializados para a máquina de vetores de suporte. Isso é feito através da transferência de um array de inteiros contendo os handles. As duas outras entradas para essa função são o valor do deslocamento e o número de pontos de dados.

O valor do deslocamento indica o deslocamento entre a barra atual e a barra inicial que será utilizado para a geração das entradas de treinamento e o número de pontos de treinamento (indicado por N) determina o tamanho dos seus dados de treinamento. O diagrama abaixo ilustra como utilizar esses valores. Um valor do deslocamento igual a 4 e um valor N igual a 6 determinará que a máquina de vetores de treinamento apenas utilize as barras capturadas no quadrado branco para gerar as entradas e saídas de treinamento. De maneira similar, um valor do deslocamento igual a 8 e um valor N igual a 8 determinará que a máquina de vetores de treinamento apenas utilize as barras capturadas no quadrado azul para gerar as entradas e saídas de treinamento.

Uma vez que a função setIndicatorHandles() tenha sido chamada, é possível chamar a função genInputs(). Essa função utilizará os handles do indicador para gerar um array de dados de entrada que serão utilizados para o treinamento.

Figura 7. Gráfico de candle ilustrando os valores do Deslocamento e N

Figura 7. Gráfico de candle ilustrando os valores do Deslocamento e N


Como são geradas as saídas de treinamento?

As saídas de treinamento são geradas através da simulação de negociações hipotéticas com base em dados históricos de preços e determinação se essas negociações teriam sido ou não exitosas. Para fazer isso, há alguns parâmetros que são utilizados para instruir a ferramenta de aprendizagem da máquina de vetores de suporte sobre como avaliar uma negociação hipotética como exitosa ou não.

A primeira variável é OP_TRADE. O valor dela pode ser BUY (comprar) ou SELL (vender) e corresponderá ou a negociações de compra ou de venda. Se o valor for BUY, então, ao gerar saídas, a máquina apenas procurará o potencial êxito das negociações de compra hipotéticas. Alternativamente, se o valor for SELL, então, ao gerar saídas, a máquina apenas procurará o potencial êxito das negociações de venda hipotéticas.

Os próximos valores utilizados para essas negociações hipotéticas são Stop Loss e Take Profit. Os valores são estabelecidos em bipes e estabelecerão a parada e os níveis limites para cada uma das negociações hipotéticas.

O parâmetro final é a duração da negociação. Essa variável é medida em horas e assegurará que apenas as negociações que sejam finalizadas dentro dessa duração máxima sejam consideradas exitosas. A razão para incluir essa variável é evitar que a máquina de vetores de suporte sinalize negociações em mercado diagonal de movimento lento.


Considerações a serem feitas durante a escolha das entradas

É importante refletir sobre a seleção de entradas ao implementar máquinas de vetores de suporte em suas negociações. Da mesma forma que no exemplo dos schnicks, é importante escolher uma entrada que apresente semelhança ao longo de diferentes incidências. Por exemplo, você pode querer utilizar uma média móvel como entrada. Entretanto, porque o preço médio de longo prazo tende a mudar expressivamente ao longo do tempo, uma média móvel isoladamente poderá não ser a melhor entrada a ser utilizada. Isso se dá porque não haverá qualquer semelhança significativa entre o valor da média móvel de hoje e os valores de média móvel de seis meses atrás.

Suponha que estamos negociando EURUSD e utilizando uma máquina de vetores de suporte com uma entrada de média móvel para assinalar negociações de "compra". Vamos dizer que o preço atual seja 1,10. Porém, ela está gerando dados de treinamento de seis meses atrás, quando o preço era 0,55. Ao treinar a máquina de vetores de suporte, o padrão que ela encontra apenas poderá levar à sinalização de uma negociação quando o preço é próximo de 0,55, visto que esse é o único dado que ela conhece. Assim, a sua máquina de vetores de suporte nunca poderá sinalizar uma negociação até que o preço caia novamente para 0,55.

Em vez disso, uma entrada melhor que pode ser utilizada para uma máquina de vetores de entrada poderá ser um MACD ou um oscilador similar, visto que o valor do MACD independe do nível de preço médio e apenas sinaliza movimento relativo. Recomendo que você faça testes com isso para analisar o que produz os melhores resultados para você.

Outra consideração a ser feita durante a escolha de entradas é assegurar que a máquina de vetores de suporte possua uma imagem adequada de um indicador para sinalizar uma nova negociação. Você pode descobrir, por experiência de negociação própria, que um MACD é apenas útil quando você possui as últimas cinco barras para observações, visto que isso mostrará uma tendência. Uma barra única do MACD pode ser inútil isoladamente, a menos que você possa determinar se ela está subindo ou descendo. Dessa forma, poderá ser necessário transferir algumas últimas barras do indicador MACD para a máquina de vetores de suporte. Há duas maneiras possíveis de fazer isso:

  1. Você pode criar um novo indicador personalizado que utiliza as últimas cinco barras do indicador MACD para calcular uma tendência como um valor único. Esse indicador personalizado pode então ser transferido à máquina de vetor de suporte como uma entrada única, ou

  2. Você pode utilizar as últimas cinco barras do indicador MACD na máquina de vetores de suporte como cinco entradas separadas. A forma de fazer isso é inicializar cinco instâncias diferentes do indicador MACD. Cada um dos indicadores pode ser inicializado com um desvio diferente em relação à barra atual. Então os cinco handles dos indicadores distintos podem ser transferidos para a máquina de vetores de suporte. Deve-se destacar que a opção 2 tenderá a causar maiores tempos de execução para o seu Expert Advisor. Quanto mais entradas você tiver, mais tempo levará para o êxito do treinamento.


Implementação de máquinas de vetores de suporte em Expert Advisor

Eu preparei um Expert Advisor que é um exemplo de como alguém poderia utilizar potencialmente as máquinas de vetores de suporte em suas próprias negociações (uma cópia dele pode ser baixada neste link https://www.mql5.com/pt/code/1229). Espero que o Expert Advisor permita que você experimente as máquinas de vetores de suporte. Recomendo que você copie/altere/modifique o Expert Advisor para que se adapte ao seu próprio estilo de negociação. O EA funciona da seguinte forma:

  1. Duas novas máquinas de vetores de suporte são criadas utilizando a biblioteca svMachineTool. Uma é configurada para sinalizar novas negociações de "compra" e a outra é configurada para sinalizar novas negociações de "venda".

  2. Sete indicadores padrão são inicializados com cada um dos seus handles armazenados em um array de inteiros (Nota: qualquer combinação de indicadores pode ser utilizada como entrada, eles apenas precisam ser transferidos à SVM em um array de inteiros único).

  3. O array de handles do indicador é transferido as novas máquinas de vetores de suporte.

  4. Com a utilização de handles de indicador e outros parâmetros, os dados de preço históricos são utilizados para gerar entradas e saídas precisas que serão utilizadas para treinar as máquinas de vetores de suporte.

  5. Uma vez que todas as entradas e saídas tenham sido geradas, ambas as máquinas de vetores de suporte são treinadas.

  6. As máquinas de vetores de suporte são utilizadas no EA para sinalizar novas negociações de "compra" e "venda". Quando uma nova negociação de "compra" ou "venda" é sinalizada, a negociação é aberta juntamente com ordens manuais de Stop Loss e Take Profit.

A inicialização e treinamento da máquina de vetores de suporte são executados dentro da função onInit(). Para referência, esse segmento do EA svTrader foi incluído abaixo com notas.

#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#property indicator_buffers 7

//+---------Support Vector Machine Learning Tool Functions-----------+
//| The following #import statement imports all of the support vector
//| machine learning tool functions into the EA for use. Please note, if
//| you do not import the functions here, the compiler will not let you
//| use any of the functions
//+------------------------------------------------------------------+
#import "svMachineTool.ex5"
enum ENUM_TRADE {BUY,SELL};
enum ENUM_OPTION {OP_MEMORY,OP_MAXCYCLES,OP_TOLERANCE};
int  initSVMachine(void);
void setIndicatorHandles(int handle,int &indicatorHandles[],int offset,int N);
void setParameter(int handle,ENUM_OPTION option,double value);
bool genOutputs(int handle,ENUM_TRADE trade,int StopLoss,int TakeProfit,double duration);
bool genInputs(int handle);
bool setInputs(int handle,double &Inputs[],int nInputs);
bool setOutputs(int handle,bool &Outputs[]);
bool training(int handle);
bool classify(int handle);
bool classify(int handle,int offset);
bool classify(int handle,double &iput[]);
void  deinitSVMachine(void);
#import

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>

//+-----------------------Input Variables----------------------------+
input int            takeProfit=100;      // TakeProfit level measured in pips
input int            stopLoss=150;        // StopLoss level measured in pips
input double         hours=6;             // The maximum hypothetical trade duration for calculating training outputs.
input double         risk_exp=5;          // Maximum simultaneous order exposure to the market
input double         Tolerance_Value=0.1; // Error Tolerance value for training the SVM (default is 10%)
input int            N_DataPoints=100;    // The number of training points to generate and use.

//+---------------------Indicator Variables--------------------------+
//| Only the default indicator variables have been used here. I
//| recommend you play with these values to see if you get any 
//| better performance with your EA.                    
//+------------------------------------------------------------------+
int bears_period=13;
int bulls_period=13;
int ATR_period=13;
int mom_period=13;
int MACD_fast_period=12;
int MACD_slow_period=26;
int MACD_signal_period=9;
int Stoch_Kperiod=5;
int Stoch_Dperiod=3;
int Stoch_slowing=3;
int Force_period=13;

//+------------------Expert Advisor Variables------------------------+
int         tickets[];
bool        Opn_B,Opn_S;
datetime    New_Time;
int         handleB,handleS;
double      Vol=1;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   New_Time=0;
   int handles[];ArrayResize(handles,7);
//+------------------------------------------------------------------+
//| The following statements are used to initialize the indicators to be used for the support 
//| vector machine. The handles returned are stored to an int[] array. I have used standard 
//| indicators in this case however, you can also you custom indicators if desired
//+------------------------------------------------------------------+
   handles[0]=iBearsPower(Symbol(),0,bears_period);
   handles[1]=iBullsPower(Symbol(),0,bulls_period);
   handles[2]=iATR(Symbol(),0,ATR_period);
   handles[3]=iMomentum(Symbol(),0,mom_period,PRICE_TYPICAL);
   handles[4]=iMACD(Symbol(),0,MACD_fast_period,MACD_slow_period,MACD_signal_period,PRICE_TYPICAL);
   handles[5]=iStochastic(Symbol(),0,Stoch_Kperiod,Stoch_Dperiod,Stoch_slowing,MODE_SMA,STO_LOWHIGH);
   handles[6]=iForce(Symbol(),0,Force_period,MODE_SMA,VOLUME_TICK);

//----------Initialize, Setup and Training of the Buy-Signal support vector machine----------
   handleB=initSVMachine();                             // Initializes a new SVM and stores the handle to 'handleB'
   setIndicatorHandles(handleB,handles,0,N_DataPoints); // Passes the initialized indicators to the SVM with the desired offset 
                                                        // and number of data points
   setParameter(handleB,OP_TOLERANCE,Tolerance_Value);  // Sets the maximum error tolerance for SVM training
   genInputs(handleB);                                  // Generates inputs using the initialized indicators
   genOutputs(handleB,BUY,stopLoss,takeProfit,hours);   // Generates the outputs based on the desired parameters for taking hypothetical trades

//----------Initialize, Setup and Training of the Sell-Signal support vector machine----------
   handleS=initSVMachine();                             // Initializes a new SVM and stores the handle to 'handleS'
   setIndicatorHandles(handleS,handles,0,N_DataPoints); // Passes the initialized indicators to the SVM with the desired offset 
                                                        // and number of data points
   setParameter(handleS,OP_TOLERANCE,Tolerance_Value);  // Sets the maximum error tolerance for SVM training
   genInputs(handleS);                                  // Generates inputs using the initialized indicators
   genOutputs(handleS,SELL,stopLoss,takeProfit,hours);  // Generates the outputs based on the desired parameters for taking hypothetical trades
//----------
   training(handleB);   // Executes training on the Buy-Signal support vector machine
   training(handleS);   // Executes training on the Sell-Signal support vector machine   
   return(0);
  }


Negociação avançada com máquina de vetores de suporte

Uma capacidade adicional foi integrada à ferramenta de aprendizagem da máquina de vetores de suporte para os usuários mais avançados. A ferramenta permite que os usuários transfiram seus próprios dados de entrada e saída personalizados (como no exemplo dos schnicks). Isso permite que você projete seus próprios critérios personalizados para as entradas e saídas da máquina de vetores de suporte e transfira esses dados manualmente para treiná-la. Isso garante a possibilidade de utilizar máquinas de vetores de suporte em qualquer aspecto de suas negociações.

Não é apenas possível utilizar máquinas de vetores de suporte para sinalizar novas negociações, mas também para sinalizar o fechamento de negociações, gerenciamento de dinheiro, novos indicadores avançados, etc. Entretanto, para assegurar que você não receba erros, é importante compreender como essas entradas e saídas devem ser estruturadas.

Entradas: As entradas são transferidas à SVM com um array unidimensional de valores duplos. Por favor, note que qualquer entrada que você criar deverá ser transferida como um valor duplo. Booleanos, inteiros, etc. - tudo deverá ser convertido em valor duplo antes de ser transferido para a máquina de vetores de suporte. As entradas são requeridas no formato a seguir. Por exemplo, suponha que estamos transferindo entradas com 3 entradas x 5 pontos de treinamento. Para obter isso, nosso array duplo deve ter 15 unidades de comprimento, no formato:

| A1 | B1 | C1 | A2 | B2 | C2 | A3 | B3 | C3 | A4 | B4 | C4 | A5 | B5 | C5 |

Também é necessário transferir um valor para o número de entradas. Nesse caso, N_Inputs=3.

Saídas: as saídas são transferidas em um array de valores booleanos. Esses valores booleanos são a saída desejada da SVM correspondente a cada um dos conjuntos de entradas transferidos. Da mesma forma que o exemplo acima, considere que tenhamos 5 pontos de treinamento. Nesse caso, transferiremos um array booleano de valores de saída de 5 unidades de comprimento.

Notas gerais:

  • Ao gerar suas próprias entradas e saídas, certifique-se de que o comprimento de seus arrays sejam compatíveis com os valores que você está transferindo. Se eles não forem correspondentes, um erro será gerado para notificar você sobre a discrepância. Por exemplo, se transferimos N_Inputs=3, e as entradas são um array de comprimento 16, um erro será lançado (visto que um valor N_inputs igual a 3 significará que o comprimento de qualquer array de entrada deverá ser um múltiplo de 3). Da mesma forma, certifique-se de que o número de conjuntos de entradas e o número de saídas transferidas sejam iguais. Novamente, se você tiver N_Inputs=3, comprimento de entradas igual a 15 e comprimento de saídas igual a 6, outro erro será lançado (visto que você possui 5 conjuntos de entradas e 6 saídas).

  • Tente assegurar que você tenha variação suficiente em suas saídas de treinamento. Por exemplo, se você transfere 100 pontos de treinamento, o que significa um array de saída de comprimento 100 e todos os valores são falsos, com apenas um valor verdadeiro, então a diferenciação entre o vaso verdadeiro e os casos falsos não é o suficiente. Isso tenderá a fazer com que o treinamento da máquina seja muito rápido, mas a solução final será muito fraca. Um conjunto de treinamento mais diverso geralmente resultará em uma SVM mais eficaz.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/584

Arquivos anexados |
schnick.mq5 (10.8 KB)
schnick_demo.mq5 (11.39 KB)
Fundamentos básicos da programação MQL5: strings Fundamentos básicos da programação MQL5: strings
O artigo cobre tudo que você pode fazer com strings no MQL5. Deve ser de interesse principalmente para programadores MQL5 novatos, enquanto os desenvolvedores mais experientes terão uma boa oportunidade para resumir e sistematizar seu conhecimento.
Alterar os parâmetros do Expert Advisor instantaneamente a partir do painel de usuário Alterar os parâmetros do Expert Advisor instantaneamente a partir do painel de usuário
Este artigo fornece um pequeno exemplo demonstrando a implementação de um Expert Advisor em que os parâmetros podem ser controlados a partir do painel de usuário. Quando mudar os parâmetros para "rápidos", o Expert Advisor escreve os valores obtidos a partir do painel de informações para um arquivo para ler futuramente o arquivo e exibe de acordo no painel. Este artigo pode ser relevante para aqueles que negociam em modo manual ou semi-automático.
Como testar um robô de negociação antes da compra Como testar um robô de negociação antes da compra
A compra de um robô de negociação no Mercado MQL5 apresenta uma vantagem distinta em relação a todas as outras opções similares - um sistema automatizado oferecido pode ser inteiramente testado diretamente no terminal MetaTrader 5. Antes da compra, um Expert Advisor pode e deve ser cuidadosamente executado em todos os modos não favoráveis no Strategy Tester integrado para que você entenda completamente o sistema.
Fundamentos básicos da programação MQL5: arrays Fundamentos básicos da programação MQL5: arrays
Juntamente com as variáveis e funções, os arrays são partes integrais de quase todas as linguagens de programação. O artigo deve ser de interesse principalmente para programadores MQL5 novatos, enquanto os desenvolvedores mais experientes terão uma boa oportunidade para resumir e sistematizar seu conhecimento.