Too good to be true?

 
I just created a simple neural network based custom indicator and advisor, and it shows astronomical profits for EUR/USD for H1 and M30 periods in the strategy tester. Can you guys try it out and tell me what you think? Is MetaTrader just pulling my leg?

Here is the custom indicator:

//+------------------------------------------------------------------+
//|                                                           NN.mq4 |
//|                                                   Michael Rennie |
//|                                            http://www.wmin.ac.uk |
//+------------------------------------------------------------------+
#property copyright "Michael Rennie"
#property link      "http://www.wmin.ac.uk"

#property indicator_separate_window
#property indicator_minimum -1
#property indicator_maximum 1
#property indicator_buffers 1
#property indicator_color1 Red

//---- buffers
double NNOutput[];

#define Network_NumInputs 6
#define Network_NumHidden 3
#define Network_NumOutputs 1

double InputRanges[Network_NumInputs] = {0.0106999999999999, 0.00322, 0.00169999999999981, 0.000890000000000057, 0.000541666666666663, 0.000433333333333286};
double OutputRange = 0.502511362839716;

double HiddenLayer_Weights[Network_NumInputs][Network_NumHidden];
double HiddenLayer_Bias[Network_NumHidden];
double OutputLayer_Weights[Network_NumHidden][Network_NumOutputs];
double OutputLayer_Bias[Network_NumOutputs];

HiddenLayer_Bias[0] = 			-4.10859066699714;
HiddenLayer_Weights[0][0] = 	4.36354844369731;
HiddenLayer_Weights[1][0] = 	0.0204045335708819;
HiddenLayer_Weights[2][0] = 	0.313204518216276;
HiddenLayer_Weights[3][0] = 	-0.135870398801778;
HiddenLayer_Weights[4][0] = 	-0.595716791477371;
HiddenLayer_Weights[5][0] = 	0.186980796161265;
HiddenLayer_Bias[1] = 			1.26166987431495;
HiddenLayer_Weights[0][1] = 	1.78045079803871;
HiddenLayer_Weights[1][1] = 	-0.23093241110435;
HiddenLayer_Weights[2][1] = 	-0.395469433609578;
HiddenLayer_Weights[3][1] = 	0.314086889406961;
HiddenLayer_Weights[4][1] = 	1.18973567595017;
HiddenLayer_Weights[5][1] = 	0.236020963168224;
HiddenLayer_Bias[2] = 			0.932500356639842;
HiddenLayer_Weights[0][2] = 	-4.06499123497026;
HiddenLayer_Weights[1][2] = 	0.137264947074701;
HiddenLayer_Weights[2][2] = 	0.432620214314007;
HiddenLayer_Weights[3][2] = 	-0.271497058060078;
HiddenLayer_Weights[4][2] = 	-0.485670337880429;
HiddenLayer_Weights[5][2] = 	0.316848084763736;

OutputLayer_Bias[0] = 			0.531541091598325;
OutputLayer_Weights[0][0] = 	4.01742582583331;
OutputLayer_Weights[1][0] = 	-0.191887786930284;
OutputLayer_Weights[2][0] = 	-3.24672526289884;



int MovingAverageLengths[Network_NumInputs] = { 1, 5, 10, 20, 60, 120 };

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,NNOutput);
   SetIndexLabel(0, "NN");
//----  

//Print("init()");
      
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {   
for(int time = 0; time < Bars - IndicatorCounted(); time++)
   {      
      if(time == Bars - 1)
      {
         NNOutput[time] = 0;//last prediction is simply 0
         continue;
      }
      
      //calculate the MA inputs for current time
      double Inputs[Network_NumInputs];
          
      for(int input = 0; input < Network_NumInputs; input++)
      {
         double ma = 0;
         int d;
         for(d = 0; d < MovingAverageLengths[input]; d++)
         {
            if(time + d == Bars)
               break;
            ma += Close[time + d];
         }
         ma /= d;
         Inputs[input] = ma;
      }
      
      //difference it with MA from previous time
      for(input = 0; input < Network_NumInputs; input++)
      {
         ma = 0;
         for(d = 0; d < MovingAverageLengths[input]; d++)
         {
            if(time + 1 + d == Bars)
               break;
            ma += Close[time + 1 + d];
         }
         ma /= d;
         
         //difference AND scale it to [-1 1]
         Inputs[input] = (Inputs[input] - ma) / InputRanges[input];
         
         //bring it to [0 1]
         Inputs[input] = (Inputs[input] + 1) / 2;         
      }
      
      //send the inputs to the NN
      NNOutput[time] = CalcOutput(Inputs);
   }     
   
   return(0);
  }
//+------------------------------------------------------------------+

double CalcOutput(double Inputs[])
{               
      double HiddenNodes[Network_NumHidden];
      
      //first the hidden layer
      for(int output = 0; output < Network_NumHidden; output++)
      {
         HiddenNodes[output] = HiddenLayer_Bias[output];
      
         for(int input = 0; input < Network_NumInputs; input++)
            HiddenNodes[output] += Inputs[input] * HiddenLayer_Weights[input][output];
            
         HiddenNodes[output] = 1 / (1 + MathExp(-HiddenNodes[output]));
      }
      
      //now the output layer
      double nnOutput = OutputLayer_Bias[0];
      for(input = 0; input < Network_NumHidden; input++)      
         nnOutput += HiddenNodes[input] * OutputLayer_Weights[input][0];   
      nnOutput = 1 / (1 + MathExp(-nnOutput));
      
      //bring it from [0 1] to [-1 1]
      nnOutput = nnOutput * 2 - 1;
   
      //scale it to the [-1 1] exactly
      nnOutput /= OutputRange;
      
      return(nnOutput);
}



And here is the expert:

//+------------------------------------------------------------------+
//|                                                    NN Expert.mq4 |
//|                                                   Michael Rennie |
//|                                            http://www.wmin.ac.uk |
//+------------------------------------------------------------------+
#property copyright "Michael Rennie"
#property link      "http://www.wmin.ac.uk"


#define OpenPositionThreshold 0.3
#define ClosePositionThreshold 0.1

#define Slippage 3
extern int LotSize = 1;

#define OrderString "NN Order"

int start()//| expert start function
  {
  
int MagicNumber = 0x01091984 + Period();

   double prediction = iCustom(NULL, 0, "NN", 0, 1);
   
   //Print("Prediction: ", prediction);
   
   //check if any existing orders need closing 
   for(int order = OrdersTotal() - 1; order >= 0; order--)// go backwards
   {
      OrderSelect(order, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() != MagicNumber)
         continue;
         
      if(OrderType() == OP_BUY)
      {
         if (prediction < -ClosePositionThreshold)
            OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
      }
      else if(OrderType() == OP_SELL)
      {
         if (prediction > ClosePositionThreshold)
            OrderClose(OrderTicket(), OrderLots(), Ask, Slippage);
      }
      
   }
      
   //count how many remaining open orders there are
   int numOpenedOrders = 0;     
   for(order = OrdersTotal() - 1; order >= 0; order--)
   {
      OrderSelect(order, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == MagicNumber)
         numOpenedOrders++;
   }
   
   double Spread = Ask - Bid;
   
   if(numOpenedOrders == 0)
   {           
      if(prediction > OpenPositionThreshold)
      {         
         OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, Bid - Spread, 0, OrderString, MagicNumber, 0, Aqua);
      }
      else if(prediction < -OpenPositionThreshold)
      {
         OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, Ask + Spread, 0, OrderString, MagicNumber, 0, OrangeRed);
      }
   }
   else
   {
      for(order = 0; order < OrdersTotal(); order++)
      {
         OrderSelect(order, SELECT_BY_POS, MODE_TRADES);
         if(OrderMagicNumber() != MagicNumber)
            continue;
            
         if(OrderType() == OP_BUY)
         {
            //if(OrderStopLoss() < Bid - (TrailingStop + 5) * Point)
            if(OrderStopLoss() < Bid - Spread * 2)
            {
               OrderModify(OrderTicket(), OrderOpenPrice(), Bid - Spread, OrderTakeProfit(), 0);               
            }
         }
         else if(OrderType() == OP_SELL)
         {
            if(OrderStopLoss() > Ask + Spread * 2)
            {
               OrderModify(OrderTicket(), OrderOpenPrice(), Ask + Spread, OrderTakeProfit(), 0);
            }
         }
      }
   }
   
   return(0);
  }
//+------------------------------------------------------------------+

int init()//| expert initialization function
{
   return(0);
}
int deinit()//| expert deinitialization function
{
   return(0);
}
 
I am curious.
What do you expect as result by use of 18 decimal point numbers if the double in mt4 environment has max 8 decimal points. "0.000890000000000057"?
 
Those numbers were generated from training - I didnt write them myself. It doesnt matter if precision is lost.
 
Hi Michael,

I've had a bit of a play with Neural nets in the past and one thing I've found with them is that they are notorious for "curve fitting" - i.e. you'll get amazing profits on the data it used to learn from but when you attempt to use it in the real world, it fails miserably. The only way to test this would be to train your neural net on say, 70% of your data and then simulation trade it on the other 30%. If you get similair profits (or even any profits at all) on the 30% then you may be onto something.
 
Doesn't generate any trades here...
 
Sorry for being slightly offtopic. Can you tell me how did you train the neural nets? With which program? There are so many...
 
BTW, I get terrible results with EUR/USD for H1 and M30. Steady declining curve. And your expert makes too many trades.
 
Thanks for trying it Alex. Hmm thats weird that you get good results and I dont. I used the "Control Points" option in the settings tab. What did you use?

I wrote my own c# program for training the weights, and exported them to MetaTrader.
 

Hi,

I have problems with the indicator NN.mq4. When I get a compile error:
'HiddenLayer_Bias' - expression on global scope not allowed D: \ Program \ MetaTrader - Alpari \ experts \ indicators \ NN3.mq4 (30, 1)
'HiddenLayer_Weights' - expression on global scope not allowed D: \ Program \ MetaTrader - Alpari \ experts \ indicators \ NN3.mq4 (33, 1)

A total of 25 errors!

What is wrong?

 
derumuro :

Hi,

I have problems with the indicator NN.mq4. When I get a compile error:
'HiddenLayer_Bias' - expression on global scope not allowed D: \ Program \ MetaTrader - Alpari \ experts \ indicators \ NN3.mq4 (30, 1)
'HiddenLayer_Weights' - expression on global scope not allowed D: \ Program \ MetaTrader - Alpari \ experts \ indicators \ NN3.mq4 (33, 1)

A total of 25 errors!

What is wrong?

I beleive you have the problem of opening and closing within the same bar, it is a well know limitation of metatrader tester, try the same EA at open price only, and if you still have excellent result, then you found a good NN.

Reason: