Download MetaTrader 5

Tough time understanding the loop structure and price array's.

To add comments, please log in or register
Have you developed a trading robot? Publish it in the Market and make profit!
Neal_Van
327
Neal_Van 2012.03.01 17:00 

I'm trying to learn the language and I understand that an important part of an indicator is

being able to cycle through price data but I'm having a tough time understanding it.   The

definitions in the documentation are not sinking in and some things don't appear to have

a definition however your supposed to understand what they are.  I'm not criticizing here

I'm just stating my opinion because I'm confused -  so please help me.  


Perhaps an experienced programmer could tell me their interpretation of this code

in layman's terms so I can understand?

for (int i = 1; i < rates_total; i++)

I understand that this is a for loop and that it will loop as long as i is

is less than rates_total and that i is incremented.   But where I get lost

is what is it really saying and what exactly is rates_total?  

I'm sorry I'm just not getting it but I need to learn this.  I get nearly everything

else but this is where I get lost.    Perhaps this is my dyslexia kicking lol in but

i need better explanations.   Thank you, Sincerely, Neal

rsa2000
7
rsa2000 2012.03.01 18:41  

HI,

the rates in mql are organized in a structure called Array , it´s a form or organizing data in memory and accessing it later 

the array is a list where each element is accessed using the index , normally the arrays have a fixed number of elements 


the for loop is a control structure used to perform the same task n times , and is very convenient for iterating elements in array

in the code u showed it´s a simple loop iterating an array


there are 2 variables ( assuming u know the concept of variable )  the i , by convention the i is used as a name for the variable iterating the for  but  can use any name for it

rates_total  it´s the variable that contains the maximum number of elements in the rates array , it´s declared before in some code that u didnt paste here

so for ( int = i ;i< rates_total ;i++ )

let´s assume rates_total  = 10 ( the for will run 9 because u started with 1 as the initial value for i  )

you can read the line as , put 1 as the value of i , now check the condition i < rates_total  ( if is true then the code inside the for will execute one time ) after that one execution there's  i++ which means add 1 to the value of i

so the next time i = 2 and is going to check the condition 2 < rates_total ( 10 ) it´s true and then it will execute one more till , till u reach i = 10 and i < rates_total which is no longer true , so the loop stops

so it´s a way to perform some kind of operaqtion to every element in the array


for( i =0;i<rates_total;i++ ) Print( rates_array[i].bid ) , prints the bid value of each element of the array

array_name[index_position] is the way u access the array







onewithzachy
2271
onewithzachy 2012.03.06 15:00  

rates_total = total number  of  bar in a chart.

Say, you open EURUSD 1 minute chart and there are 12345 bars in it, that rates_total. You have rates_total 12345 in EURUSD 1 minute.

that's the simplest but dumb explanation of it :) 

In geeky MQL5, rates_total is the size of the price[] array.

Here's the example : 

Open MetaEditor, press F1 to get help, click MQL5 Reference > Language Basic > Function > Event Handling Function. Study and copy the sample on bottom of that "Event Handling Function" help page.

Click new (or press Ctrl + N) on MetaEditor, select Custom Indicator > next > name it "whatever" > next > OnCalculate ( the top one, not the number two) > next > finish.

On your new "whatever" Custom Indicator page, press Ctrl + A to select all then press Ctrl + V to paste it. Press F5 then.

Your MT5 will open and press Ctrl + T to open tool box and select "Experts" tab.

So what your reading there, it's bar is equal with rates_total :) there, you have it.

BTW, your loop for (int i = 1; i < rates_total; i++), will count EURUSD above from 1 and exit loop at 12344, not 12345.

To correct that, either you count it from 0 to < rates_total or from 1 to <= rates_total and not from 1 to < rates_total like yours.

 

eric_mql5
106
eric_mql5 2012.03.06 18:38  

also keep in mind this

double my_array[N]  has N elements and are indexed from 0,1,...,N-1 (there are N numbers from 0 to N-1)

so usually in C/C++ start from 0 to N-1

for(int i=0;i<N;i++){

my_array[i]=i*i;

you could also do it like this but it is ugly 

 for(int i=0;i<=N-1;i++){

my_array[i]=i*i;

 

if you want to go backward

for(i=N-1;i>=0;i--)


Neal_Van
327
Neal_Van 2012.03.08 02:43  

Thanks for responses sorry for being so late in getting back to my question but very busy laboring.

Ok so rates total is just an array that reflects the number of bars on the chart?

and the for loop is a way of counting (iterating through) those bars on the chart

in a backwards fashion from 0 or where ever is chosen to start?

I'm assuming the main purpose of this is to find when the current bar

changes on the chart?    and if i'm right,.... if rates total = 1, that is

the time to run the conditions of the for loop? 

Documentation on MQL5: Standard Constants, Enumerations and Structures / Chart Constants / Chart Properties
  • www.mql5.com
Standard Constants, Enumerations and Structures / Chart Constants / Chart Properties - Documentation on MQL5
onewithzachy
2271
onewithzachy 2012.03.08 10:01  
Neal_Van:

Thanks for responses sorry for being so late in getting back to my question but very busy laboring. (reply : it's ok. we're all busy)

Ok so rates total is just an array that reflects the number of bars on the chart? (reply : not correct definition but for the sake of simple explanation, then the answer is yes)

and the for loop is a way of counting (iterating through) those bars on the chart (reply : exactly)

in a backwards fashion from 0 or where ever is chosen to start? (reply : I don't understand "backwards fashion from 0" but, Yes, sort of, I'll explain this below)

I'm assuming the main purpose of this is to find when the current bar changes on the chart?   (reply : yes, that is the purpose)

and if i'm right,.... if rates total = 1, that is the time to run the conditions of the for loop? (reply : No. If rates_total = 1, then you have only one bar on the chart :). Very unlikely. Where did you get this idea ?. Above you said that rates total is just an array that reflects the number  of bars on the chart, which is correct. So where did you get the idea of rates_total = 1 ?. The iteration start whenever "i" is less than rates_total - you know that from your first post)

I'll explain this but you may have to read this carefully because it may confuse you.

Before we continue, please open MQL5 help file, click Timeseries and indicators access > Indexing direction in Arrays, Buffers, and Timeseries, and read the first three paragraphs.

Every array is always counted from 0 to (number of element -1). Standard array is always counted from left to right. 

The type of price[] array is Timeseries which is counted from the right to the left. It's called Timeseries, because it is based on time. The data on the left is the oldest one - historical, while on the right is the newest one - the up to date one, and this is the one that we will work on. Important : We still count timeseries array from 0 but we start counting from the right not left.

I apologize but I have to correct myself, The type of price [] array is not timeseries but common array which we count from left to right.

It is HC files that is indexed as timeseries and MT5 use HC files to show bar on chart. However, HC files is not important to be discussed here.

Many thanks to phi.nuts for correcting me, I was working with MT4 while at the same time replying to Neil_Van post here. 

Below, I bold my correction and strikeout my error.  Everything else remain the same.

You mention "backward fashion from 0", which I don't get it, perhaps you don't understand the concept of arrays timeseries.  

However, remember this, the array of Indicator buffer is not timeseries, it's a standard array which we count from left to right. We'll talk about this later, on different reply. 

If you obtain data from price[] array using your example :

for (int i = 1; i < rates_total; i++)

It mean you obtain data from price[] array (or obtain data from bar on chart - if you wish) starting from bar 1 the oldest bar plus one bar (which is not current - newest bar) to the left most oldest bar the right most newest current bar or bar 0. To correct that we use this that code is correct 

for (int i = 0; i < rates_total; i++)

which mean we obtain data from price[] array from the current - newest - the right most bar or bar 0 to the oldest bar.  the oldest one (and not plus one bar) to the newest bar 0.

For example we have 1000 bars on EURUSD 1 minute chart. That mean, rates_total is also 1000. If right now time is 12:00, with your for loop example we obtain data from 11.59 the oldest one plus 1 minute to the oldest one. With the second example, we obtain data from 12:00 - which is right now to the oldest one. oldest one to the newest one. 

To answer your question below, we can also obtain data from the current bar 0 to the oldest one by decrements the iteration.

So the code will be like this :

for (int i = rates_total; i < 0; i--)

It mean we obtain data from price[] array from bar 0 to the oldest one.

while your codes, will obtain data from the oldest one to the newest current bar 0 by increments the iteration. 

One minute later, we have new price, and now the number of bar is 1001 and so also the rates_total is 1001. Is that mean the for loop iterate 1000 iteration then one minute later it iterate 1001 - on every tick ?. The answer is yes.

Good thing is, MQL5 has variable called prev_calculated in On_Calculated () function. 

When you attach, the CI for the first time, the value of prev_calculated is 0, one tick later it's value become equal with rates_total. I gave you example in my previous reply, if you scroll down (right click, un-check auto scroll) to the very first time when you attach that example CI, the value of prev_calculated is 0. Please look at that again.

 So, to calculate only the current bar and to set condition of the for loop to start iteration, we use this :

int count, i ;

if(prev_calculated == 0)                  // <<== first time attached ...
   {
   count = 0;                              // <<== ... we obtain data from price[] from the left most bar to the right most bar
   }
   else
   {
   count = prev_calculated - 1;           // <<== this is important : one tick afterwards and thereafter we obtain always and only from bar 0
   }

for (i = count; i < rates_total; i ++)    // <<== we iterate to less than rates total, if new bar coming the value of rates total is increased by 1
   {
   Buffer [i] =  // obtain data from price[i] array            
   }

 With EURUSD with 1000 bars above,

  1. The first time we attach the CI, the prev_calculated is 0, the for loop iterate from 0 to 999 (count = 0, to less than rates_total of 1000), which is 1000 iteration. We get all data from historical bar 999 to the newest one bar 0.
  2. One tick later, everything changes, the prev_calculated is 1000, the for loop iterate from 999 to 999 (count = prev_calculated - 1 = 999 to less than 1000, is 999 less than 1000 ?, you get that ?). Only one iteration, and this is the data from current newest right most bar which is bar 0. Only bar 0.
  3. One minute later we have new bar, this new bar is bar 0. Now rates_total is 1001, but prev_calculated is still 1000. The for loop iterates from count 999 to 1000 (get that again ? less than rates_total of 1001). 2 iteration which is, iteration from bar number 1 to bar number 0 of the right most bar.
  4. And so on, and so on starting again from #2.

And that's how CI calculate any changes in the current bar, and to answer your Q " To find when the current bar changes on the chart? ", 

So, the different value between prev_calculated variable and rates_total is the one that "trigger" the calculation/for loop iteration.

For example, if we change into this :

 count = prev_calculated;           // <<== one tick atferwards,

That mean one tick afterward, we have prev_calculated = 1000, rates total = 1000, and we count from 1000.  That's doesn't works because the for loop won't iterate from 1000 to 999 (999 is less than 1000), and we wont' get any current data.

One minute later, we have rates total 1001, and prev_calculated is still 1000.  The for loop iterates from 1000 to 1000. We get the new data only from bar number 0 on the first tick. One tick later, prev_calculated is 1001, the for loop loop won't iterate from 1001 to 1000 and we won't get any new data. 

I'll explain about buffer later, when you understand this and also cause I have something else to do. :) I hope you don't mind. 


Neal_Van
327
Neal_Van 2012.03.09 10:39  

I'll explain about buffer later, when you understand this and also cause I have something else to do. :) I hope you don't mind. 


No not at all it is very kind of you to explain this much.  thank you.  thank you everyone who posted...

I think this is starting to sink in and of course I will have to read more and then reread this several times plus go through more code.

I have 1 question so far and perhaps it is difficult for me because I'm dyslexic (but I won't give up until my goal is complete)

so visually it's harder for me to understand.  I don't want to pretend I understand something that is easier for most to get but bear with me lol I'm getting it.

However.... I don't understand why some indicators increment and some decrement the for loop?  What is the difference?  

I know it sounds stupid but for me it's difficult to understand.   

   


onewithzachy
2271
onewithzachy 2012.03.09 20:23  

However.... I don't understand why some indicators increment and some decrements the for loop?  What is the difference?    

Dear, Neal_Van,

Please apologize me for my error above. I was working with MT4 while answering your question. I hope I didn't give more though time understanding this.

The correct one is, the type of price[] array is like any common array which is counted from left to right.

So, if we open EURUSD 1 minute chart with 1000 bar. When we obtain data from current bar 0, we actually obtain data from price[] array index 999 (or price [999]) . and when we look at the very oldest bar, that is the price[] array index 0 (or price [0]).

To answer you question, why some indicator increment and the other decrements the for loop, the answer is below.

Here are the example.

if we obtain price [] array data from oldest bar forward to the newest one, we increments the for loop, and the codes is like yours on your first post except i = 0 :

for (int forward = 0; forward < rates_total; forward ++)      // we increase from oldest to bar 0 (rates_total)

if we obtain price[] array data from current newest one backward to the oldest one, we decrements the for loop :

for (int backward = rates_total; backward > 0; backward --)   // we decrease from bar 0 (rates_total) to oldest

No different at all, in the end, all indicators will end up calculating current price on bar 0, anyway.

 

Most Indicator is calculated from oldest bar forward to newest bar.

Some people - like me - does not like counting from oldest bar. We say, why bother oldest bar, lets just start from current price and go backward a little bar and saves time and energy and so we don't miss a tick. 

Another reason to count backward is, some indicator was designed to compare price from the newest bar to the oldest one. So they must be calculated/iterate backward. 

Surely you can not compare the current price with the future one, because the future one does not exist yet. Like comparing bar 5 with bar 1, because when bar 5 was still bar 0, bar 1 was not exist yet.

That does sound strange, however the purpose is to study the chart. One of these studies is to find what we called divergence. Divergence is when some part of indicator moves to different direction than the price.

Say, we use indicator RSI and compare bar 1 with bar 7. If price on bar 1 is higher than bar 7,  and RSI on bar 1 is lower that RSI on bar 7, then you have a divergence.

In this case, between bar 1 and bar 7, price moves higher/becomes higher than before, while the RSI moves lower/becomes lower than before. They both moves on different direction.

Later, usually, price will gives up and follow the indicator, in this case, price will moves down.

By the way, calculating divergence in indicator usually use backward and forward calculating. First, the indicator count forward from oldest bar, and then, get this : in every bar, the indicator must count backward to collect data and to search for divergence. And so on and so on, on every bar.

The code may look like this 

int backward, forward;
bool found_divergence;

for (forward = 0; forward < rates_total; forward ++)       // <<== we count forward from oldest to newest, we increment...
   {
   found_divergence = false;                               // <<== ... we "nulling" found_divergence, because we haven't found any divergence ...
   for (backward = forward; backward > 0; backward --)    // <<== ... but on every bar, we count backward, we decrements ...
      {
      // ... code to search for divergence goes here              // <<== ... and search for the divergences ...

      if (found_divergence = true ) break;                  // <<== ... if we found one, we break from "backward - decrements" for loop
      }
   
   }

 However, that code may good for chart studying but not good for trading, because for trading we better count from newest - current bar, because it much more faster for indicator to find the most recent divergence to be used for trading. 

 The codes will be like below and on both loop we using decrements, and count from bar 0 which is equal with rates_total. (We only change the iteration direction in the first for loop).

int backward_1, backward_2;
bool found_divergence;

for (backward_1 = rates_total; backward_1 > 0 ; backward_1--)  // <<== we count backward from newest to oldest, we decrements...
   {
   found_divergence = false;                                    // <<== ... we "nulling" found_divergence, because we haven't found any divergence ...
   for (backward_2 = backward_1; backward_2 > 0; backward_2--) // <<== ... on every bar, we count backward, we decrements ...
      {
      // ... code to search for divergence goes here                    // <<== ... and search for the divergences ...

      if (found_divergence = true ) break;                       // <<== ... if we found one, we break from "backward - decrements" for loop
      }  
   
   }

Those are very simple sample of divergences code, because usually we look for divergence on both high and low prices.

 :)

There, you have it .

On previous post, you said correctly that,  "rates total is just an array that reflects the number of bars on the chart".

And you also said, "iterating trough in backwards fashion from 0". If you mean iterating through from bar 0 to oldest one, that's correct then.

Talk to you later.

onewithzachy
2271
onewithzachy 2012.03.09 23:02  

With apologize to Neil_Van, I think I have to live a moment with what Daffy Duck said :
I'VE NEVER BEEN SO HUMILIATED IN MY ENTIRE LIFE. 

and many thank to phi.nuts

Neal_Van
327
Neal_Van 2012.03.18 15:22  

Sorry my mother was in the hospital for the last week.  I had to move into her house to take care of her cats and dogs

so I'm just getting back to business today.  I am still fighting stress so I will have to get back to this topic later.

I have printed this out and will read when my mood swings higher.  

To add comments, please log in or register