A New Guy Dips a Toe in the Beginning EA Programming Water

 

All,

I have traded manually for just over a year now and have come up with a few strategies that have started to work and then succumbed to my lack of discipline.

In order to counter that I have gone through the MQL4 book and am trying to learn to code an EA with parameters I can adjust and test.

Obviously the long term idea is to have an EA running (we can talk about stuff like that here, right?) but for now I have designed what I had hoped was a simple strategy whose key purpose would be for learning MQL4 but also would allow analysis of the differences money management can make.

I know the basics of C++, I have a working knowledge of Python, and I use VBA (excel) and VBA.NET (in an ERP user interface) on a daily basis, enough that I wish I could just connect excel to MT4, it would be much easier!

 So here's where I started:

//1 - do nothing if there are any open orders whose stop loss has not been moved to breakeven

//2 - establish the existence and direction of trend in 200EMA for each pair, discarding those who do not show >0 movement in the same direction for the past 10 periods

//3 - of those remaining, do the same for the 10EMA

//4 - discard any pairs with diverging trends

//5 - discard any pairs where the trends are diverging if the 10EMA is behind (IE "above", in a downtrend) the 200EMA

 //6 - discard any pairs where the trends are converging if the 200EMA is behind the 10EMA

//7 - discard any pairs where the spread is >X 

//8 - select the pair of those remaining that has the greatest delta in the 200EMA from 10 periods ago

//9 -  place an order in the direction of the chosen pair's trend where SL = (extremity of 3 periods ago + spread); TS = delta(SL,Price), lot size = 3% of account /TS; TP = Price + 4*TS

 

 Alright, so now I'm finding that there are a lot of things not quite like C++,  and there are a lot of references I need to learn about. So far, I think I have got Item 1. Does this make sense? I also am just a bit unclear about the correct use of the built-in event triggers, as all of the tutorials I have been able to find use the old init-start-deinit syntax. I think 'OnTick' is self-explanatory, but I am not sure!

 

Also, at the end of the TestForEquity function I call the next one, the TestFor200Trend function; but is this a legal function call in MQL4? 

 

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
//test for open orders that are not at breakeven
   TestForEquity();


  }
//+------------------------------------------------------------------+
int TestForEquity()
  {
   int ctr=OrdersTotal();
   while(ctr>0)
     {
      if(OrderSelect(ctr,SELECT_BY_POS,MODE_TRADES)==TRUE)
        {
         double SL=OrderStopLoss();
         double Price=OrderOpenPrice();
         if(OrderType()==OP_BUY)
           {
            if(SL<Price)
              {
               break;
              }
           }
         else
           {
            if(OrderType()==OP_SELL)
              {
               if(SL>Price)
                 {
                  break;
                 }
              }
           }
        }
      ctr--;
     }
   //test for long trend existence and direction
   TestFor200Trend();
   return(0);
  }

 

 If anyone has time to comment, it's much appreciated! I'm going to add each section of my EA as a separate post as it is either developed or fails to be developed!

 
To start to learn mql4 have a look at the example EAs of mt4 in your expert\ folder ...
 

Well yeah, I assumed that would be obvious, and did so...

 I'm still unclear on the new event triggers;

I'm still interested in whether the community thinks my approach to the first step makes sense;

And I'm still unclear on whether you can just call a function the way I have done here.

 Anybody have any actual input? One day I'll find a way to help you, said the mouse to the forum lions...

 

OK, so on to step two. Are there any experts out there on Arrays? Please don't tell me to RTFM or review sample code in MT4 - assume I'm Very Dumb and have done so already without the desired result.

 I'm very open to suggestions of other ways to do this, but in order to compare a selection of currency pairs, I want to create an array, where in the first two dimensions we have a list of pairs vertically (known by their rank in the Marketwatch window) and horizontally, we have attributes of each pair at the close of the last period: High, Low, 200EMA and 10EMA.

The third dimension would be the period before last, the one before that, 3 periods ago, 4 periods ago, etc.

 Arrays in MQL4 have got me a bit stumped, so I'm leaving out the actual currency data for now and just trying to initialize, write to, and read from my array.

OK, so following the documentation:

double matrix[][10][20]; // 3-dimensional dynamic array

 

Done in the global scope, compiles happily. OK, I actually want the first dimension to be big enough to hold all the pairs available, the second to hold my 4 attributes high, loe, 200EMA,10EMA; and my third dimension to go back 10 periods:

double matrix[][4][10]; // 3-dimensional dynamic array

 

so far, so good. I try to capture the number of pairs availabe:

int nbr(); //variable to hold the number of pairs available to me
int nbr=SymbolsTotal(true);
double matrix[nbr][4][10]; // 3-dimensional dynamic array

 And this fails. "Invalid Index value". OK, lets take a look at the book:

 "Before using an array in a program, it must be declared. An array can be declared like a variable on the global and local level. Accordingly, values of global array elements are available to the whole program, values of a local one - only to the function, in which it is declared."

OK, do I need to resize it first? Is this the way to do so?

 

int nbr(); 
nbr = SymbolsTotal(true);
double matrix[][4][10]; // 3-dimensional dynamic array
ArrayResize(matrix,nbr);

 

Ugh, apparently not. Fails with "  'nbr' - declaration without type ".

 OK, well when I was little global variables were considered a Bad Thing at least in C++, so lets move all this to where I'll use it, in a function called by OnTick().

 

int FillTheArray()
   {
   int nbr(); 
   nbr = SymbolsTotal(true);
   double matrix[][4][10]; 
   ArrayResize(matrix,nbr);
   
   return(0);
   }

 

Nope.. my line int nbr(); is flagged and it fails: " 'nbr' - function can be declared only in the global scope.

OK, I thought I was declaring a local variable . Lets check the book again:

 OK, local variables don't get (), fine. Aha! We are getting somewhere, and this at least compiles:

 

int FillTheArray()
   {
   int nbr; 
   nbr = SymbolsTotal(true);
   double matrix[][4][10]; // 3-dimensional dynamic array
   ArrayResize(matrix,nbr);
   
   return(0);
   }

 

OK, so I have my array, apparently, and it has apparently been resized to fit the number of pairs available to me.

 So can I write to and read from my array? Visualizing my array as solid with (x,y,z) dimensions, I want to write '1.123' to (nbr,0,1).

...which failed... Oh right, if there are nbr elements in an array that starts at 0, then the top one is nbr-1, ok...

 

int FillTheArray()
   {
   int nbr; 
   nbr = SymbolsTotal(true);
   double matrix[][4][10]; // 3-dimensional dynamic array
   ArrayResize(matrix,nbr);
   matrix[nbr-1,0,1] = 1.123;
   double bob = matrix[nbr-1,0,1];
   Alert(bob);
   return(0);
   }

 

Alright!! it compiles without error, and on the next tick an alert pops up with the value of 'bob' (I tend to anthropomorphize my variables) , proving also that I can indeed write to and read from my array, and call a function. 

Somebody tell me, am I at all on the right track here? I guess my next step will be to loop through the array and assign the atribute valuables I want to it; for that I'll first have to figure out how to get those values.

I'm recording my struggles because it helps me stay focused and hopefully it will help another newbie who finds the documentation woefully inadequate !

 

OK, so I got a bit sidetracked trying to figure out arrays, but hopefully getting the actual data about my currency pairs should be more straightforward.

This code compiles and runs but I haven't tried checking it for trends etc; and I'm overdue for bed...

However, if anyone has a chance to tell me if I'm on the right track that would be fantastic. Just to be clear, the goal here is to collect up the high, low, 200EMA and 10EMA for each pair available and for each of the past 10 days (the array is declared in the global scope and nbr is set to the number of pairs in marketwatch)

int GetAttributes()
  {
   ArrayResize(matrix,nbr);
   for(int day=1;day<=11;++day) //0 is today, 1 is yesterday...
     {
      for(nbr;nbr>=0;--nbr)
        {
         matrix[nbr,0,day] =    iHigh(SymbolName(nbr,true),PERIOD_D1,day); //last period high
         matrix[nbr,1,day] =    iLow(SymbolName(nbr,true),PERIOD_D1,day); //last period low
         matrix[nbr,2,day] =    iMA(SymbolName(nbr,true),PERIOD_D1,200,0,MODE_EMA,PRICE_CLOSE,day); //last period 200EMA
         matrix[nbr,3,day] =    iMA(SymbolName(nbr,true),PERIOD_D1,10,0,MODE_EMA,PRICE_CLOSE,day); //last period 10EMA
        }
     }
   return(0);
  }

 

Can anyone comment on whether I'm using the built-in functions correctly?

 Thanks in advance! 

 

to check the correctness: 1) create a script 2) run your code-snippage and fill your matrix and 3) compare each value: err = matrix[x,1,day] - iMA(...)

 
thanks, good idea, I hadn't thought of using scripts. I must be doing something wrong though as the code that runs in the EA fails with an array out of range error in the script. I will tinker with it a bit more and see what happens.
 
UncleSteve:

OK, so I got a bit sidetracked trying to figure out arrays, but hopefully getting the actual data about my currency pairs should be more straightforward.

This code compiles and runs but I haven't tried checking it for trends etc; and I'm overdue for bed...

However, if anyone has a chance to tell me if I'm on the right track that would be fantastic. Just to be clear, the goal here is to collect up the high, low, 200EMA and 10EMA for each pair available and for each of the past 10 days (the array is declared in the global scope and nbr is set to the number of pairs in marketwatch)

 

int GetAttributes()
  {
   ArrayResize(matrix,nbr);
   for(int day=1;day<=11;++day) //0 is today, 1 is yesterday...
     {
      for(nbr;nbr>=0;--nbr)
        {
         matrix[nbr,0,day] =    iHigh(SymbolName(nbr,true),PERIOD_D1,day); //last period high
         matrix[nbr,1,day] =    iLow(SymbolName(nbr,true),PERIOD_D1,day); //last period low
         matrix[nbr,2,day] =    iMA(SymbolName(nbr,true),PERIOD_D1,200,0,MODE_EMA,PRICE_CLOSE,day); //last period 200EMA
         matrix[nbr,3,day] =    iMA(SymbolName(nbr,true),PERIOD_D1,10,0,MODE_EMA,PRICE_CLOSE,day); //last period 10EMA
        }
     }
   return(0);
  }

Can anyone comment on whether I'm using the built-in functions correctly?

 Thanks in advance! 

 First check that the 2nd and 3rd dimensions of the array are the correct size. You don't seem to fill the element 0 in the last dimension, so it will have to be at  least 12.

You are changing the value of a globalscope variable (nbr) in your code and you may not want to do this.

Also --nbr does not work as you expect 

Better to use

      for(int x=nbr-1;x>=0;x--)
        {
         matrix[x,0,day] =    iHigh(SymbolName(nbr,true),PERIOD_D1,day); //last period high
         matrix[x,1,day] =    iLow(SymbolName(nbr,true),PERIOD_D1,day); //last period low
         matrix[x,2,day] =    iMA(SymbolName(nbr,true),PERIOD_D1,200,0,MODE_EMA,PRICE_CLOSE,day); //last period 200EMA
         matrix[x,3,day] =    iMA(SymbolName(nbr,true),PERIOD_D1,10,0,MODE_EMA,PRICE_CLOSE,day); //last period 10EMA
        }
 

yes, thank you, I had forgotten the vagaries of arrays (or dictionaries as I learned them in python).

I also have decided to scrap the multi-dimensional array and just use two single dimension ones: keep uptrend pairs and keep downtrend pairs. I'll use loops to eliminate contenders before adding them to those pairs.

Reason: