Tutorial da Rede Neural FANN2MQL
Em primeiro lugar:
Por favor, instale a Biblioteca fann2MQL, pode ser baixado Aqui.
Introdução
Até agora, houve apenas um exemplo de como usar a Biblioteca Fann2MQL, onde os traders podem usar a Biblioteca de Código Fonte Aberto da Rede Neural "FANN" em seus códigos de MQL.
Mas o exemplo escrito pelo criador da Biblioteca Fann2MQL não é fácil de entender. Não é para iniciantes.
Então eu escrevi um outro exemplo, uma maneira mais fácil em seu conceito e totalmente comentada.
Não está diretamente relacionado com a negociação e não vai utilizar qualquer dado financeiro. É um exemplo simples de aplicação estática.
Neste exemplo, nós vamos ensinar uma rede neural simples para reconhecer um padrão simples:
O padrão a ser ensinado será composto por 3 números: a, b e c.
Se a < b && b < c então a expectativa de saída = 1
Se a < b && b > c então a expectativa de saída = 0
Se a > b && b > c então a expectativa de saída = 0
Se a > b && b < c então a expectativa de saída = 1
Você pode raciocinar com esses números como sendo coordenadas de vetor (vetor indo para cima ou para baixo), por exemplo, ou a direção do mercado. Neste caso, o padrão pode ser interpretado como:
UP UP = UP
UP DOWN = DOWN
DOWN DOWN = DOWN
DOWN UP = UP
Primeiro, vamos criar uma rede neural.
Em seguida, vamos mostrar a rede alguns exemplos de padrões para que ela possa aprender e deduzir as regras.
Finalmente, vamos mostrar a rede novos padrões que ela nunca viu e perguntar-lhe quais são as suas conclusões. Se ele entendeu as regras, então estará capacitada a reconhecer estes padrões.
o código comentado:
// Nós incluímos a biblioteca Fann2MQl #include <Fann2MQL.mqh> #property copyright "Copyright © 2009, Julien Loutre" #property link "http://www.thetradingtheory.com" #property indicator_separate_window #property indicator_buffers 0 // o número total de camadas, aqui, há uma camada de entrada, // 2 camadas ocultas e uma camada de saída = 4 camadas. int nn_layer = 4; int nn_input = 3; // Número de neurônios de entrada. Nosso teste padrão é feito de 3 números, // significando 3 neurônios de entrada. int nn_hidden1 = 8; // número de neurônios na primeira camada oculta int nn_hidden2 = 5; // número na segunda camada oculta int nn_output = 1; // número de saídas // trainingData[][] conterá os exemplos // Vamos usar para ensinar as regras aos neurônios. double trainingData[][4]; // IMPORTANTE! size = nn_input + nn_output int maxTraining = 500; // número máximo de tempo do treinamento, // os neurônios com alguns exemplos double targetMSE = 0.002; // o MSE (Mean-Square Error /Erro Quadrático Médio) dos neurônios, deveríamos // obter no máximo (você vai entender isso mais abaixo no código) int ann; // Esta variável será o identificador da rede neuronal. // Quando o indicador é removido, temos de eliminar todas as redes neurais // a partir da memória do computador. int deinit() { f2M_destroy_all_anns(); return(0); } int init() { int i; double MSE; Print("=================================== START EXECUTION ================================"); IndicatorBuffers(0); IndicatorDigits(6); // Nós redimensionamos o array trainingData, para que possamos usá-lo. // Nós vamos mudar o seu tamanho em um de cada vez. ArrayResize(trainingData,1); Print("##### INIT #####"); // Criamos novas redes de neurônios ann = f2M_create_standard(nn_layer, nn_input, nn_hidden1, nn_hidden2, nn_output); // Vamos verificar se foi criado com sucesso. 0 = OK, -1 = erro debug("f2M_create_standard()",ann); // Nós definimos a função de ativação. Não se preocupe com isso. Apenas faça. f2M_set_act_function_hidden (ann, FANN_SIGMOID_SYMMETRIC_STEPWISE); f2M_set_act_function_output (ann, FANN_SIGMOID_SYMMETRIC_STEPWISE); // Alguns estudos mostram que estatisticamente os melhores resultados são alcançados usando este intervalo; // mas você pode tentar diferente e ver se fica melhor ou o pior f2M_randomize_weights (ann, -0.77, 0.77); // Eu só imprimi no console o número de neurônios de entrada e saída. // Apenas para verificar. Apenas para fins de depuração. debug("f2M_get_num_input(ann)",f2M_get_num_input(ann)); debug("f2M_get_num_output(ann)",f2M_get_num_output(ann)); Print("##### REGISTER DATA #####"); //Agora nós preparamos alguns exemplos de dados (com expectativa de saída) // e os adicionamos ao conjunto de treinamento. // Uma vez que temos de adicionar todos os exemplos que queremos, nós vamos enviar // estes dados de treinamento configurados aos neurônios, para que eles possam aprender. // prepareData() tem alguns argumentos: // - Ação para fazer (treinar ou computar) // - os dados (aqui, 3 dados por configuração) // - O último argumento é a expectativa de saída. // Aqui, esta função leva os dados de exemplo e a expectativa de saída, // e adiciona nas configurações de aprendizado. // Verifique o comentário associado a esta função para obter mais detalhes. // // Aqui é o padrão que estamos ensinando: // Existem 3 números. Vamos chamá-los de a, b e c. // Você pode raciocinar com esses números como sendo coordenadas de vetor // Por exemplo (vetor indo para cima ou para baixo) // Se a < b && b < c então saída = 1 // Se a < b && b > c então saída = 0 // Se a > b && b > c então saída = 0 // Se a > b && b < c então saída = 1 // UP UP = UP / Se a < b && b < c então saída = 1 prepareData("train",1,2,3,1); prepareData("train",8,12,20,1); prepareData("train",4,6,8,1); prepareData("train",0,5,11,1); // UP DOWN = DOWN / Se a < b && b > c então saída = 0 prepareData("train",1,2,1,0); prepareData("train",8,10,7,0); prepareData("train",7,10,7,0); prepareData("train",2,3,1,0); // DOWN DOWN = DOWN / Se a > b && b > c então saída = 0 prepareData("train",8,7,6,0); prepareData("train",20,10,1,0); prepareData("train",3,2,1,0); prepareData("train",9,4,3,0); prepareData("train",7,6,5,0); // DOWN UP = UP / Se a > b && b < c então saída = 1 prepareData("train",5,4,5,1); prepareData("train",2,1,6,1); prepareData("train",20,12,18,1); prepareData("train",8,2,10,1); // Agora imprimiremos a formação integral configurada ao console, para verificar como se parece. // Apenas para fins de depuração. printDataArray(); Print("##### TRAINING #####"); // Precisamos treinar os neurônios muitas vezes, ordenadamente, // para que sejam bons naquilo que foram solicitados para fazer. // Aqui vou treiná-los com os mesmos dados (nossos exemplos) várias vezes, // até que compreendam plenamente as regras que estamos tentando ensiná-los, ou até // O treinamento ser repetido o número 'maxTraining' de vezes // (neste caso maxTraining = 500) // Quanto melhor for entendida a regra, menor será o Erro Quadrático Médio. // A função de teach() retorna o Erro Quadrático Médio (ou MSE) // 0.1 ou inferior é um número suficiente para regras simples // 0,02 ou menor é melhor para regras complexas como a que // estamos tentando ensiná-los (é um reconhecimento modelo, o que não é tão fácil. ) for (i=0;i<maxTraining;i++) { MSE = teach(); // Toda vez que o loop é executado, a função teach é ativada. // Confira os comentários associados a esta função para entender mais. if (MSE < targetMSE) { // Se o MSE é menor do que nós definimos (aqui targetMSE = 0,02) debug("training finished. Trainings ",i+1); // Então imprimimos o console // em quantos treinamentos // forem necessários para os neurônios compreenderem i = maxTraining; // e vamos sair deste ciclo } } // Nós imprimimos no console o valor MSE após o treinamento ter sido concluído. debug("MSE",f2M_get_MSE(ann)); Print("##### RUNNING #####"); // E agora podemos solicitar aos neurônios a análise de novos dados que eles nunca viram. // Será que eles vão reconhecer os padrões corretamente? // Você pode ver que eu usei a mesma função prepareData() aqui, // com o primeiro argumento definido para "compute". // O último argumento foi dedicado à expectativa de saída, // quando utilizamos esta função para registrar exemplos anteriores // é inútil, então deixamos a zero. // Se você preferir, você pode chamar diretamente a função compute(). // Neste caso, a estrutura é computar (inputVector[]); // Então, ao invés de prepareData ("compute",1,3,1,0); você faria algo como: // double inputVector[]; // declara um novo array. // ArrayResize(inputVector,f2M_get_num_input(ann)); // Redimensionar o array ao número de entrada do neurônio. // inputVector[0] = 1; // Adiciona os dados no array. // inputVector[1] = 3; // inputVector[2] = 1; // result = compute(inputVector); // Chamar a função compute(), com o array de entrada. // a função prepareData() chama a função compute(), // que imprime o resultado no console, // afim de verificarmos se os neurônios estavam certos ou não. debug("1,3,1 = UP DOWN = DOWN. Should output 0.",""); prepareData("compute",1,3,1,0); debug("1,2,3 = UP UP = UP. Should output 1.",""); prepareData("compute",1,2,3,0); debug("3,2,1 = DOWN DOWN = DOWN. Should output 0.",""); prepareData("compute",3,2,1,0); debug("45,2,89 = DOWN UP = UP. Should output 1.",""); prepareData("compute",45,2,89,0); debug("1,3,23 = UP UP = UP. Should output 1.",""); prepareData("compute",1,3,23,0); debug("7,5,6 = DOWN UP = UP. Should output 1.",""); prepareData("compute",7,5,6,0); debug("2,8,9 = UP UP = UP. Should output 1.",""); prepareData("compute",2,8,9,0); Print("=================================== END EXECUTION ================================"); return(0); } int start() { return(0); } /************************* ** printDataArray() ** Imprimir os dados utilizadas no treinamento dos neurônios ** Este é inútil. Apenas criado para fins de depuração. *************************/ void printDataArray() { int i,j; int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1; string lineBuffer = ""; for (i=0;i<bufferSize;i++) { for (j=0;j<(f2M_get_num_input(ann)+f2M_get_num_output(ann));j++) { lineBuffer = StringConcatenate(lineBuffer, trainingData[i][j], ","); } debug("DataArray["+i+"]", lineBuffer); lineBuffer = ""; } } /************************* ** prepareData() ** Prepara os dados para um treinamento ou computação. ** coloca os dados num array ** e os envia à função de treinamento ou execução. ** Atualiza de acordo com o número de entrada/saída que o seu código precisa. *************************/ void prepareData(string action, double a, double b, double c, double output) { double inputVector[]; double outputVector[]; // nós redimensionamos os array no tamanho certo ArrayResize(inputVector,f2M_get_num_input(ann)); ArrayResize(outputVector,f2M_get_num_output(ann)); inputVector[0] = a; inputVector[1] = b; inputVector[2] = c; outputVector[0] = output; if (action == "train") { addTrainingData(inputVector,outputVector); } if (action == "compute") { compute(inputVector); } // Se você tiver mais do que 3 entradas, basta alterar a estrutura desta função. } /************************* ** addTrainingData() ** Adiciona um único conjunto de dados de treinamento ** (exemplo dados + expectativa de saída) para a configuração do treinamento global *************************/ void addTrainingData(double inputArray[], double outputArray[]) { int j; int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1; // registra os dados de entrada ao array principal for (j=0;j<f2M_get_num_input(ann);j++) { trainingData[bufferSize][j] = inputArray[j]; } for (j=0;j<f2M_get_num_output(ann);j++) { trainingData[bufferSize][f2M_get_num_input(ann)+j] = outputArray[j]; } ArrayResize(trainingData,bufferSize+2); } /************************* ** teach() ** Obtém todos os dados de treinamento e usá-os para treinar os neurônios de uma vez. ** A fim de treinar corretamente os neurônios, você precisa executar ** esta função muitas vezes, até que o Erro Quadrático Médio fique abaixo do limite. *************************/ double teach() { int i,j; double MSE; double inputVector[]; double outputVector[]; ArrayResize(inputVector,f2M_get_num_input(ann)); ArrayResize(outputVector,f2M_get_num_output(ann)); int call; int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1; for (i=0;i<bufferSize;i++) { for (j=0;j<f2M_get_num_input(ann);j++) { inputVector[j] = trainingData[i][j]; } outputVector[0] = trainingData[i][3]; //f2M_train() está mostrando apenas um exemplo de cada vez aos neurônios. call = f2M_train(ann, inputVector, outputVector); } // Uma vez que temos de mostrar um exemplo, // vamos verificar se eles são bons, verificando o Erro Quadrático Médio (MSE) dos neurônios. // Se é baixo, eles aprenderam bem! MSE = f2M_get_MSE(ann); return(MSE); } /************************* ** compute() ** Computa um conjunto de dados e retorna o resultado computado *************************/ double compute(double inputVector[]) { int j; int out; double output; ArrayResize(inputVector,f2M_get_num_input(ann)); // Envia novos dados aos neurônio out = f2M_run(ann, inputVector); // e verifica o que eles dizem sobre isso usando f2M_get_output(). output = f2M_get_output(ann, 0); debug("Computing()",MathRound(output)); return(output); } /************************* ** debug() ** Dados de impressão ao console *************************/ void debug(string a, string b) { Print(a+" ==> "+b); }
A saída
Saída da rede Neural no console.
Conclusão
Também você pode ler o artigo: "Utilizando Redes Neurais Em MetaTrader", escrito por Mariusz Woloszyn, autor da Biblioteca Fann2MQL.
Levei 4 dias para entender como usar a bilbioteca FANN em MetaTrader, através de análise da pouca documentação que está disponível aqui e no google.
Espero que este exemplo seja útil para você e evitará que você perca muito tempo experimentando. Mais artigos seguirão nas próximas semanas.
Se você tiver dúvidas por favor me pergunte e eu responderei.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/1574
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso