下载MetaTrader 5

FANN2MQL 神经网络教学

8 四月 2016, 15:03
Julien
0
878

首先:

请安装 fann2MQL 库,需要用它来测试该示例。 可以从此处下载。



简介

截至目前,只有一个演示如何使用 Fann2MQL 库的示例,它允许交易者在其 MQL 代码中使用开源的神经网络库“FANN”。

但是,该示例由 Fann2MQL 库的开发者编写,不容易理解。 它并不是为新手准备的。

所以,我编写了另一个示例,在理念上更为简单且进行了充分注释。

它跟交易并不直接相关,也没使用任何金融数据。 它是一个简单的静态应用程序示例。

在该示例中,我们将教一个简单的神经网络以识别一个简单模式:

我们要教的形态由 3 个数字组成:a、b 和 c。

if a < b && b < c then expected output = 1
if a < b && b > c then expected output = 0
if a > b && b > c then expected output = 0
if a > b && b < c then expected output = 1

你可以将这些数字想象为矢量坐标(向上或向下的矢量)或市场方向等。 无论如何,可以将该形态理解为:

UP UP = UP

UP DOWN = DOWN

DOWN DOWN = DOWN

DOWN UP = UP

首先,我们要创建一个神经网络。

然后我们要给它展示一些模式的示例,让它学习并推导规则。

最后,我们给这个神经网络展示它从未见过的模式,并让它给出自己的结论。 如果它理解了规则,就能够识别这些模式。



经过注释的代码如下:

// We include the Fann2MQl library
#include <Fann2MQL.mqh>

#property copyright "Copyright © 2009, Julien Loutre"
#property link      "http://www.thetradingtheory.com"

#property  indicator_separate_window
#property  indicator_buffers 0

// the total number of layers. here, there is one input layer,
// 2 hidden layers, and one output layer = 4 layers.
int nn_layer = 4;
int nn_input = 3; // Number of input neurones. Our pattern is made of 3 numbers, 
                  // so that means 3 input neurones.
int nn_hidden1 = 8; // Number of neurones on the first hidden layer
int nn_hidden2 = 5; // number on the second hidden layer
int nn_output = 1; // number of outputs

// trainingData[][] will contain the examples 
// we're gonna use to teach the rules to the neurones.
double      trainingData[][4];  // IMPORTANT! size = nn_input + nn_output


int maxTraining = 500;  // maximum number of time we will train 
                        // the neurones with some examples
double targetMSE = 0.002; // the Mean-Square Error of the neurones we should 
                          // get at most (you will understand this lower in the code)

int ann; // This var will be the identifier of the neuronal network.

// When the indicator is removed, we delete all of the neurnal networks 
// from the memory of the computer.
int deinit() {
   f2M_destroy_all_anns();
   return(0);
}

int init() {
   int i;
   double MSE;
   
   Print("=================================== START EXECUTION ================================");
   
   IndicatorBuffers(0);
   IndicatorDigits(6);
   
   // We resize the trainingData array, so we can use it.
   // We're gonna change its size one size at a time.
   ArrayResize(trainingData,1);
   
   Print("##### INIT #####");
   
   // We create a new neuronal networks
   ann = f2M_create_standard(nn_layer, nn_input, nn_hidden1, nn_hidden2, nn_output);
   
   // we check if it was created successfully. 0 = OK, -1 = error
   debug("f2M_create_standard()",ann);
   
   // We set the activation function. Don't worry about that. Just do it.
        f2M_set_act_function_hidden (ann, FANN_SIGMOID_SYMMETRIC_STEPWISE);
        f2M_set_act_function_output (ann, FANN_SIGMOID_SYMMETRIC_STEPWISE);
        
        // Some studies show that statistically, the best results are reached using this range; 
     // but you can try to change and see is it gets better or worst
        f2M_randomize_weights (ann, -0.77, 0.77);
        
        // I just print to the console the number of input and output neurones. 
      // Just to check. Just for debug purpose.
   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 #####");
   
   // Now we prepare some data examples (with expected output) 
   // and we add them to the training set.
   // Once we have add all the examples we want, we're gonna send 
   // this training data set to the neurones, so they can learn.
   // prepareData() has a few arguments:
   // - Action to do (train or compute)
   // - the data (here, 3 data per set)
   // - the last argument is the expected output.
   // Here, this function takes the example data and the expected output, 
   // and add them to the learning set.
   // Check the comment associated with this function to get more details.
   //
   // here is the pattern we're going to teach:
   // There is 3 numbers. Let's call them a, b and c.
   // You can think of those numbers as being vector coordinates 
  // for example (vector going up or down)
   // if a < b && b < c then output = 1
   // if a < b && b > c then output = 0
   // if a > b && b > c then output = 0
   // if a > b && b < c then output = 1
   
   
   // UP UP = UP / if a < b && b < c then output = 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 / if a < b && b > c then output = 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 / if a > b && b > c then output = 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 / if a > b && b < c then output = 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);
   
   // Now we print the full training set to the console, to check how it looks like.
   // this is just for debug purpose.
   printDataArray();
   
   
   Print("##### TRAINING #####");
   
   // We need to train the neurones many time in order 
   // for them to be good at what we ask them to do.
   // Here I will train them with the same data (our examples) over and over again, 
   // until they fully understand the rules we are trying to teach them, or until 
   // the training has been repeated 'maxTraining' number of time  
   // (in this case maxTraining = 500)
   // The better they understand the rule, the lower their mean-Square Error will be.
   // the teach() function returns this mean-Square Error (or MSE)
   // 0.1 or lower is a sufficient number for simple rules
   // 0.02 or lower is better for complex rules like the one 
   // we are trying to teach them (it's a patttern recognition. not so easy.)
   for (i=0;i<maxTraining;i++) {
      MSE = teach(); // everytime the loop run, the teach() function is activated. 
                     // Check the comments associated to this function to understand more.
      if (MSE < targetMSE) { // if the MSE is lower than what we defined (here targetMSE = 0.02)
         debug("training finished. Trainings ",i+1); // then we print in the console 
                                                     // how many training 
                                                     // it took them to understand
         i = maxTraining; // and we go out of this loop
      }
   }
   
   // we print to the console the MSE value once the training is completed
   debug("MSE",f2M_get_MSE(ann));
   
   
   Print("##### RUNNING #####");
   // And now we can ask the neurone to analyse new data that they never saw.
   // Will they recognize the patterns correctly?
   // You can see that I used the same prepareData() function here, 
   // with the first argument set to "compute".
   // The last argument which was dedicated to the expected output 
   // when we used this function for registering examples earlier,
   // is now useless, so we leave it to zero.
   // if you prefer, you can call directly the compute() function.
   // In this case, the structure is compute(inputVector[]);
   // So instead of prepareData("compute",1,3,1,0); you would do something like:
   //    double inputVector[]; // declare a new array
   //    ArrayResize(inputVector,f2M_get_num_input(ann)); 
   // resize the array to the number of neuronal input
   //    inputVector[0] = 1; // add in the array the data
   //    inputVector[1] = 3;
   //    inputVector[2] = 1;
   //    result = compute(inputVector); // call the compute() function, with the input array.
   // the prepareData() function call the compute() function, 
   // which print the result to the console, 
   // so we can check if the neurones were right or not.
   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()
** Print the datas used for training the neurones
** This is useless. Just created for debug purpose.
*************************/
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()
** Prepare the data for either training or computing.
** It takes the data, put them in an array, 
** and send them to the training or running function
** Update according to the number of input/output your code needs.
*************************/
void prepareData(string action, double a, double b, double c, double output) {
   double inputVector[];
   double outputVector[];
   // we resize the arrays to the right size
   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);
   }
   // if you have more input than 3, just change the structure of this function.
}


/*************************
** addTrainingData()
** Add a single set of training data 
**(data example + expected output) to the global training set
*************************/
void addTrainingData(double inputArray[], double outputArray[]) {
   int j;
   int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1;
   
   //register the input data to the main array
   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()
** Get all the trainign data and use them to train the neurones one time.
** In order to properly train the neurones, you need to run ,
** this function many time until the Mean-Square Error get low enough.
*************************/
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() is showing the neurones only one example at a time.
      call = f2M_train(ann, inputVector, outputVector);
   }
   // Once we have show them an example, 
   // we check if how good they are by checking their MSE. 
   // If it's low, they learn good!
   MSE = f2M_get_MSE(ann);
   return(MSE);
}


/*************************
** compute()
** Compute a set of data and returns the computed result
*************************/
double compute(double inputVector[]) {
   int j;
   int out;
   double output;
   ArrayResize(inputVector,f2M_get_num_input(ann));
   
   // We sent new data to the neurones.
   out = f2M_run(ann, inputVector);
   // and check what they say about it using f2M_get_output().
   output = f2M_get_output(ann, 0);
   debug("Computing()",MathRound(output));
   return(output);
}


/*************************
** debug()
** Print data to the console
*************************/
void debug(string a, string b) {
   Print(a+" ==> "+b);
}


输出结果


神经网络在控制台的输出结果。



总结

你也可以阅读 Mariusz Woloszyn 写的“在 MetaTrader 中使用神经网络”一文,他是 Fann2MQL 库的开发者。

通过分析这里和 google 上为数不多的可用文档,我花了 4 天时间才理解了如何在 MetaTrader 中使用 Fann。

希望本例能够对你有用,避免浪费过多的试验时间。 后续几周将会跟进更多的文章。

如果你有问题就直接问,我会进行回答。

由MetaQuotes Software Corp.从英文翻译成
原始文章: https://www.mql5.com/en/articles/1574

附加的文件 |
ASNN_1_learner.mq4 (11.74 KB)
验证流言: 全日交易取决于亚洲时段的交易行情 验证流言: 全日交易取决于亚洲时段的交易行情

在本文中,我们会探讨著名论述“全日交易取决于亚洲时段的交易行情”。

烛台方向统计再现的研究 烛台方向统计再现的研究

是否能够基于烛台方向的再现趋势,在一天内的特定时间预测市场在即将到来的一小段时间内的市场行为? 即,是否可以在第一时间找出此类事件。 每个交易者可能都想过这个问题。 本文的目的是尝试基于烛台在特定时间间隔内的统计再现来预测市场行为。

Meta 交易者持仓报告 - 在 MetaTrader 4 中进行美国商品期货交易委员会报告分析的新领域 Meta 交易者持仓报告 - 在 MetaTrader 4 中进行美国商品期货交易委员会报告分析的新领域

本文关于在 MetaTrader 中使用美国商品期货交易委员会(CFTC)的报告数据。 文章详细描述了所讨论的 META 交易者持仓报告(COT)项目,展示了如何加载和处理必要的信息。 项目中包含的 Expert Advisor 将帮助我们分析文章中给出概念的有效性。 最后,我们将得出一些结论并提供有用的建议。

请保护好自己,开发员! 请保护好自己,开发员!

知识产权的保护依旧是个大问题。 本文对 MQL4 程序保护的基本原则进行阐述。 通过这些原则,你可以确保你所开发的成果不会被窃取,或至少能够让小偷的“工作”复杂化,以让他罢手。