Você está na página 1de 130

MQL4 Language for Newbies.

Introduction [ ru ]
Introduction
This sequence of articles is intended for traders, who know nothing about programming, but have a desire to learn
MQL4 language as quick as possible with minimal time and effort inputs. If you are afraid of such phrases as "object
orientation" or "three dimensional arrays", this article is what you need. The lessons are designed for the maximally
quick result. Moreover, the information is delivered in a comprehensible manner. We shall not go too deep into the
theory, but you will gain the practical benefit already from the first lesson.

Advice
If you have never worked with programming before, you may find it difficult to catch the meaning of some cases at the
first reading. Slowly read the text once again and think over each sentence. Finally you will understand everything,
because there is actually nothing difficult. Do not move forward without understanding the previous information. Study
code examples. Write your own examples based on what you have already understood.

First Acquaintance with MQL4


First of all let's view, what you can do using this language. It is intended for creating scripts, custom indicators, expert
advisors and libraries:




Scripts are sequences of commands, programs that operate only once upon your request. They may substitute
for operations you perform everyday in trading. For example when you open indents. They can also perform
specific functions - for example analyze charts and generate statistic information.
Custom indicators are technical indicators, written in addition to built-in indicators. They develop charts or
other visual information. Unlike scripts, custom indicators operate at each price change, i.e. at every tick.
What indicators will show, depends on you only. It can be a useless sinus chart or something that will help
you orientate yourself in the market situation. For example if you know exactly in what circumstances the
market experiences trend, and when - flat, you can write it as an indicator.
Expert advisors are mechanical trading systems, bound to any financial instrument. Like custom indicators,
expert advisors operate at every tick, but unlike indicators, they can inform you on the market situation (for
example, give certain advice to buy or to sell) or trade by itself without your help. A terminal supports
strategies testing, which enables quick assessment of profitability of your expert advisor. You describe your
strategy in MQL4 language, while a terminal dispassionately follows all your instructions.
Libraries are sets of functions for performing specific tasks. For example, one of your advisors may use
special mathematic functions to decide, when to sell and when to buy.

In this article we will learn to write common scripts. A special program - MetaEditor 4 is used for this purpose. To boot
it, press F4 key at an open custom terminal. To create a new script, click button File->New in the menu of MetaEditor 4
or use Ctrl+N buttons:

In the window that appeared, choose what you are going to create. Choose Script and click Next:

In the next window print the name of the script in Name field. Add your name in Author field and e-mail or web
address in Link field. Then click OK:

After that you will see a new window, with which you will work most of all. It shows the original text:

Please note, that even an empty not operating script contains a code. Now everything is ready to begin programming.
But, unfortunately, you have no idea, how it should be done. Lets try to improve the situation.

Source Code, Compiling and Others


You should understand an important matter. What is written in MetaEditor is a source code. I.e. it is a sequence of
commands that a terminal will follow one after another downward. But the terminal cannot follow source codes. The
source code is understandable for you, but not for MetaTrader. To make the source code understandable for the
terminal, it should be translated into a proper language. To make this, press F5 key in MetaEditor. After that the
source code will be compiled into a run file. Compiling is a process of translating a source code, written by you and
understandable for you, into a special file, which is understandable and performable by MetaTrader. Check it yourself.
Create a new script named Test1 and save, but do not compile. Open the terminal and, using navigator, enter
Scripts folder. You see, there is no script named Test1:

Now compile the script (F5 key):

Enter the terminal once again. There is a script named Test1:

Click twice on the script name in the terminal Navigator and it opens. But nothing happens, because the script is empty.
You should already understand, what the process of script writing looks like: you write the source code, compile it,
open the script in the terminal, watch the result, change the specific code, compile, watch and so on until you get the
necessary result.

Where Should Scripts Be Written?


You have already seen, that an empty script contains a specific code. But where should you write the source code,
which will work? It should be written between lines int start(){ and return(0);}, as shown at the picture:

Write here everything that I will offer you, and all this will work. Later we will view in details, what these lines mean.

Variables
What a variable is? Try to answer this question yourself and I will help you. How old are you? How old will you be in
five years? Now look: your age is a variable. Your age changes with the course of time, like any other variable. I.e. the
first characteristic of a variable is its change with the course of time. Another example: what was your height when you
were five? Probably, much less than now. Height is another example of a variable. But there is an important difference.
Note, that age is calculated in integers. Height is better assessed in decimals (floating-point number). Age: 20 years,
30 years. Height: 1.8 meters, 1.95 meters. This is a very important feature: each variable belongs to a certain type. Lets
see, what other types of variables exist. You can describe in figures many parameters, but how should we describe a
text? Special string types are used for this purpose. Such variables types contain only lines. Now lets see, how to create
and describe a variable in MQL4 language. Example:
int age = 25;

Here we see an integer type variable (int - integer). Int is a key word of MQL4 language, which shows, that we use a
whole number type. Then we wrote age it is the name of a variable, i.e. a word, using which we will reach the
meaning, stored in this variable. After that we assigned value 25 to the variable, using symbol =. After each
instruction ; should be put. Note, declaration and initialization of any variable come to the variable following form:
[variable type] [variable name] = [variable value];
By the way, it is not necessary to assign a value to a variable (initialize), you could write it so:
int age;

One more example:

double height = 1.95;

Here we declare a variable named height, which stores double type values (floating-point number, decimal), and
assign a value 1.95 using = operator.
Now lets see a string variable:
string name = "Janet";

string is a variable type, name is a variable name, Janet is a variable value. Note, that the value of the string type
variable is placed between double quotes ().
There is another very useful type of a variable bool. Variables of this type can accept only two values: either true or
false. Example:
bool trend = false;

Now you should remember some easy things. MQL4 language is a case dependable language, i.e. it is very important,
whether you write a code in CAPITALS or small letters. For example if you declare several variables with identical
names, but different case, you will get absolutely different variables:
double HIGHTPRICE;
double hightprice;
double HightPrice;
double hightPrice;

The above shown code will create four absolutely different variables. Also please note, that all key words of MQL4
language are written in small letters.
Next example:
DOUBLE hightPrice1;
Double hightPrice2;

The abovementioned code will not work, because the word double will not be accepted as a key word of MQL4
language. One more important moment is that the names of variables can not start with numbers or special signs (*,&,
,%,$). For example:
double 1price;
double %price;

One more language element is a comment. If you write // before a line, it will whole be commented. It means that
during compiling it will be ignored. For example:
// this is a comment

Now you can see, that an empty script code includes many comments of an informative character. Comment your code.
Sometimes it may help you save a lot of time.

Working with Variables


Now lets see, what we can do with variables after we have declared them. Lets see a simple example:
double a = 50.0;// declare a value with a floating point and
// assign the value 50 to it
double b = 2.0;
double c;

c = a + b;

// assign to the variable c sum of variables


// a and b. Now the value is equal to 52. Like after
// any other instruction put a semicolon (;)

c = a - b;

// diminution, c = 48

c = a*b;

// multiplication, c = 100

c = a / b;

// division, c = 25

c = (a + b)*a;

// place the operations that should be performed


// first inside the brackets. In our case
// first we get the sum of a and b
// after that this sum will be multiplied by a and assigned to c

c = (a + b) / (a - b); // if there are several operations in brackets,


// they will be performed
c = a + b*3.0;

// according to mathematic rules first you will get


// multiplication b and 3, and then the sum

If you need to perform an operation with a variable and assign a result to it, for example add 5, do it in one of the
following ways:
int a = 5;
a = a + 5;

// add 5

a += 5;

// analogous

a = a*5;
a *= 5;

// multiply a by 5 and assign to it

a /= 5;

// divide and assign

If you want to add or subtract 1, use the following method:


int a = 5;
a++;

// add1, it is called increment

--;

// subtract 1, it is decrement

It is all ok, but working with such scripts you can only guess, whether everything goes correctly, because nothing
happens on the screen.
That is why it is convenient to show the results. For this purpose there is an integrated function MessageBox().

MessageBox()
A function is a set of instructions, which accepts the parameters and depending on them shows the result. In our case
MessageBox() function accepts two parameters: first message text, second title text. Here is an example:
MessageBox("Hello, World! There is some text.","caption");

To perform a function, first write its name. Do not forget about the case! Then open the brackets and write parameters
using commas. In our case parameters are of a string type. As we remember, all lines are written inside quotes (). Like
in any instruction, put a semicolon at the end. To understand properly lets see the picture. It shows how the code and
results are bound:

Of course, it is all ok. But how can we show variables of other types? Easily make a mental note:
int a = 50;
int b = 100;
MessageBox("It is very simple. a+b=" + (a + b), "a+b=?")

As a result we get:

As you have already guessed, MQL4 is designed so, that when we try to add another number type to a line, it
automatically transfers numbers into lines and combines them. It is a really wonderful property! You can do such
operations with string variables also:

int a = 50;
int b = 100;
string str1 = "a + b =";
str1 += a + b; // now str1 = "a + b = 150"
// now use the variable str1 as
// a first parameter
MessageBox(str1, "a + b = ?");

Now you know how to draw different data using MessageBox() function. But what is the interest of showing the results
of simple mathematic operations? We need MQL4 not simply to find sums and multiplications, dont we?

Arrays
Do not be afraid. It is very easy. Look. Suppose you want to remember five prices. What should we do? Well, we can
do this:
double price1 = 1.2341;
double price2 = 1.2321;
double price3 = 1.2361;
double price4 = 1.2411;
double price5 = 1.2301;

We get five variables, which have one data type and describe one parameter price. We can go another way, using an
array. An array is a set of variables, which differ in indexes, but have one name. This is how we declare an array from
five elements:
double price[5];

Common form:
(array type) (array name) [number of elements];
In our case: array type double, name price, number of elements 5. Lets see how we can refer to the array
elements:
double price[5];

// declare an array of 5 elements

price[0] = 1.2341; // refer to the first element of the array and


// assign a price to it. Note
// that the index of the first element starts with 0
// It is an important feature,
// you should get used to it.
price[1] = 1.2321;

// refer to the second element

price[2] = 1.2361;

// and so on

price[3] = 1.2411;
price[4] = 1.2301;

We can perform any operations with the array elements, like with common variables. Actually, elements of the array
are common variables:

double price[2];
price[0] = 1.2234;
price[1] = 1.2421;
MessageBox("Middle price is " + (price[0] +
price[1]) / 2.0,"middle price");

When declaring an array we can assign initial values to all elements:


double price[2] = {1.2234, 1.2421};

We simply enumerate the initial values of elements comma separated in braces. In such a case you may let a compilator
automatically put the number of elements, instead of writing it yourself:
double price[] = {1.2234, 1.2421};

Undoubtedly all this is ok, but Unfortunately it is useless. We should somehow get to real data! For example, current
prices, time, amount of free money and so on.

Integrated or Built-in Arrays and Variables


Of course we cannot do without real data. To get access to them, we should simply refer to a corresponding built-in
array. There are several such arrays, for example:
High[0];

// refer to the last maximal price,


// that the bar has achieved in the current timeframe
// and current currency pair. Currency pair and
// the timeframe depend on the chart, on which you
// have started a script. It is very important to remember!

Low[0];

// minimal price of the last bar


// in the current chart.

Volume[0]; // value of the last bar in the current chart.

To understand properly in-built arrays and indexes, look at this:

You see, the last bar index (number) is 0, next to last is 1 and so on.
There are also built-in common variables. For example Bars shows the number of bars in the current chart. It is a
common variable, but it was declared before you and outside your script. This variable exists always, like other built-in
arrays and variables.

Cycles
Suppose you decided to calculate a mean value of maximal prices of all bars in the chart. For this purpose you
alternatively add each element to a variable, for example so:
double AveragePrice = 0.0;
AveragePrice += High[0];
AveragePrice += High[1];
AveragePrice += High[2];
AveragePrice += High[3];
AveragePrice += High[4];

// ... and so on

AveragePrice /= Bars;

I can tell you only this: it may work, but it is absurd. For such purposes there are cycles. Note, that all operations are
absolutely similar, only the index changes from 0 to variable Bars-1 value. It would have been much more convenient
somehow to determine a counter and using it refer to the array elements. We can solve this task using cycles:
double AveragePrice = 0.0;
for(int a = 0; a < Bars; a++)
{
AveragePrice += High[a];

Lets see each line:


double AveragePrice = 0.0; // everything is clear
// this is a cycle.
or(int a = 0; a < Bars; a++)

You see, the cycle starts with a key word for. (There are other types of cycles, for example while, but we will not learn
them now). Then in quotes point semicolon separated counter, cycle operation conditions, counter increase operation.
In a general case it can be presented like this:
for(declaration of a counter; the cycle operation conditions;
counter changes)
{
// the source code, that will be repeated is in braces,
}

Lets view each stage of cycle declaration more closely.

Count declaration: int type is used for the counter. The name of the variable-counter does not matter. You should
initialize the primary value, for example by 0.

Counter operation conditions: it is all easy. Here you determine a condition, and if it is true, the cycle goes on.
Otherwise the cycle is ended. For example in out case:
a < Bars

It is clear, that the cycle will go on while the variable-counter is less than variable Bars. Suppose, variable Bars=10,
then at each move over the cycle, the variable will increase by 1 until it reaches 10. After that the cycle stops.
Counter change: if we do not change the counter (in our case increase it)? The cycle will never end, because the
condition will never be fulfilled. For better understanding of the cycle meaning, I have written a code that will perform
a cycle with describing comments:
// the cycle:
// double AveragePrice=0.0;
//
// for(int a=0;a>
// {
//

AveragePrice+=High[a];

// }
//
// will be performed in this way:
//
double AveragePrice=0.0;
int a=0;

AveragePrice+=High[a];
a++;

// now a=1, suppose Bars=3.


// then the cycle goes on, because Bars > a

AveragePrice+=High[a];
a++;

// a=2

AveragePrice+=High[a];
++;

// a=3

// the conditions is not fulfilled any more, so the cycle


// stops, because a=3 and Bars=3

Now you should understand how the cycle works. But you should know some more details.
Cycle operation conditions can be different. For example like this:
a>10

// the cycle works while a>10

a!=10

// the cycle works while a is not equal to 10

a==20

// while a is not equal to 20

a>=2

// while a is more or equal to 2

a<=30

// while a is less or equal to 30

The counter can be changed in a different way. For example, you do not have to increase it each time by 1. You can do
like this:
a--

// the counter will each time decrease by 1

a += 2

// the counter will each time increase by 2

Beside, you can place the counter change inside the cycle body. For example so:
for(int a=0; a<Bars;)
{
AveragePrice+=High[a];
a++; // the counter changes inside the cycle body
}
>

Also it is not necessary to declare the variable-counter in the cycle. You can do it another way:
int a = 0;
for(;a < Bars;)
{
AveragePrice += High[a];

a++; // the counter changes inside the cycle body


}

If the cycle body contains only one operator, for example like this:
for(int a = 0; a < Bars; a++)
{
AveragePrice += High[a];
}

then it is not necessary to put braces:


for(int a = 0; a < Bars; a++)
AveragePrice += High[a];

It is all about cycles by now. There are other cycle types, but we will discuss them at the next lesson. Now you should
get, when to use the cycles and remember the syntax. Try to write several cycles, that will show the counter values
through MessageBox() function. Try to write a discontinuous cycle and see what will happen after start.

Conditions
There is one more important thing that you will always use conditions. Our life contains a lot of conditions and action
that follow these conditions. Very often we think by conditional clause. For example: If I have enough time, I will read
this book. If not, then its better to read a magazine. You can generate hundreds of such conditions and actions. But
how can we write them in MQL4? Here is an example:
// of course the conditionsn should be written in MQL4
if( I have enough time )
{
// here we place any actions, directions in MQL4
will read this book;
}
// if the first condition is not fulfilled,
// the second is fulfilled
else
{
read a magazine;

// code

Now you should understand the syntax of conditions. Lets view conditions, fully written in MQL4 language:
int a = 10;
int b = 0;
if(a > 10 )
{
b = 1;
}

else
{
b = 2;
}
MessageBox("b=" + b,".");

Everything is quite easy. What is the value of b after the completion? Of course b=2, because the condition a > 10 is not
fulfilled. It is easy. By the way, it is not necessary to use the key word else:
int a = 10;
int b = 0;
if(a > 10)
{
b = 1;
}

In this case if a condition is not fulfilled, the code block that follows the condition inside braces is omitted. In our case
after fulfilling b = 0. Also pay attention on the way, the conditions are built. We know that different types of variables
can acquire different values, for example:






int - integers (1, 60, 772);


double with a floating point (1.0021, 0.221);
string only lines ("Word", "Some text.");
bool only true or false (true, false).

So, the conclusion is: in conditions compare variables only with the values, they can accept, for example:
int Integer=10;
double Double=1.0;
string String="JustWord";
bool Bool=true;
if(Integer<10) // the condition is correct
{
MessageBox("It works!","Really!");
}
if(Double!=1.0) // the condition is correct
{
MessageBox("works!","Simple!");
}
if(String==10) // this is nonsense!!
// we found the variable
//String with string type, but 10 is int
{

MessageBox("Wrong type","u can't c this");


}
if(String!="Word") // ok
{{
// ...
}
if(Bool==true) // correct
{
// ...
}

Note, that we make comparisons using condition operators (==, !=, >, <, >=, <=). For string and bool types use only
== and != comparisons.
Now lets get acquainted with the meaning of inclusions. Yes, you can use conditions in cycles and cycles in
conditions; you can use conditions in other conditions and so on. For example:

int a=0;
double b=0.0;
bool e;
if(a==0)
{
for(int c=0;c<Bars;c++)
{
b+=High[c];
}
if(b>500.0)
{
e=true;
}
else
{
e=false;
}
}

The next example shows another way of using conditions:

int a=0;
int result;

if(a==0)
{
result=1;
}
else if(a==1)
{
result=2;
}
else if(a==2)
{
result=3;
}
else
{
result=4;
}

If in case of one condition default you have another condition, write it after the key word else, like in the code above.
This will also work. The number of other conditions is unlimited. If actions of condition fulfillment fit one operation,
you may omit braces like in cycles:
if(a==1)
{
b=2;
}
// or this way:
if(a==1)
b=2;

Complex Conditions
Very often one condition is not enough. You need to compare many parameters; here you have to do with complex
conditions. For example, if I have enough time and patience, I will learn MQL4 language. We can write it as a code:
if((enough time) && (enough oatience))
{
I will learn MQL4 language;
}

It means you should first divide complex conditions into simple conditions, put them into brackets, and put && (logical
AND) or || (logical OR) between them. If both conditions should be true, put && (AND). If only one conditions should
be true, put || (OR). Here is an example:
nt a=10;
int b=20;

if((a>5) && (b<50))


MessageBox("Its works!","Yes");

Beside you can enclose and combine as much conditions, as you need:
int a=10;
int b=20;
if ( ((a>5) || (a<15)) && ( b==20))
MessageBox("It works, too!","Yes");

All Together
Using together complex and simple conditions, cycles you may write a very complicated code. Almost every
mechanism can be described using these plain structures of MQL4 language. If you understand, how these simple
things are written and operate, you will understand a half of MQL4 or any other programming language! It is really
very easy! All you need is practice. Try to write as much scripts as you can, in order to remember the syntax and get the
practice. Besides, view the samples in the attached file examples.mq4 and try to understand them.

Other Built-in Variables and Arrays


You already know such arrays as High[], Low[], Volume[] and a variable Bars. Here are some more useful variables:
double Open[]

// the array of prices of the current


// chart opening bars

double Close[] // the array of prices of the current


// chart closing bars
double Bid

// the last known buying price in


// the current currency pair

double Ask

// the last known selling price in


// the current currency pair

Conclusion
So, you have learnt a lot of new things. Probably you have a mess in your head. Reread the text, remember, practice and
try to get the meaning. I promise, very soon everything will straighten out. What is written in this article is the basis of
the whole MQL4 language. The better you understand this material, the easier your further study will be. I will say
more it will be much easier to study further, because the material, described in this article, is the most difficult part. In
next articles we will study different peculiarities of MQL4 language and will view other integrated functions that
provide great possibilities for programming.

MQL4 Language for Newbies. Difficult Questions in Simple Phrases. [ ru ]


Introduction
This is the second article from the series "MQL4 Language for Newbies". The first article "MQL4 Language for
Newbies. Introduction" described what can be done using MQL4, we learned to write simple scripts, studied out what a
variable is, learned to work with variables, analysed functions, arrays, built-in arrays and variables, cycles 'for' and
simple and complex conditions. Now we will examine more complex and advanced constructions of the language, learn
new options and see, how they can be applied in everyday practice. You will get acquainted with a new cycle type
'while', new condition type 'switch', operators 'break' and 'continue'. Besides you will learn to write your own functions
and work with multidimensional arrays. And for a dessert I have prepared an explanation about a preprocessor.

Advice
Do not start reading this article not having fully understood the first one. You will make a lot of errors and still will
understand nothing. This article is based on the old material, so do not hurry! And I want to make you easy - the
difficulties that you will meet when learning the new material, are deceitful. The time will come, when you will not
have to think over how the cycles are written, what conditions to put - everything will be done mechanically. The more
you work with MQL4 language, the easier it will be for you to use it.

New Type of Cycles - while


I would like to mention, that the cycle 'for', described in the previous article, is a universal one and can substitute for
any other cycle type that we will learn now. But it is not always convenient and suitable. Sometimes it is more efficient
to use while. Soon you will understand, the use of which cycle type is more rational. Let's make a task in two ways:
let's find a total volume of all bars, using both cycles and see the difference:
// using the cycle for
double sum = 0.0;
for(int a = 0; a < Bars; a++)
sum += Volume[a];
// now using while, the result is the same
double sum = 0.0;
int a = 0;
while(a < Bars)
{
sum += Volume[a];
a++;
}

You see, now the counter is declared and used separately. 'While' here shows that while the condition is true, the cycle
goes on. Here is a general form:
while(condition of cycle fulfillment)
{
code
}

Here is an easier example:

while(I haven't eaten up the apple) // condition


{
// what to do, if the condition is not fulfilled
bite more;
}

In fact the cycle 'while' differs from the cycle 'for' only in the absence of a counter. If you don't need it, use while,
though it is not necessary. For example, I often use while with a counter, it is a matter of taste. Like in case with for, if
the cycle body includes only one instruction, you can omit bracers. Also for your development remember the meaning
of the word iteration. It is one of multiple operations (repetitions), undertaken by the cycle. I.e. performing a cycle
body once means that one iteration is performed.

New Type of Conditions - switch


Like in case with cycles, it should be noted that switch can be substituted by a combination of familiar to you
conditions 'if' and 'else'. The construction 'switch' is used when you need to perform some actions depending on the
value of a variable. This is like an ordinary mode switch in a microwave oven. For example, imagine that you write an
Expert Advisor, and it changes its behaviour depending on the market situation. Let a variable int marketState be
responsible for it. It may take the following meanings:





1 - uptrend
2 - downtrend
3 - flat

No matter how this position is defined, our task is to realize some kind of mechanism, so that depending on the market
situation the Expert Advisor performed corresponding actions. Well, you know how to do this. The most evident
variant is the following:
if(marketState == 1)
{
// trading strategy for an uptrend
}
else
if(marketState == 2)
{
// strategy for a downtrend
}
else
if(marketState == 3)
{
// strategy for a flat
}
else
{
// error: this state is not supported!
}

Here are some peculiarities:




all conditions are conducted with one and the same variable;
all conditions come to comparing the variable to one of the meanings that the variable can accept.

So, all this refers also to the switch structure. Here is a code, using switch, the result is the same:
switch(marketState)
{
case 1:

// trading strategy for an uptrend


break;

case 2:

// strategy for a downtrend


break;

case 3:

// strategy for a flat


break;

default: // error: this state is not supported!


break;
}

Note, that first we define, what variable will be compared:


// switch - key word, marketState // a variable for comparison
switch(marketState)

and then indicate, what should be done in specific cases:

case 1:

// case - key word;

// trading strategy

// if marketState is equal to 1, then

// for an uptrend

// perform this code

break;

// key word that indicates


// the end of actions in this case

case 2:
// startegy for

// if marketState is equal to 2, then


// perform this

// a downtrend
break;
case 3:

// end
// identical

// strategy for flat


break;
default:

// otherwise, perform this

// error: this
// state is not
// supported!
break;

In a general view switch has the following form:


switch(a variable for comparison)

{
case [a variable value]:
// a code for this case
break;
case [another value of the variable]
// a code for this case
break;
default:
// a code for all other cases
break;
}

Use switch, when comparing one variable to several values, and a certain code block corresponds to a value. In other
cases use a common combination of 'if' and 'else' conditions. Sometimes you need to perform a code in several values
of a variable. For example, if marketState == 1 or 2, then perform a certain code. This is how it can be done using
switch:
switch(marketState)
{
case 1:

// if marketState is equal to 1

case 2:

// or if marketState is equal to 2, then


// perform this
break;

default: // in any other case perform


// this code
break;
}

Operators: continue and break


We have just seen the operator break. It is used to escape from the body of switch. Besides you can use it for escaping
from a cycle. For example, if you don't need the execution of a cycle in some conditions. Suppose we need to find the
amount of first bars, needed to enclose 1000 points. We can write the following code:
int a = 0;
double volume = 0.0;
while(volume < 1000.0)
{
volume += Volume[a]; // equivalent to volume = volume + Volume[a];
a++;
}
// now variable "a" includes the amount of bars, the volume of their sums

// is no less than 1000 points

Now let's write an analogous code, using the operator break:


int a = 0;
double volume = 0.0;
while(a < Bars)
{
// if the volume is exceeds 1000 points, then
if(volume > 1000.0) // exit the cycle
break;
volume += Volume[a];
a++;
}

You see, the operator break is easy-to-use and allows to avoid unwanted cycle iterations. One more useful operator
continue is intended for 'omitting' unwanted iterations. Suppose we need to calculate a total volume, but we mustn't
take into account the volume of bars in the moments of important news. As you know, important news involve large
volumes of points. Let's pretend to be naive children and suppose that the bar volume 50 points and more is news. To
solve this task, let's use the continue operator:
int a = -1;
double volume = 0.0;
while(a < Bars)
{
a++;
// if the volume exceeds 50 points, then it must
// be news, omit it
if(Volume[a] > 50.0)
continue;
volume += Volume[a];
}

You see, the use of the continue operator is quite trivial, but sometimes it may help you. It is clear, that this script is
intended for small timeframes.

Writing Own Functions


But why do we need them? The fact is, that very often you can find duplication of your code. I.e. you will use one and
the same set of instructions in different cases. To save your time and strength you can write this duplicated code into a
separate function. And when you need it, you can simply write the name of the function and it will do everything for
you. Let's view how it works. Suppose you need to find the color of a candlestick. It is known that a white candlestick
is the one that closed higher than opening, the black one - vice verse. Let's write a code for determining a color of a
candlestick:
bool color; // as there are only 2 variants
// (white or black candlestick),

// then suppose that the velue


// false corresponds to a black
// candlestick, and true - white
if(Close[0] > Open[0])
color = true;

// white candlestick

if(Open[0] > Close[0])


color = false;

// black candlestick

That is all, now the variable color contains the color of the last candlestick. To determine the color of another
candlestick, for example, the last but one, you need to change the index 0 to 1. But aren't you going to put this code
everytime you need to find the color of a candlestick? And what if there are dozens of such cases? That is why we need
functions. Let's think, how it should work. Such function should accept one argument - the index of a candlestick,
which color you need to determine, and return the color - a variable of bool type. Let's imagine that the function is
written and we activate it:
bool color; // here will be the color of a wanted candlestick
color = GetColor(0);

As you have guessed, our function is named GetColor. In this function call we wanted to find the color of the last
candlestick. That is why the only argument is equal to zero. The function returns the color of a candlestick, so we make
an assignment at once. It is a very important moment! A variable is created inside the function, then its value will
replace the function call. Ultimately the function call and the code of the function determining, described above, will
give the same result - the variable color will contain the color of the last candlestick, but using functions we spend less
strength.
And now let's unexpectedly get back to the code of an empty script. The fact is, that it already contains a full
description of the function start(). The most interesting thing is that all this time you've been writing scripts in this
function! When you start your script, the terminal activates the function start(). Let's examine the code of an empty
script:
int start()

This line is very important! It includes the name of the function, i.e. a keyword, which you will write in order to
activate this function. In our case it is 'start'. It also contains type of a return value - int. It means, that after the
performance of the function it will return us some value of int type. The brackets contain list of arguments, but in our
case the function does not accept any parameters.
Then in bracers you see the function description, i.e. a code that will be performed at function call:
{
//---// a code that will be performed
// at the function call.
//---return(0);
}

It is clear that we wrote a code in the body of start() function. At the end of the function we see the operator return,
which returns the function value. In our case it returns zero.
Now look at the general form of writing a function:

[type of return value] [function name] ([list of arguments])


{
// function code
return([a value, which the function returns]);
}

Now let's go back to our candlesticks and GetColor function. Look at the code of this function:
bool GetColor(int index)
{
bool color;
if(Close[index] > Open[index])
color = true;

// white candlestick

if(Open[index] > Close[index])


color = false;

// black candlestick

return(color);
}

Let's dwell on the first line:


bool GetColor(int index)

Here we have: bool - type of a return value; GetColor - function name; int - type of argument; index - argument name.
Note, we use index inside the function body, but in the function call this name is never mentioned. For example:
bool lastColor = GetColor(0);

Then:
{
bool color;
if(Close[index]>Open[index])
color=true;

// white candlestick

if(Open[index]>Close[index])
color=false;

// black candlestick

This function body is a general code, which will be performed at each function call. After that:
return(color);
}

The operator return indicates, what the function should return. The return value should correspond to the type,
determined at the very beginning. If needed, you may use several operators 'return' in one function, for example:
bool GetColor(int index)
{
if(Close[index] > Open[index])
return(true);

// white candlestick

if(Open[index] > Close[index])


return(false);

// black candlestick

It is clear, that the use of several return operators allowed to avoid the variable color. Besides, in the operator return
you may use even logical expressions:
return(Close[index] > Open[index]);

It is possible, because the operators of comparison also return variables of bool type (true or false) like some other
common functions. Looks like difficult, but soon you will get used to it.
Now let's get back to a list of arguments. Only the argument int index is used in our function. If you need to use several
arguments, enumerate them comma separated:
bool SomeomplicatedFunction(int fistArgument, int secondArgument,
sting stringArgument)

In order to refer to the arguments, use their names like in the previous function. When a function call with several
arguments, pay attention to sequence of arguments order: do not mix anything! If the function should not return any
value, use the keyword void, to indicate it. Note, that the return operator in this case is not used:
void function()
{
// code
}

One more detail: you may set the values for the function arguments on default. What is this? Suppose you have written
a complex function that includes 5 arguments, which influence its behaviour. But several last arguments almost always
are used with the same values. Only for two dozens of function call you need to use different values. In order not to
indicate each time the values of the last arguments, which are almost always the same, default values of arguments are
used. In such a case you simply omit the last arguments, as if they do not exist, though actually they are used, but the
values are assigned on default. When you meet that special case, you indicate all the arguments. Let's see how we can
declare a function with default arguments:
void someFunction(int argument1, int argument2,
int specialArgument = 1)
{
// code
}

You see, everything is easy: we assign a needed value to a needed argument and now it can be omitted at function call:
someFunction(10,20);

// we omitted the last argument, but


// actually it is assigned a value by default

someFunction(10,20,1); // this activation is fully identical to the previous one


someFunction(10,20,2); // here we indicate another value,
// it is a rare case

You can indicate as much default values of arguments as you want. But remember an important rule: they all should be
placed at the end. For example:
void someFunction(int argument1, int argument2,

int specialArgument = 1)

// all right

void someFunction(int argument1, int argument2 = 10,


int specialArgument=1)

// all right

void someFunction(int argument1, int argument2 = 10,


int specialArgument)

// wrong! default
// values must stay
// at the end of the
// list of arguments

void someFunction(int argument1 = 0, int argument2 = 10,


int specialArgument = 1) // you can assign
// default values
// to all arguments

Multidimensional Arrays
You will often use arrays during programming, and in major cases one-dimensional arrays will be enough. But in some
cases you will need two-dimensional, three-dimensional arrays. Now you will learn to use them.
To begin with, let's visually present one-dimensional arrays, revise declaration, initialization, indexes and value:

Any one-dimensional array can be presented as a row of values of one type. Look, how different references to a onedimensional array will be processed:

Two-dimensional arrays are like common tables, look:

As seen from the picture, two-dimensional arrays already have two indexes for reference to the value: the first index
determines a row, the second index - a column. Like in one-dimensional arrays, a list of values is used for
initialization. This is how the values of the table cells are referred to:

You see, everything is clear. Let's see, how we can go through all values of a two-dimensional array. 2 cycles should be
used:
int array2D[3][3]={10,20,30,
40,50,60,
70,80,90};
for(int y=0;y<3;y++)
for(int x=0;x<3;x++)
MessageBox("array2D["+y+"]["+x+"]="+array2D[y][x]);

In this example the referencing goes downwards from left to right. Just for training try to change the direction, for
example upwards.
Three-dimensional arrays differ only in the presence of one more index for referencing to cells values. A threedimensional array can be easily presented as several tables (two-dimensional arrays). This is how we can go through all
the elements of a three-dimensional array:
int array3D[3][3][3] = {11, 12, 13,
14, 15, 16,
17, 18, 19,
21, 22, 23,
24, 25, 26,
27, 28, 29,
31, 32, 33,
34, 35, 36,
37, 38, 39};
for(int z = 0; z < 3; z++)
for(int y = 0; y < 3; y++)
for(int x = 0; x < 3; x++)
MessageBox("array3D["+z+"]["+y+"]["+x+"]=" +
array3D[z][y][x]);

Thoroughly study out two- and tree-dimensional arrays - it is very important. Once again very attentively look through
the explanatory pictures. A lot of different tasks are solved using arrays, so devote enough time to them and they will be
very useful for you in future. If you understand the principle of working with arrays, you will have no trouble working
with any n-dimensional array.

Some Functions for Working with Arrays


Let's start with simple functions.
int ArraySize(object array[]);

This function returns the amount of elements that the array contains. It works with all types. For example:
// create two different arrays
int arrayInt[] = {1, 2, 3, 4};
double arrayDouble[] = {5.9, 2.1, 4.7};
// here store the amount of elements
int amount;
amount = ArraySize(arrayInt);

// note:
// to define a specific
// array, you need to indicate
// only its name.

// Now amount is equal to 4

amount = ArraySize(arrayDouble);

// amount is equal to 3

Next function:

int ArrayInitialize(object array[],double value);

ArrayInitialize
assigns a value to all array elements, returns the amount of elements, to which a value was assigned. Use this function
with arrays of int and double type.

Next:
int ArrayMaximum(double array[], int count = WHOLE_ARRAY,
int start = 0);
int ArrayMinimum(double array[], int count = WHOLE_ARRAY,
int start = 0);

These two functions return the index of a maximal and minimal cell value. To use them, simply indicate in what array
they should be looked for:
int array[] = {10, 100, 190, 3, 1};
// will be returned 1, because array[1] - maximal value
ArrayMaximum(array);
// will be returned 4, because array[4] - minimal value
ArrayMinimum(array);

Next:

int ArrayDimension(object array[]);

Using these functions you can determine the dimensionality of an array, I.e. you can determine, whether it is onedimensional, two-dimensional or n-dimensional. For example:
int array1D[15];
int array4D[3][3][3];
ArrayDimension(array1D); // get 1
ArrayDimension(array3D); // 3

Here are more complex and useful functions:


int ArraySort(double&array[], int count = WHOLE_ARRAY, int start = 0,
int sort_dir = MODE_ASCEND);

This function sorts elements. If you do not directly indicate the arguments on default, for example this way:

int array[5] = {1, 10, 5, 7, 8};


ArraySort(array);

elements will be sorted ascending. You can use additional parameters to specify the function behaviour:





int count - the number of elements that should be sorted


int start - the index of an element, from which the sorting should be started
int sort_dir - the direction of sorting (ascending - MODE_ASCEND or descending - MODE_DESCEND)

Here you should wonder: what is MODE_ASCEND and MODE_DESCEND?? According to int, it must be an integer!
Don't be nervous, everything will strighten out in the next part - "Preprocessor". For example, if you need to sort
descending 5 elements starting from the second, indicate something like this:
ArraySort(array, 5, 1, MODE_DESCEND);

And the last function for today:


int ArrayCopy(object&dest[], object source[], int start_dest = 0,
int start_source=0, int count=WHOLE_ARRAY);

It is used for copying one array into another. Let's view the obligatory parameters:




dest[] - into which array to copy


source[] - from which array to copy

Optional parameters:





start_dest - index of an array element, into which the copying is performed


start_source - index of an array element, from which the copying is performed
int count - the amount of elements for copying

The function returns the amount of copied elements. Use ArrayCopy very carefully: make sure that arrays have enough
capacity, when you copy in them!

Preprocessor
What is this? Preprocessor is a special mechanism, intended for processing a source code. I.e. first the preprocessor
prepares a code and then conveys it for compilation. Today we will learn one more useful option - constants.
What is the main point? To understand this, let's remember an example from the part about switch:
switch(marketState)
{
case 1:
// trading strategy for an uptrend
break;
case 2:
// strategy for a downtrend
break;

case 3:
// strategy for a flat
break;
default:
// error: this state is not supported!
break;
}

Here we activated a mechanism, that acts in different ways depending on the market state. Remember? So, it would be
easier and more discriptive to write something like TREND_UP, TREND_DOWN, FLAT instead of 1, 2 and 3:
switch(marketState)
{
case TREND_UP:
// trading strategy for an uptrend
break;
case TREND_DOWN:
// strategy for a downtrend
break;
case FLAT:
// strategy for a flat
break;
default:
// error: this state is not supported!
break;
}

In this case a source code appears much easier to understand and more vivid, doesn't it? So, constants allow to
substitute TREND_UP, TREND_DOWN and FLAT by corresponding values 1, 2 and 3 before the compilation. All
you need is to indicate, what the preprocessor should change. It is done by means of the preprocessor directives,
which start from a special symbol "#". The preprocessor directives should be placed in the beginning of a source file
together with other directives. Let's look at a complete example of using constants:
//+------------------------------------------------------------------+
//|

preprocessor.mq4 |

//|

Copyright 2007, Antonio Banderass. All rights reserved |

//|

banderassa@ukr.net |

//+------------------------------------------------------------------+
#property copyright "Copyright 2007, Antonio Banderass. All rights reserved"
#property link
#define TREND_UP

"banderassa@ukr.net"
1

#define TREND_DOWN 2

#define FLAT

//+------------------------------------------------------------------+
//| script program start function

//+------------------------------------------------------------------+
int start()
{
MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" + TREND_DOWN +
" FLAT=" + FLAT);
return(0);
}

Note, that we have placed the constants declaration in the beginning of the file, under other preprocessor directives.
Let's examine the declaration more closely:
#define TREND_UP 1

First we write the key word #define. It shows to the preprocessor that after that comes constant declaration. Then we
write the name of the constant, its identifier, i.e. a word, through which you will refer to the constant value. In our
case it is TREND_UP. The value - 1 comes after that. Now when the preprocessor sees TREND_UP in the source code,
it will replace it by 1, the same is with all other constants. Here is the source code of our example before processing by
a preprocessor:
int start()
{
MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" +
TREND_DOWN + " FLAT=" + FLAT);
return(0);
}

and after:
int start()
{
MessageBox("TREND_UP=" + 1 + " TREND_DOWN=" + 2 +
" FLAT=" + 3);
return(0);
}

Now you should understand, what MODE_ASCEND and MODE_DESCEND from the previous part mean. They are
constants with correspondent values.

Conclusion
So, you have learned a lot of new material from this article: new cycle type - while; new condition type - switch;
operators break and continue. You learned to write own functions and work with multi-dimensional arrays, learned how
to use constants. All this is your main instrument, a basis for writing more advanced things, like user's indicators and
expert advisors. That is why make sure, that you have thoroughly studied out the material of the article, because it is
very important and will be constantly used in future.

MQL4 Language for Newbies. Technical Indicators and Built-In Functions [ ru


]
Introduction
This is the third article from the series "MQL4 Language for Newbies". In the first two articles we learned the
fundamentals of MQL4, the basis of further development. Now we will learn to use built-in functions and functions for
working with technical indicators. The latter ones will be essential in the future development of your Expert Advisors
and indicators. Besides we will see on a simple example, how we can trace trading signals for entering the market, for
you to understand, how to use indicators correctly. And at the end of the article you will learn something new and
interesting about the language itself.

Mathematical Functions
Let us start with the most simple, but still used and helpful mathematic functions.

MathAbs
Function Prototype:
double MathAbs(double value)

It is a very simple function, which returns the absolute value (number module). It means, if you, for example, use it for
a negative number, as a result you will get a positive number.
Example of its usage:
int a=-10;
double b=-20.0;
double c=7.0;
a=MathAbs(a); // now a is equal to 10
b=MathAbs(b); // now b is equal to 20.0
c=MathAbs(c); // the value of c will not change, for it was positive

MathCeil, MathFloor and MathRound


Functions' prototypes:
double MathCeil(double x)
double MathFloor(double x)
double MathRound(double value)

These three functions are very much alike: all they round off a number to the whole number. But each of them has its
own peculiarity:
MathCeil rounds up in such a way, that even if we have one thousandth of a whole number (for example, 1.001), it is
considered a whole number. I.e. a number is rounded up to a higher value. For example:
double a;
a=MathCeil(1.001);

// a=2.0, even one thousandth is rounded off to a whole number

a=MathCeil(1.999);

// a=2.0

a=MathCeil(-1.001); // a=-1.0, it is correct, because -1.0 is more than -1.001

a=MathCeil(-1.999); // a=-1.0, it is correct, -1.0 is more than -1.999

MathFloor makes the same, as MathCeil, but quite opposite. I.e. if we need to round down a positive number, it will
simply lose a fractional part:
double a;
a=MathFloor(1.999); // a=1.0, no matter how large the fractional part is, it will be
taken away
a=MathFloor(1.001); // a=1.0
a=MathFloor(-1.001); // a=-2.0, correct, because -2.0 is less than -1.001
a=MathFloor(-1.999); // a=-2.0, correct, -2.0 is less than -1.999

MathRound rounds off numbers in a familiar to us way. I.e. if a fractional part is large (0.5 and more), it will be
rounded off to 1. If the fractional part is small (less than 0.5), it will be rounded off to 0, i.e. it will be simply omitted.
Examples:
double a;
a=MathRound(1.1);

// a=1.0, the fractional part is too small (0.1)

a=MathRound(1.57);

// a=2.0, the fractional part is enough to be rounded off to 1

a=MathRound(-3.1);

// a=-3.0 not enough

a=MathRound(-6.99); // a=-7.0 enough

MathMax
MathMin
Functions' prototypes:
double MathMax(double value1, double value2)
double MathMin(double value1, double value2)

These two functions are very much alike. They accept 2 arguments and return accordingly the largest and the smallest
one. Examples:
double a;
a=MathMax(50.0,1.0);

// a=50.0

a=MathMin(10.0,12.0); // a=10.0

MathPow
Function prototype:
double MathPow(double base, double exponent)

This function allows raising a number base to the power exponent. Examples:
double a;
a=MathPow(5.0,2.0);

// a=25.0, 5 to the power 2

a=MathPow(2.0,8.0);

// a=256.0, 2 to the power 8

a=MathPow(25.0,0.5); // a=5.0, you know, a number to the power 0.5 is its square
root

MathSqrt
Function prototype:
double MathSqrt(double x)

Take the square root using this function. But do not try to take the square root of a negative number. In this case a zero
will be returned. Examples:
double a;
a=MathSqrt(9.0);

// a=3.0

a=MathSqrt(25.0);

// a=5.0

a=MathSqrt(-256.0); // a=0.0, I explained

MathLog
Function prototype:
double MathLog(double x)

Does anyone remember, what a logarithm is? Logarithm of a to the base b is equal to the power, to which you need to
raise b, to get a. Widely used are logarithms to the bases e (Euler number) - natural logarithms (lna) and to the base 10 common (Brigg's) logarithm (lg a). The more information about logarithms can be found at:
http://en.wikipedia.org/wiki/Logarithm
So, the function MathLog is intended for taking natural logarithm of the number x. Do not try to take natural logarithm
of negative numbers or zero. In this case you will get -1. Examples of using the function:
double a;
a=MathLog(10.0);

// a=2.30258509

a=MathLog(0.0);

// a=-1.0, incorrect

a=MathLog(-10.0); // a=-1.0, incorrect

MathExp
Function prototype:
double MathExp(double d)

This function returns number e, raised to the power d. Many of you must have forgotten this number.
e is a mathematical constant, base of natural logarithm, irrational and transcendental number. e =
2,718281828459045 Sometimes e is called Eulerian number or Napierian number. Plays an important role in the
differential and integral calculus. More information about Eulerian number is at:
http://en.wikipedia.org/wiki/Eulerian_number
If you indicate a very large degree, overflow will take place, zero will be returned. How large should be the degree for a
mistake? Let us find it, let us conduct a small experiment:
double exponent=1.0; // here the degree value will be stored
double result=1.0;

// result, returned by the function

int i=0;

// number of cycle iterations

while(result!=0.0)
overflowing)

// while the result is not equal to zero (while there is no

result=MathExp(exponent); // remember the result


exponent*=10.0;

// increase the degree

i++;

// the next iteration is over

}
MessageBox("i="+i); // result of the experiment

The following happens: each time we try to call the function MathExp and with each iteration the degree is increased
10 times until finally we get the overflow and zero is returned. I got the following result: i=310. It means you can use as
a degree numbers 1*10 to the power 309 (just imagine a number at a length of 309 digits!!). So I think you should not
be afraid of the overflow.

MathMod
Function prototype:
double MathMod(double value,double value2)

This function allows finding a residue of division. For example, dividing 5 by 2 we get 2 and residue 1. The first
argument value - dividend, value2 - divisor. The residue is returned. Examples:
double a;
a=MathExp(5,2); // a=1.0
a=MathExp(10,3); // a=1.0, correct
a=MathExp(50,10); // a=0.0, divided without residue

MathRand and MathSrand


Functions' prototypes:
int MathRand()
void MathSrand(int seed)

MathRand returns one by one pseudorandom integers in the range from 0 till 32767. Here you may have some
questions: what does "pseudo" mean? What a strange range, and what if I need from 5 to 10? Why exactly 32767? Here
are the answers:
"Pseudo" means that the numbers are not entirely random and depend on something. Suppose, you have written a
script, which returns 5 pseudorandom numbers. For example:
int a=0;
while(a<5)
{
MessageBox(random=+MathRand());
a++;
}

Well, the numbers are really random, but if you start the script once again, the sequence will be always the same. It is
so, because there is a number, from which the function MathRand repulses. Let us call this number the beginning
number. In order to change it, use another function - MathSrand. This function accepts a single argument - the
beginning number, on which all pseudorandom numbers will depend. Imagine that the beginning number is a fruit,
from which a tree (random numbers) will grow. On default the beginning number is 1. So, in order to get a really
random sequence, we first need to assign a unique value to the beginning number. How can we do this? There is one

more function - TimeLocal, which does not have arguments and returns the number of seconds, passed after 00:00 the
1st of January, 1970. This function suits ideally, because in most cases we will receive a unique number. Didn't you get
tangled yet? It looks like this:
int a=0;
MathSrand(TimeLocal()); // assign a unique value to the beginning number
while(a<5)
{
MessageBox(random=+MathRand());
a++;
}

Now each time we will get a new sequence. Let us go on.


From 0 to 32767. Why 32767? Look: the maximal value that int can accept is 2 to power 16 (because the value of int
variable occupies 16 bits in the computer memory, not considering the sign), it is equal to 32768, but as we count from
zero, we need to subtract 1. So we get 32767.
In order to get any necessary range, use the operator % - residue in division. For example, if we need to get random
numbers in the range from 0 to 5:
int a=0;
MathSrand(TimeLocal());
while(a<5)
{
MessageBox(random=+MathRand()%6);
a++;
}

Please note, that we wrote MathRand()%6, not MathRand()%5 - while our range starts from zero, we need to add 1.
Now suppose we need random numbers in the range from 5 to 10:
MessageBox(random=+MathRand()%6+5); // just add the necessary shift

The same is when we need to get a range with negative numbers, for example from -5 to 5:
MessageBox(random=+MathRand()%11-5);

If you need only negative numbers, multiply the result by -1. For example we need the range from -10 to -20:
MessageBox(random=+(MathRand()%11+10)*(-1));

If you need to get a non-integral, for example in the range from 0.0 to 1.0 accurate to thousandth, use the following
code:
MessageBox(random=+MathRand()%1001/1000.0);

First we create a random number in the range from 0 to 1000 and then divide it by 1000.0. Note, that we must divide
exactly by 1000.0 (with a floating point), not by 1000 (integer). Otherwise we get zero, because it will be rounded off.

Trigonometric and arc-trigonometric functions


Trigonometric functions are mathematic functions from an angle. They are important in the analysis of periodical
processes. Very close to them are arc-trigonometric functions. More information is here:
http://en.wikipedia.org/wiki/Trigonometric_function

http://en.wikipedia.org/wiki/ArcSin
In MQL4 all these functions accept arguments in radians, not degrees. I.e. if you need to find sine of 20 degree, you
must first turn 20 degrees into radians. For example:
MathSin(20.0*3.14159/180.0);

I.e. 1 grade = pi / 180. It is convenient to declare and use the constant at the beginning of a program, if you often use
trigonometric functions:
#define PI 3.1415926535897

MathSin, MathCos, MathTan, MathArcsin, MathArccos and MathArctan


Functions' prototypes:
double MathSin(double value)
double MathCos(double value)
double MathTan(double x)
double MathArcsin(double x)
double MathArccos(double x)
double MathArctan(double x)

Let us dwell on the peculiarities of some functions. MathTan accepts values in the range from -263 to 263, if you
exceed the limits, the number will be indefinite. MathArcsin and MathArccos accept values in the range from -1 to 1,
otherwise you will get zero and the appropriate message in EA journal. MathArctan returns 0, if it accepts 0.

New Functions for Displaying Messages


By now you know only one function for displaying information - MessageBox. Now you will learn three more
functions that are very much alike, but have their own peculiarities.

Alert
Function prototype:
void Alert(...)

Displays a dialogue window containing your signals (information). At calling the function, you will hear a special
signal, which can be changed or disabled in the terminal settings: Service -> Settings -> tab Events. The window will
look like this:

You can change the size of the window for an easy viewing of a large amount of information. Besides, you can always
view the last callings of the function, because they are not deleted. You can also perform several callings successively,
you will get a window with an active last signal, and you do not need to click "OK" each time. You can use the function
similar to MessageBox:
Alert(signal type:+signalType);
Alert(random=+MathRand()%1001);

Though the intention was different. You are supposed simply to enumerate parameters for entering, comma separated.
I.e. it is like in the example above, but using "," instead of "+". I recommend using the second variant:
Alert(signal type:,signalType);
Alert(random=,MathRand()%1001);

Comment
Function prototype:
void Comment(...)

Similar function, identical in usage, displaying a message in the upper left corner of a chart. Here you do not have to
click anything to have the code performed. Use this function, for example, for showing the current state. Example:
Comment(some usefull information);

Print
Function Prototype:
void Print( ...)

One more analogous function, displaying messages in Expert Advisors' journal:


Print(processing...);

Besides, the journal saves all messages in a correspondent file (the name of the file corresponds to the date) on your
computer in the folder MetaTrader 4\experts\logs:

Also some notes about the three functions should be made. You cannot display arrays, simply indicating them, like a
parameter. They should be displayed element-by-element, for example like this:
for(int a=0;a<100;a++)
Alert("Close[",a,"]=",Close[a]);

You can display maximum 64 parameters in each function. Each calling of the function Alert is also written in an
Expert Advisor journal. The type double will be displayed accurate to 4 numbers after a point.

Technical Indicators
Almost all Expert Advisors use technical indicators. If you look at a simple EA included into the installation file
(MACD Sample), you will see that it uses technical indicators. Now you will learn how to get values of all available
technical indicators. There is a correspondent function to each technical indicator, which can count the value on any
available security and timeframe. And you do not have to bother, if this indicator is now open on a chart or not. It does
not matter.
Now let us view in details the parameters of technical indicators' functions. Actually the majority of them are repeated.
For example, all function we are going to dwell on, have similar 2 first arguments and 1 last for counting the values of
technical indicators:

symbol the first argument defining which financial security (currency pair) should be used for counting the
technical indicator values. I.e. to what chart the technical indicator should be used. To use an indicator on the
current chart, use the constant NULL (or 0). The current chart here means the chart, on which you will start
your script (Expert Advisor, indicator). If you need another security, you can use its name as a string
("EURUSD","GBPUSD" etc.).
timeframe the second argument, which defines on what timeframe the indicator should be used. If you need
a timeframe, used on the current chart, use 0 (zero). If you need another timeframe, use one of the predefined
constants:
 PERIOD_M1 - 1 minute
 PERIOD_M5 - 5 minutes

 PERIOD_M15 - 15 minutes
 PERIOD_M30 - 30 minutes
 PERIOD_H1 - 1 hour
 PERIOD_H4 - 4 hours
 PERIOD_D1 - 1 day
 PERIOD_W1 - 1 week
 PERIOD_MN1 - 1 month
shift the last argument defining on what bar the indicator should be used. Remember the first article: to find
the close price of the last bar we used indexes, starting from zero. I.e. Close [0] - close price of the last bar,
Close[1] - the last but one etc. Well, this argument works the same way as an index in arrays. To find the
value of the indicator on the last bar, shift must be equal to 0, on the last but one - 1 and so on.

Technical indicators very often use for counting mean values on several bars. I.e. they take different prices (opening,
closing, etc.) on several bars and find the mean value using a definite method. Also very often shifting is used. So
among the parameters you can find the following:




applied_price defines what type of prices should be used for getting the mean value. There are the
following predefined constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
ma_method defines a method, used for receiving mean values. There are the following predefined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly weighted moving average
period defines how many bars will be used for getting the mean value.
ma_shift shift of midline in bars. If the shift is positive, the line is shifted to the right. And on the contrary,
if the shift is negative, the line is shifted to the left.

The above described parameters will occur very often. So, when you see such parameters, you should understand that
this function uses mean values for the calculation of its values. To learn, how exactly the values are calculated, and
what part mean values take in it, use the link that is after a short description of each function.
One more important moment: all these indicators (functions) can be divided into two categories:

simple when an indicator has only one value. For example: Acceleration/Deceleration (AC),
Accumulation/Distribution (A/D), DeMarker (DeM) etc. I.e. the indicator has only one line/histogram, the
value of which is returned at calling the appropriate function. Here is an example of several simple indicators
used on one chart:

complex when an indicator has several values (lines). For example: Alligator, Average Directional
Movement Index (ADX), Bollinger Bands (BB), Average Convergence/Divergence (MACD) etc. In such a
case you should indicate, what value (line) the indicator should return. For this purpose in all functions of
complex indicators the parameter mode is used. Using certain constants you indicate, what should be
returned. Here is an example of several complex indicators used on one chart:

Each function description will be supported by a descriptive picture, examples of usage (different colors are used for
better visualization of what is in charge of what) and a link with the indicator description (how to use it in trading, the
meaning of the indicator). You are supposed to be acquainted with indicators and to use it in practice. I recommend
reading the description of functions in this article in order to understand how to use them, and view the examples. But
for remembering the assignment of each argument in future, use Help in MetaEditor. Open the window ToolBox using
hot keys Ctrl+T and go to the tab Help. There you will find the description of each parameter, as well as a convenient
list of all functions, so you will easily find what you need. The language of Help can be changed using menu View>Languages. After that restart MetaEditor.

Acceleration/Deceleration (AC)
The indicator Acceleration/Deceleration (AC) is used for changing the speed of price changes (acceleration,
deceleration). http://ta.mql4.com/indicators/bills/acceleration_deceleration
Function prototype:
double iAC(string symbol, int timeframe, int shift)

Parameters:





symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
shift defines, to what bar the indicator should be used.

Examples of usage:

double ac;
ac=iAC(0,0,0);
// acceleration of the last bar on the active chart and timeframe
ac=iAC(0,0,1);
// acceleration of the last but one bar on the active chart and timeframe
ac=iAC("GBPUSD",PERIOD_M30,0);
// acceleration of the last bar on the chart GBPUSD, timeframe - 30 minutes

Accumulation/Distribution (A/D)

The indicator Accumulation/Distribution (A/D) is used for confirming price changes through volume calculation.
http://ta.mql4.com/indicators/volumes/accumulation_distribution
Function prototype:
double iAD(string symbol, int timeframe, int shift)

Parameters:





symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
shift defines, to what bar the indicator should be used.

Examples of usage:

double ad;
ad=iAD(0,0,0);
// accumulation on the last bar on the current chart and period
ad=iAD(0,0,Bars-1);
// accumulation on the first available bar, active chart and period

ad=iAD("GBPUSD",PERIOD_M5,5);
// accumulation on the 6th last bar on GBPUSD, period - 5 minutes

Alligator
The indicator Alligator is the combination of 3 moving averages, using fractal geometry and nonlinear dynamics.
http://ta.mql4.com/indicators/bills/alligator
Function prototype:
double iAlligator( string symbol, int timeframe, int jaw_period, int jaw_shift, int
teeth_period,
int teeth_shift, int lips_period, int lips_shift, int ma_method,
int applied_price,
int mode, int shift)

Parameters:











symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
jaw_period - the period of averaging of the alligator's jaw (blue line)
jaw_shift - shift of the alligator's jaw
teeth_period - the period of averaging of the alligator's teeth (red line)
teeth_shift - shift of the alligator's teeth
lips_period - the period of averaging of the alligator's lips (green line)
lips_shift - shift of the alligator's lips
ma_method defines a method, used for receiving mean values. There are the following predefined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly weighted moving average
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
mode defines, the value of what you want to find (jaws, teeth or lips). For choosing use one of the constants:
 MODE_GATORJAW - line of the alligator's jaw (blue)
 MODE_GATORTEETH - line of the alligator's teeth (red)
 MODE_GATORLIPS - line of the alligator's lips (green)
shift defines, to what bar the indicator should be used.

Look, what the function arguments are responsible for, when using Alligator on a chart. Such analogy will help you:

Using the parameter mode, define what should be returned:

Examples of usage:
double jaw;

double teeth;
double lips;
jaw=iAlligator(0,0,13,8,8,5,5,3,MODE_SMA,PRICE_MEDIAN,MODE_GATORJAW,0);
// find the values of "jaws" (blue line) on the current chart and period.
// Here simple moving average is used, price average. Periods
// of averaging for jaws, teeth and lips 13, 8 and 8 accordingly. Shift:
// 5, 5 and 3 accordingly. The value is taken for the last bar.
teeth=iAlligator(EURUSD,PERIOD_H1,128,96,64,0,0,0,MODE_EMA,PRICE_TYPICAL,MODE_GATO
RTEETH,1);
// find the values of "teeth" (red line) on an hour chart EURUSD.
// Exponential moving average and typical price are used.
// Periods of averaging: 128, 96 and 64. Shift is not used. The value
// is taken for the last but one bar.
lips=iAlligator(GBPUSD,PERIOD_D1,21,18,13,5,3,0,MODE_SMMA,PRICE_WEIGHTED,MODE_GATO
RLIPS,5);
// find the values of "lips" (green line) on a daily chart GBPUSD.
// Uses smoothed moving average and weighted close price.
// Periods of averaging: 21, 18 and 13. Shift: 5, 3 and 0. The value
// is taken for the 5th last bar.

Average Directional Movement Index (ADX)


The indicator Average Directional Movement Index (ADX) is used to determine the presence of a price trend.
http://ta.mql4.com/indicators/trends/average_directional_movement
Function prototype:
double iADX(string symbol,int timeframe,int period,int applied_price,int mode,int
shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period the number of bars, used to find the mean value.
mode choose a line, the value of which will be received. Use the following predetermined constants:
 MODE_MAIN - the main line
 MODE_PLUSDI - line +DI
 MODE_MINUSDI - line DI
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double main;

// main line

double plusDi;

// line +DI

double minusDi; // line -DI


main=iADX(0,0,3,PRICE_CLOSE,MODE_MAIN,0);
// find the value of the main line on the active chart and period on the last bar.
// Uses averaging on 3 bars, uses close price.
plusDi=iADX(USDCAD,PERIOD_M1,6,PRICE_OPEN,MODE_PLUSDI,1);
// find the value of line +DI on the minute chart USDCAD on the second last bar.
// Uses averaging on 6 bars, uses open price.
minusDi=iADX(AUDUSD,PERIOD_H1,10,PRICE_HIGH,MODE_MINUSDI,5);
// find the value of line -DI on the hour chart AUDUSD on the 6th last bar.
// Uses averaging on 10 bars, uses maximal price.

Average True Range (ATR)

The indicator Average True Range (ATR) is used to determine the market volatility.
http://ta.mql4.com/indicators/oscillators/average_true_range
Function prototype:
double iATR(string symbol,int timeframe,int period,int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period the number of bars, used to find the mean value.
shift defines, to what bar the indicator should be used.

Examples of usage:

double atr;
atr=iATR(0,0,15,0);
// volatility of the last bar on the active chart and period.
// Uses 15 bars to get the mean value.
atr=iATR(EURUSD,PERIOD_M15,5,1);

// volatility of the last but one bar on a 15 minute chart EURUSD.


// Uses 5 bars to get the mean value.
atr=iATR(USDCAD,PERIOD_H1,32,0);
// volatility of the last bar on an hour chart USDCAD.
// Uses 32 bars to get the mean value.

Awesome Oscillator (AO) by Bill Williams


The indicator Awesome Oscillator (AO) by Bill Williams is used to determine market moving forces.
http://ta.mql4.com/indicators/bills/awesome
Function prototype:
double iAO( string symbol, int timeframe, int shift)

Parameters:





symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
shift defines, to what bar the indicator should be used.

Examples of usage:

double ao;
ao=iAO(0,0,0);
// moving force of the last bar on the active chart and period
ao=iAO(EURUSD,PERIOD_M5,0);
// moving force of the last bar on 5-minute chart EURUSD
ao=iAO(EURAUD,PERIOD_W1,1);
// moving force of the last but one bar on a weekly chart EURAUD

Bears Power
The indicator Bears Power is used for estimating the balance of "bears'" power.
http://www.fibo-forex.ru/pages.php?page=1799
Function prototype:
double iBearsPower(string symbol,int timeframe,int period,int applied_price,int
shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double bp;
bp=iBearsPower(0,0,5,PRICE_OPEN,0);
// balance of the last bar on the active chart and period. Use 5 bars for averaging
and opening prpice.
bp=iBearsPower("EURUSD",PERIOD_M5,32,PRICE_CLOSE,1);

// balance of the last but one bar on 5-minute chart EURUSD. Use 32 bars for
averaging and close price.
bp=iBearsPower("EURGBP",PERIOD_D1,51,PRICE_MEDIAN,0);
// balance of the last bar on a daily chart EURGBP. Use 51 bars for averaging and
average price.

Bollinger Bands (BB)


The indicator Bollinger Bands (BB) is used to determine upper and lower limits of the normal range of price
fluctuations.
http://ta.mql4.com/indicators/trends/bollinger_bands
Function prototype:
double iBands( string symbol, int timeframe, int period, int deviation, int
bands_shift,
int applied_price, int mode, int shift)

Parameters:











symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
deviation deviation from the main line.
bands_shift - shift about prices.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
mode choose a line, the value of which will be found. Use the following predetermined constants:
 MODE_UPPER - upper line
 MODE_LOWER - lower line
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double bb;
bb=iBands(0,0,20,2,0,PRICE_LOW,MODE_LOWER,0);
// lower limit of the last bar on the active chart and period.
// Use 20 bars for averaging, and the minimal price.
// Deviation from the main line is 2, shift is not used.
bb=iBands("EURUSD",PERIOD_H1,13,2,3,PRICE_HIGH,MODE_UPPER,1);
// upper limit of the last but one bar on an hour chart EURUSD.
// Use 13 bars for averaging, and the maximal price.
// Deviation from the main line is 2, shift is 3 bars.
bb=iBands("EURGBP",PERIOD_D1,21,3,4,PRICE_HIGH,MODE_UPPER,0);
// upper limit of the last bar on a daily chart EURGBP.
// Use 21 bars for averaging, and the maximal price.
// Deviation from the main line is 2, shift is 4 bars.

Bulls Power

The indicator Bulls Power is used for estimating the balance of "bulls'" power.
http://www.forexdealer.net/help/bul_hlp.htm
Function prototype:
double iBullsPower(string symbol, int timeframe, int period, int applied_price, int
shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double bp;
bp=iBullsPower(0,0,10,PRICE_CLOSE,1);
// balance of the last but one bar on the active chart and period. Use 10 bars for
averaging
// and close price.
bp=iBullsPower("EURGBP",PERIOD_M1,21,PRICE_HIGH,1);
// balance of the last bar on a minute chart EURGBP. Use 21 bars for averaging and
the maximal price.
bp=iBullsPower("EURUSD",PERIOD_H1,33,PRICE_MEDIAN,0);
// balance of the last bar on an hour chart EURUSD. Use 33 bars for averaging and
the average price.

Commodity Channel Index (CCI)


The indicator Commodity Channel Index (CCI) is used for measuring the deviation of the price from its average
statistical price.
http://ta.mql4.com/indicators/trends/commodity_channel_index
Function prototype:
double iCCI( string symbol, int timeframe, int period, int applied_price, int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double cci;
cci=iCCI(0,0,14,PRICE_TYPICAL,0);
// index of the last bar on the active chart and period.
// Use 14 bars for finding the mean value and
// typical price.
cci=iCCI("EURUSD",PERIOD_M1,21,PRICE_HIGH,1);
// index of the last but one bar on a minute chart EURUSD.
// Use 21 bars for finding the mean value and
// maximal price.
cci=iCCI("EURGBP",PERIOD_D1,7,PRICE_CLOSE,0);
// index of the last bar on a daily chart EURGBP.
// Use 7 bars for finding the mean value and
// close price.

DeMarker (DeM)

The indicator DeMarker (DeM) is used to forecast price turn on the basis of the price difference of past bars.
http://ta.mql4.com/indicators/oscillators/DeMarker
Function prototype:
double iDeMarker( string symbol, int timeframe, int period, int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
shift defines, to what bar the indicator should be used.

Examples of useage:

double dm;
dm=iDeMarker(0,0,13,0);
// DeMarker value of the last bar on the current chart and period.
// Use 13 bars to find the mean value.
dm=iDeMarker("EURJPY",PERIOD_H4,51,1);

// DeMarker value of the last but one bar on 4-hour chart EURJPY.
// Use 51 bars to find the mean value.
dm=iDeMarker("USDCAD",PERIOD_M30,21,0);
// DeMarker value of the last bar on 30-minutes chart USDCAD.
// Use 21 bars to find the mean value.

Envelopes
The indicator Envelopes is used to determine the limits of the price fluctuations on the basis of two moving averages.
http://ta.mql4.com/indicators/oscillators/envelopes
Function prototype:
double iEnvelopes( string symbol, int timeframe, int ma_period, int ma_method, int
ma_shift,
int applied_price, double deviation, int mode, int shift)

Parameters:













symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
ma_period - the number of bars, used to find the main line.
ma_method defines the method, used to find mean values. There are the following predetermined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly-weighted moving average
ma_shift shift of the indicator lines in bars. If the shift is positive, the indicator lines are shifted to the right.
And on the contrary, if the shift is negative, lines are shifted to the left.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
deviation deviation from the main line in percentage. For example, if you write 0.1, this will mean 10%,
0.25 25% etc.
mode - choose a line, the value of which will be found. Use the following predetermined constants:
 MODE_UPPER - upper line
 MODE_LOWER - lower line
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double e;
e=iEnvelopes(0,0,21,MODE_SMA,0,PRICE_CLOSE,0.05,MODE_LOWER,0);
// lower limit of the last bar on the active chart and period.
// Use 21 bars and close price for finding the value of simple moving
// average. Shift is not used. Deviation from the main
// line: 5%.
e=iEnvelopes("EURUSD",PERIOD_H1,13,MODE_SMMA,3,PRICE_MEDIAN,0.15,MODE_UPPER,1);
// upper limit of the last but one bar on an hour chart EURUSD.
// Use 13 bars and average price for finding the value of smoothed moving
// average. Shift: 3 bars. Deviation from the main line: 15%.
e=iEnvelopes("EURAUD",PERIOD_D1,7,MODE_EMA,2,PRICE_CLOSE,0.20,MODE_LOWER,0);
// lower limit of the last bar on a daily chart EURAUD.
// Use 7 bars and close price for finding the value of exponential
// moving average. Shift: 2 bars. Deviation from the main
// line: 20%.

Force Index (FRC)


The indicator Force Index (FRC) is used for measuring the power of "bulls" at each rise and the power of "bears" at
each fall.
http://ta.mql4.com/indicators/oscillators/force_index
Function prototype:
double iForce( string symbol, int timeframe, int period, int ma_method,
int applied_price, int shift)

Parameters:







symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
ma_period - the number of bars, used to find the main line.
ma_method defines a method, used to find mean values.There are the following predetermined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly-weighted moving average
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double f;
f=iForce(0,0,13,MODE_SMA,PRICE_CLOSE,0);
// force index of the last bar on the active chart and period. Period
// of averaging: 13 bars. Method of averaging: simple moving average.
// Use close price.
f=iForce("EURGBP",PERIOD_M5,21,MODE_LWMA,PRICE_HIGH,1);
// force index of the last but one bar on 5-minute chart EURGBP. Period
// of averaging: 21 bars. Method of averaging: linearly-weighted moving average.
// Use maximal price.
f=iForce("EURUSD",PERIOD_M1,32,MODE_SMMA,PRICE_MEDIAN,0);
// force index of the last bar on a minute chart EURUSD. Period
// of averaging: 32 bars. Method of averaging: smoothed moving average.
// Use average price.

Fractals
Fractals are one of five indicators of the trading system of Bill Williams, used to detect bottoms and tops of a price
chart. Fractals appear not on all bars. So, if a fractal did not appear on a bar, the function returns zero.

http://ta.mql4.com/indicators/bills/fractal
Function prototype:
double iFractals( string symbol, int timeframe, int mode, int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
mode - choose a line, the value of which will be received. The following predetermined constants are used:
 MODE_UPPER - upper fractals
 MODE_LOWER - lower fractals
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Example of usage:
double f;
f=iFractals(0,0,MODE_UPPER,0);
// upper fractal of the last bar on the active chart and
// period.

f=iFractals("USDCAD",PERIOD_M5,MODE_LOWER,1);
// lower fractal of the last but one bar on 5-minute chart
// USDCAD.
f=iFractals("USDJPY",PERIOD_D1,MODE_UPPER,0);
// upper fractal of the last bar on a daily chart USDJPY.

Gator Oscillator
Gator Oscillator is built on tha basis of the indicator Alligator and is used for measuring the degree of convergence or
divergence of the balance lines.
http://ta.mql4.com/indicators/bills/gator
Function prototype:
double iGator( string symbol, int timeframe, int jaw_period, int jaw_shift, int
teeth_period,
int teeth_shift, int lips_period, int lips_shift, int ma_method,
int applied_price, int mode, int shift)

Parameters:














symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
jaw_period - the period of averaging of the alligator's jaw (blue line)
jaw_shift - shift of the alligator's jaw
teeth_period - the period of averaging of the alligator's teeth (red line)
teeth_shift - shift of the alligator's teeth
lips_period - the period of averaging of the alligator's lips (green line)
lips_shift - shift of the alligator's lips
ma_method defines a method, used to find mean values.There are the following predetermined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - Linearly-weighted moving average
applied_price defines the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
mode defines, the value of what you want to find (jaws, teeth or lips). For choosing use one of the constants:
 MODE_UPPER - upper histogram
 MODE_LOWER - lower histogram
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double g;
g=iGator(0,0,13,8,8,0,0,0,MODE_SMA,PRICE_CLOSE,MODE_UPPER,0);
// upper histogram of the last bar on the active chart and period. Periods of
// averaging for jaw, teeth and lips accordingly: 13,8,8. Shift is not used.
// For averaging use close price and the method of a simple moving average.
g=iGator("EURGBP",PERIOD_M1,21,13,9,4,3,2,MODE_SMMA,PRICE_OPEN,MODE_LOWER,1);
// lower histogram of the last but one bar on a minute chart EURGBP. Periods of
// averaging for jaw, teeth and lips accordingly: 21,13,9. Shifts accordingly:
// 4,3 and 2. For averaging use open price and the method of smoothed
// moving average.
g=iGator("USDCAD",PERIOD_D1,51,21,13,8,5,4,MODE_EMA,PRICE_MEDIAN,MODE_UPPER,0);
// upper histogram of the last bar on a daily chart USDCAD. Periods of
// averaging for jaw, teeth and lips accordingly: 51,21,13. Shifts accordingly: 8,5
and 4.
// For averaging use average price and the method of exponential moving average.

Ichimoku Kinko Hyo


The indicator Ichimoku Kinko Hyo is used to define a trend, support and resistance levels, as well as signals to buy
and to sell.
http://ta.mql4.com/indicators/oscillators/ichimoku
Function prototype:
double iIchimoku( string symbol, int timeframe, int tenkan_sen, int kijun_sen,
int senkou_span_b, int mode, int shift)

Parameters:








symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
tenkan_sen - period of averaging Tenkan Sen.
kijun_sen - period of averaging Kijun Sen.
senkou_span_b - period of averaging Senkou Span B.
mode - defines, the value of what you want to find. For choosing use one of the constants:
 MODE_TENKANSEN - Tenkan-sen
 MODE_KIJUNSEN - Kijun-sen
 MODE_SENKOUSPANA - Senkou Span A
 MODE_SENKOUSPANB - Senkou Span B
 MODE_CHINKOUSPAN - Chinkou Span
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double i;
i=iIchimoku(0,0,13,21,53,MODE_KIJUNSEN,0);
// the value of the line Kijun-sen on the last bar on the current security and
period.
// Periods for finding mean values for Tenkan Sen, Kijun Sen and Senkou Span B
// accordingly: 13,21 and 53.
i=iIchimoku("EURUSD",PERIOD_M5,21,53,96,MODE_TENKANSEN,1);
// the value of the line Tenkan-sen on the last but one bar on 5-minute chart
EURUSD.
// Periods for finding mean values for Tenkan Sen, Kijun Sen and Senkou Span B
// accordingly: 21,53 and 96.
i=iIchimoku("USDCAD",PERIOD_D1,3,5,9,MODE_CHINKOUSPAN,0);
// the value of the line Chinkou Span on the last bar on a daily chart USDCAD.
// Periods for finding mean values for Tenkan Sen, Kijun Sen and Senkou Span B
// accordingly: 3,5 and 9.

Market Facilitation Index (BW MFI)


The indicator Market Facilitation Index (BW MFI) is used for measuring a price for one tick.
http://ta.mql4.com/indicators/bills/market_facilitation_index
Function prototype:
double iBWMFI( string symbol, int timeframe, int shift)

Parameters:





symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
shift defines, to what bar the indicator should be used.

Examples of usage:

double mfi;
mfi=iBWMFI(0,0,0);
// index of market facilitation of the last bar on the active chart and period.
mfi=iBWMFI("EURUSD",PERIOD_H1,1);
// index of market facilitation of the last but one bar on an hour chart EURUSD.

mfi=iBWMFI("EURGBP",PERIOD_D1,0);
// index of market facilitation of the last bar on a daily chart EURGBP.

Momentum
The indicator Momentum is used for measuring the amount of a price change over a period of time.
http://ta.mql4.com/indicators/oscillators/momentum
Function prototype:
double iMomentum( string symbol, int timeframe, int period, int applied_price, int
shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - open price
 PRICE_OPEN - close price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double m;
m=iMomentum(0,0,12,PRICE_CLOSE,1);
// momentum of the last but one bar on the active chart and period. Use
// 12 bars and close price for finding a mean value.
m=iMomentum("EURUSD",PERIOD_D1,21,PRICE_OPEN,0);
// momentum of the last bar on a daily chart EURUSD. Use
// 21 bars and open price for finding a mean value.
m=iMomentum("USDCAD",PERIOD_H1,7,PRICE_MEDIAN,1);
// momentum of the last but one bar on an hour chart USDCAD. Use
// 7 bars and average price for finding a mean value.

Money Flow Index (MFI)


The indicator Money Flow Index (MFI) is used for measuring the intensity of investments.
http://ta.mql4.com/indicators/volumes/money_flow_index
Function prototype:
double iMFI( string symbol, int timeframe, int period, int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
shift defines, to what bar the indicator should be used.

Examples of usage:

double mfi;
iMFI(0,0,14,1);
// intensity of investments of the last but one bar on the current chart and period.
// Use 14 bars to find the mean value.
iMFI("EURGBP",PERIOD_H4,32,0);
// intensity of investments of the last bar on 4-hour chart EURGBP.
// Use 32 bars to find the mean value.
iMFI("EURUSD",PERIOD_W1,9,1);

// intensity of investments of the last but one bar on a weekly chart EURUSD.
// Use 9 bars to find the mean value.

Moving Average (MA)


The indicator Moving Average (MA) shows the average price for a certain period of time.
http://ta.mql4.com/indicators/trends/moving_average
Function prototype:
double iMA( string symbol, int timeframe, int period, int ma_shift,
int ma_method, int applied_price, int shift)

Parameters:







symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
ma_shift shift of the line in bars. If the shift is positive, the line is shifted to the right. And on the contrary,
if the shift is negative, the line is shifted to the left.
ma_method defines a method, used to find mean values.There are the following predetermined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly-weighted moving average
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double ma;
ma=iMA(0,0,13,0,MODE_SMA,PRICE_CLOSE,0);
// moving average of the last bar on the active chart and period.
// Use 13 bars and close price for finding simple moving average.
// Shift is not used.
ma=iMA("GOLD",PERIOD_M15,21,6,MODE_LWMA,PRICE_LOW,1);
// moving average of the last but one bar on 15-minute chart GOLD.
// Use 21 bars and minimal price for finding linearly-weighted moving average.
// Shift: 6 bars.
ma=iMA("EURCHF",PERIOD_D1,18,4,MODE_SMMA,PRICE_TYPICAL,0);
// moving average of the last bar on a daily chart EURCHF.
// Use 18 bars and typical price for finding smoothed moving average.
// Shift: 4 bars.

Average Convergence/Divergence (MACD)


The indicator Average Convergence/Divergence (MACD) is used for tracing trends based on the correlation of two
moving averages.

http://ta.mql4.com/indicators/oscillators/macd
Function prototype:
double iMACD( string symbol, int timeframe, int fast_ema_period,
int slow_ema_period, int signal_period, int applied_price,
int mode, int shift)

Parameters:











symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
fast_ema_period - the number of bars, used for the calculation of a fast moving average.
slow_ema_period - the number of bars, used for the calculation of a slow moving average.
signal_period - the number of bars, used for the calculation of a signal line.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
mode - defines the value of what you want to find. To choose, use one of the constants:
 MODE_MAIN - main line
 MODE_SIGNAL - signal line
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double ma;
ma=iMACD(0,0,9,21,9,PRICE_CLOSE,MODE_MAIN,0);
// value of the main line for the last bar on the active chart and period.
// Bars, used to find mean values of a fast, slow and signal
// moving average accordingly: 9,21 and 9. Use close price.
ma=iMACD("EURUSD",PERIOD_H1,21,52,18,PRICE_HIGH,MODE_SIGNAL,1);
// value of the signal line for the last but one bar on an hour chart EURUSD.
// Bars, used to find mean values of a fast, slow and signal
// moving average accordingly: 21,52 and 18. Use maximal price.
ma=iMACD("USDCAD",PERIOD_D1,7,13,7,PRICE_MEDIAN,MODE_MAIN,1);
// value of the main line for the last but one bar on a daily chart USDCAD.
// Bars, used to find mean values of a fast, slow and signal
// moving average accordingly: 7,13 and 7. Use average price.

Moving Average of Oscillator (OsMA)

The indicator Moving Average of Oscillator (OsMA) is used for measuring the difference between the main and the
signal line of the indicator Average Convergence/Divergence (MACD).
http://ta.mql4.com/indicators/oscillators/macd_oscillator
Function prototype:
double iOsMA( string symbol, int timeframe, int fast_ema_period, int
slow_ema_period,
int signal_period, int applied_price, int shift)

Parameters:








symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
fast_ema_period - the number of bars, used for the calculation of a fast moving average.
slow_ema_period - the number of bars, used for the calculation of a slow moving average.
signal_period - the number of bars, used for the calculation of a signal line.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double osma;
osma=iOsMA(0,0,12,26,9,PRICE_CLOSE,0);
// difference of the last bar on the active chart and period. Bars, used
// to find mean values for the fast, slow and signal
// moving average accordingly: 12,26 and 9. Use close price.
osma=iOsMA("EURUSD",PERIOD_M1,7,13,6,PRICE_OPEN,1);
// difference of the last but one bar on a minute chart EURUSD. Bars, used
// to find mean values for the fast, slow and signal
// moving average accordingly: 7,13 and 6. Use open price.
osma=iOsMA("EURAUD",PERIOD_H1,21,48,18,PRICE_TYPICAL,0);
// difference of the last bar on an hour chart EURAUD. Bars, used
// to find mean values for the fast, slow and signal
// moving average accordingly: 21,48 and 18. Use typical price.

On Balance Volume (OBV)

The indicator On Balance Volume (OBV) relates volume to price change, accompanying this volume.
http://ta.mql4.com/indicators/volumes/on_balance_volume
Function prototype:
double iOBV( string symbol, int timeframe, int applied_price, int shift)

Parameters:





symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical prie, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double obv;
obv=iOBV(0,0,PRICE_OPEN,0);
// Balance volume of the last bar on the current chart and period. Use open price
obv=iOBV("GBPCHF",PERIOD_M30,PRICE_CLOSE,1);
// Balance volume of the last but one bar on 30-minutes chart GBPCHF. Use close
price.
obv=iOBV("GBPJPY",PERIOD_H4,PRICE_MEDIAN,0);
// Balance volume of the last bar on 4-hour chart GBPJPY. Use average price.

Parabolic Stop and Reverse system (Parabolic SAR)


The indicator Parabolic Stop and Reverse system (Parabolic SAR) is used for analyzing trend markets and defining
exit points.
http://ta.mql4.com/indicators/trends/parabolic_sar
Function prototype:
double iSAR( string symbol, int timeframe, double step, double maximum, int shift)

Parameters:







symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
step - increment of the stop level, usually 0.02.
maximum - maximal stop level, usually 0.2.
shift defines, to what bar the indicator should be used.

Examples of usage:

double sar;
sar=iSAR(0,0,0.02,0.2,0);
// indicator value for the last bar on the current chart and period.
// Step of stop level increment: 0.02. Maximal stop level: 0.2.
sar=iSAR("EURUSD",PERIOD_M1,0.03,0.18,1);
// indicator value for the last but one bar on a minute chart EURUSD.
// Step of stop level increment: 0.03. Maximal stop level: 0.18.
sar=iSAR("EURCHF",PERIOD_H1,0.01,0.15,0);
// indicator value for the last bar on an hour chart EURCHF.
// Step of stop level increment: 0.01. Maximal stop level: 0.15.

Relative Strength Index (RSI)


The indicator Relative Strength Index (RSI) is used for forecasting a price turn.
http://ta.mql4.com/indicators/oscillators/relative_strength_index
Function prototype:
double iRSI( string symbol, int timeframe, int period, int applied_price, int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double rsi;
rsi=iRSI(0,0,14,PRICE_CLOSE,0);
// indicator value for the last bar on the active chart and period.

// Use 14 bars and close price to find the mean value.


rsi=iRSI("USDCAD",PERIOD_M1,9,PRICE_OPEN,1);
// indicator value for the last but one bar on a minute chart USDCAD.
// Use 9 bars and close price to find the mean value.
rsi=iRSI("EURAUD",PERIOD_H1,25,PRICE_TYPICAL,0);
// indicator value for the last bar on an hour chart EURAUD.
// Use 25 bars and typical price to find the mean value.

Relative Vigor Index (RVI)


The indicator Relative Vigor Index (RVI) is used to define the signals to buy and to sell. It is recommended to use this
indicator with the previous one to eliminate ambiguity.
http://ta.mql4.com/indicators/oscillators/relative_vigor_index
Function prototype:
double iRVI( string symbol, int timeframe, int period, int mode, int shift)

Parameters:







symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
mode - defines, the value of what you want to find. For choosing use one of the constants:
 MODE_MAIN - main line
 MODE_SIGNAL - signal line
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double rvi;
rvi=iRVI(0,0,12,MODE_MAIN,1);
// value of the main line of the last but one bar on the active chart and period.
// Use 12 bars to find the mean value.
rvi=iRVI("EURUSD",PERIOD_D1,21,MODE_SIGNAL,0);
// value of the signal line on the last bar on a daily chart EURUSD.
// Use 21 bars to find the mean value.
rvi=iRVI("GBPJPY",PERIOD_H1,19,MODE_MAIN,1);
// value of the main line on the last but one bar on an hour chart GBPJPY.
// Use 19 bars to find the mean value.

Standard Deviation
The indicator Standard Deviation is used to measure market volatility.
http://ta.mql4.com/indicators/trends/standard_deviation
Function prototype:

double iStdDev( string symbol, int timeframe, int ma_period, int ma_shift,
int ma_method, int applied_price, int shift)

Parameters:







symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
ma_period - amount of bars, used to get the indicator lines.
ma_shift shift of the indicator lines in bars. If the shift is positive, the line is shifted to the right. And on the
contrary, if the shift is negative, the line is shifted to the left.
ma_method defines a method, used to find mean values.There are the following predetermined constants
for choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly-weighted moving average
applied_price define the price to be used (what will be averaged). There are the following predefined
constants for choosing the used price:
 PRICE_CLOSE - close price
 PRICE_OPEN - open price
 PRICE_HIGH - maximal price
 PRICE_LOW - minimal price
 PRICE_MEDIAN - average price, (high+low)/2
 PRICE_TYPICAL - typical price, (high+low+close)/3
 PRICE_WEIGHTED - weighted close price, (high+low+close+close)/4
shift defines, to what bar the indicator should be used.

Examples of usage:

double sd;
sd=iStdDev(0,0,10,0,MODE_SMA,PRICE_CLOSE,1);
// deviation of the last but one bar on the active chart and period.
// Use 10 bars and close price to find simple
// moving average. Shift is not used.
sd=iStdDev("EURUSD",PERIOD_D1,21,3,MODE_SMMA,PRICE_MEDIAN,0);
// deviation of the last bar on a daily chart EURUSD.
// Use 21 bars and average price to find smoothed
// moving average. Shift: 3 bars.
sd=iStdDev("USDCAD",PERIOD_H4,17,2,MODE_EMA,PRICE_OPEN,1);
// deviation of the last but one bar on 4-hour chart USDCAD.
// Use 17 bars and open price to find exponential
// moving average. Shift: 2 bars.

Stochastic Oscillator

The indicator Stochastic Oscillator is used to define signals to buy and to sell.
http://ta.mql4.com/indicators/oscillators/stochastic
Function prototype:
double iStochastic( string symbol, int timeframe, int %Kperiod,
int %Dperiod, int slowing, int method,
int price_field, int mode, int shift)

Parameters:











symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
%K period - amount of bars, used to generate the line %K.
%D period - amount of bars, used to generate the line %D.
slowing - value of slowing.
method - defines a method, used to find mean values.There are the following predetermined constants for
choosing a method:
 MODE_SMA - simple moving average
 MODE_EMA - exponential moving average
 MODE_SMMA - smoothed moving average
 MODE_LWMA - linearly-weighted moving average
price_field defines what prices should be used for calculation. There are the following predetermined values
for price choosing:
 0 - Low/High
 1 - Close/Close
mode - defines the value of what you want to find. To choose, use one of the constants:
 MODE_MAIN - main line
 MODE_SIGNAL - signal line
shift defines, to what bar the indicator should be used.

Using the parameter mode define, what should be returned:

Examples of usage:
double s;
s=iStochastic(0,0,10,6,6,MODE_SMA,0,MODE_MAIN,0);
// value of the main line for the last bar on the current chart and period.
// Bars used to calculate lines %K, %D and slowing
// accordingly: 10, 6 and 6. Method of averaging: simple moving average.
// Use prices: Low/High.
s=iStochastic("EURUSD",PERIOD_M1,6,3,3,MODE_SMMA,1,MODE_SIGNAL,1);
// value of the signal line for the last but one bar on a minute chart EURUSD.
// Bars used to calculate lines %K, %D and slowing
// accordingly: 6, 3 and 3. Method of averaging: smoothed moving average.
// Use prices: Close/Close.
s=iStochastic("EURGBP",PERIOD_M5,9,7,7,MODE_EMA,0,MODE_MAIN,0);
// value of the main line for the last bar on 5-minute chart EURGBP.
// Bars used to calculate lines %K, %D and slowing
// accordingly: 9, 7 and 7. Method of averaging: exponential moving average.
// Use prices: Low/High.

Williams Percent Range (%R)


The indicator Williams Percent Range (%R) is used to determine whether the market is overbought/oversold.
http://ta.mql4.com/indicators/oscillators/williams_percent
Function prototype:
double iWPR( string symbol, int timeframe, int period, int shift)

Parameters:






symbol defines, which financial security (currency pair) should be used for the calculation of a technical
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
period - the number of bars, used to find the mean value.
shift defines, to what bar the indicator should be used.

Examples of usage:

double wpr;
wpr=iWPR(0,0,14,1);
// overbought: the last but one bar on the active chart and period.
// Use 14 bars to get the mean value.

wpr=iWPR("USDCHF",PERIOD_D1,9,0);
// overbought: The last bar on a daily chart USDCHF.
// Use 9 bars to get the mean value.
wpr=iWPR("GBPJPY",PERIOD_H1,23,1);
// overbought: the last but one bar on an hour chart GBPJPY.
// Use 23 bars to get the mean value.

The Correct Usage of Technical Indicators Functions


For the correct usage of these functions you must know exactly, how an indicator is arranged and how to use it (trading
signals). Of course they should be used in your own Expert Advisors or indicators. Still, as a home task try to write a
script, which will inform about the entering points, based on the signals of any indicator (choose yourself).
As an example let us write one of such home tasks, which will show entering points based on the trading signals of
Stochastic Oscillator. We will use the following rules for entering the market:
Buy if the main line rises higher than the signal line. Sell if the main line falls lower than the signal line.
At the picture entering points are encircled:

First let us declare several variables, in which we will store the values of the signal and the main line on the current and
previous bar:
double mainLine;
double prevMainLine;

double signalLine;
double prevSignalLine;

Now let us find the values for these variables:


mainLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_MAIN,0);
prevMainLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_MAIN,1);
signalLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);
prevSignalLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,1);

You see, we restricted ourselves to the last and last but one bars. Now let us check, if there are signals to buy and sell:
if(prevMainLine<prevSignalLine && mainLine>signalLine)
Alert("Signal to buy");
// if the main line was under the signal one and rised over it,
// this is a signal to buy
if(prevMainLine>prevSignalLine && mainLine<signalLine)
Alert("Signal to sell");
// if the main line was over the signal one and fell bellow it,
// this is a signal to sell

We used operators of comparison and logical &&. Try to understand it properly.


Now let us put it into a cycle to check a hundred of last bars:
for(int a=0;a<100;a++)
{
mainLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_MAIN,a);
prevMainLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_MAIN,a+1);
signalLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,a);
prevSignalLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,a+1);
if(prevMainLine<prevSignalLine && mainLine>signalLine)
Alert("Signal to buy");
if(prevMainLine>prevSignalLine && mainLine<signalLine)
Alert("Signal to sell");
}

See it? We have simply added a counter from a cycle and can check the bars. And now for convenience instead of a
hundred let us declare a constant BARS_TO_ANALYSE, which will define, how many last bars will be analyzed.
Here is the final version of the script:
//+------------------------------------------------------------------+
//|

showStochasticSignals.mq4 |

//|

Antonuk Oleg Copyright 2007 |

//|

banderass@i.ua |

//+------------------------------------------------------------------+

#property copyright "Antonuk Oleg Copyright 2007"


#property link

"banderass@i.ua"

#define BARS_TO_ANALYSE 100


//+------------------------------------------------------------------+
//| script program start function

//+------------------------------------------------------------------+
int start()
{
double mainLine;
double prevMainLine;
double signalLine;
double prevSignalLine;
for(int a=0;a<BARS_TO_ANALYSE;a++)
{
mainLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_MAIN,a);
prevMainLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_MAIN,a+1);
signalLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,a);
prevSignalLine=iStochastic(0,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,a+1);
if(prevMainLine<prevSignalLine && mainLine>signalLine)
Alert("Signal to buy. Time: ",TimeToStr(Time[a]));
if(prevMainLine>prevSignalLine && mainLine<signalLine)
Alert("Signal to sell. Time: ",TimeToStr(Time[a]));
}
return(0);
}

In this script the following small code fragment must seem strange for you (if it does, you must be a successful
student):
TimeToStr(Time[a])

This function accepts the amount of seconds that passed from the 1st of January 1970 and returns a string with this date.
The predetermined array Time[] returns the same number of seconds as applied to a chosen bar. Here is an ideal pair.
As a subtask try to add a heavy moving average (with the period 200-500) and filter out unnecessary signals in such a
way: if a price is above the mid line, do not sell. If a price is under the mid line, do not buy.
Well, did you manage to do this? No? Then, some more information for you.

Something New about Variables Declaration


Usually we declare variables so:
double maxPrice;

double minPrice;
double lastPrices[100];
int maxIndex;
int minIndex;
int levels[10];

Do not do so any more. Do it this way:


double maxPrice,
minPrice,
lastPrices[100];
int maxIndex,
minIndex,
levels[10];

I.e. first indicate the type, and then comma separated the names of variables (arrays). There is no difference, though we
avoid unnecessary actions. The same is with initialization:
int value1=10,
value2=12,
matrix[2][2]={1,2,
3,4};

Functions that Return Several Values


Are there such functions?? Of course, you can write it yourself. Let us see what you can.
The simplest function returning one value:
int func()
{
return(100);
}

And what if we need several values of different types to be returned simultaneously? Look here:
void SuperFunc(int& valueForReturn1,double& valueForReturn2,string& valueForReturn3)
{
valueForReturn1=100;
valueForReturn2=300.0;
valueForReturn3="it works!!";
}

Now let us try to call this "amazing" function:


int value1=0;
double value2=0.0;

string value3="";
SuperFunc(value1,value2,value3);
MessageBox("value1="+value1+" value2="+value2+" value3="+value3);

The result is the following:

This function has one common difference from simple functions: when we declare it, after the argument we put the
ampersand character (&). If you do this with an argument, you can change its value inside the function, and after
calling it the result will remain. Such operation with arguments is called parameter passing by reference. Thus you
can return as many variables of different types as you wish. Try to omit the ampersand characters in the above code and
see the result:

New Type of Comments


You know how to comment one line:
// it is a one string comment

But sometimes it is more useful to comment a certain code block, in order to disable it temporarily. The above method
is not convenient for commenting 20-30 strings. Here we can use multi-line comments:
/*
it is a multi-line comment.
Very convenient, try it.
*/

Conclusion
Today you have learned a lot of new material. We have analyzed mathematic and trigonometric functions and functions
for operation with technical indicators. You saw on a simple example how to trace trading signals correctly. And
though it is not convenient to use them in scripts, and they were created not for that purpose, soon at following lessons
you will see how to use them in your own indicators and Expert Advisors. And then you will see how useful they
actually are.

MQL4 Language for Newbies. Custom Indicators (Part 1) [ ru ]


Introduction
This is the fourth article from the series "MQL4 Languages for Newbies". Today we will learn to write custom
indicators. We will get acquainted with the classification of indicator features, will see how these features influence the
indicator, will learn about new functions and optimization, and, finally, we will write our own indicators. Moreover, at
the end of the article you will find advice on the programming style. If this is the first article "for newbies" that you are
reading, perhaps it would be better for you to read the previous ones. Besides, make sure that you have understood
properly the previous material, because the given article does not explain the basics.

Types of Indicators
Now I will show you, what kinds of indicators exist. Of course, you have seen a lot of them, but now I would like to
draw your attention to features and parameters of indicators, thus we will make a small classification of features and
parameters. It will then help you to write custom indicators. So, the first simple indicator:

This is Moving Average, MA, a widely used technical indicator. Pay attention to the following important facts:






the indicator is drawn in the chart window


the indicator shows only one value
the range of the indicator values is unlimited and depends on the current prices
the line is drawn with a certain color, width and style (solid line)

Now let us view another indicator:

It is Williams Percent Range, %R. Pay attention to the following important facts:






the indicator is drawn in a separate subwindow


like in the previous case, the indicator shows only one value
the range of the indicator values is strictly limited
the drawn line has another style, color and width

Thus, the following indicator properties exist:

the indicator is drawn: in a chart window or in a separate subwindow. Now let us try to understand, why
Moving Average is drawn on the chart, and Williams Percent Range, %R is drawn in a separate window.
The difference is in the range of the shown values. Note, that the second indicator shows values in the range
from 0 to -100. Now imagine that we show these values in a chart window. And what would happen?? You
would not see this line, because the price has a much narrower range. In our case it is from 0.6805 to 0.7495.
But it is not all. Actually, prices are positive numbers, and our value is negative. Indicators are drawn in a
separate subwindow if their values are outside the price range of the active chart. And if the range is almost
the same (for example, different kinds of moving averages), an indicator is drawn in a chart window. In
future set this indicator parameter according to this simple logics. Here is a picture:

an indicator that is drawn in a separate subwindow may be limited to a strict range. It means the terminal
sets a fixed scale for showing indicator values; and even if values exceed the range, you will not see them. If
you disable this parameter, the terminal automatically will change the scale so that it contains all values of an
indicator. See the picture:

an indicator may show its values using different colors, styles and width. You have seen it quite often when
setting up the drawing of indicators in the terminal. Here is one restriction: if you use a line width more than
1, you may use only one style - solid line.

Here is one more indicator:

As you see, the indicator Volumes is drawn in the form of a histogram. So, there are several types of showing
indicator values. Here is an example of another type:

The indicator Fractals is drawn in the form of special symbols. Now look at the following indicator:

This is Alligator. Note, the indicator simultaneously draws three values (balance lines). How does it work? Actually,
any indicator (there are some exceptions, but we will talk about them later) uses data buffers when showing values.
Data buffer is almost a simple array. Its peculiarity is in the fact that this array is partially managed by the terminal.
The terminal changes the array so, that at the receipt of each new bar, a shift takes place. It is done for the purpose that
each array element corresponds to a certain bar. The maximal number of shown data buffers in one indicator is 8. It
may seem strange now, but soon you will understand that it could not be otherwise. Just remember that there is a
separate data buffer for each line in Alligator. Each data buffer has its own parameters, according to which the terminal
draws them. In our case there are 3 buffers that can be described in the following way:
1.
2.
3.

The first buffer is drawn by a solid green line at a width 3.


The second buffer is drawn by a dashed line of red color and width 1.
The third buffer is drawn by a solid blue line at a width 2.

It is not necessary for an indicator to draw a buffer. It can be used for intermediary calculations. That is why the
number of buffers may be larger than you see. But the most important property of data buffer is that each buffer
element should correspond to a certain bar on a chart. Just remember this. Soon you will see how this works in a code.
Now let us draw a conclusion of our small excursion. Any indicator has the following parameters:





one or more data buffers (though not necessarily) for showing its values or for intermediary calculations.
Each buffer, in its turn has its own parameters that define how it will be drawn and whether it will be drawn.
For example: draw the value in the form of a histogram, symbol or line; what color and style;
where the indicator should be drawn (in a chart window or in a subwindow);
if the indicator is drawn in a subwindow, should we limit the range or should the scaling be automatic.

Make sure that you clearly understand all these parameters. Now we will use a Wizard for creating a custom indicator.

Creating a Custom Indicator


Start MetaEditor, select File->New:

Then we see a window Expert Advisor Wizard, select Custom Indicator, click Next:

Fill in fields Name, Author and Link. Everything is as usual here, but now you may add parameters. What is this?
Parameters are common variables that can be set by a user. And what is important, these variables may be used in an
indicator code. The application of parameters is obvious - you enable users to set up some aspects of the indicator
operation. This can be anything you wish. For example, timeframe to use, operating mode, number of bars for
averaging etc.
As an example let us try to add a parameter that will show the number of bars processed for the calculation of the
indicator values. Where can it be used? Imagine that your indicator seriously loads your processor because of too many
calculations. And you often change the timeframe of the chart and view only the last 100-200 bars. Then you do not
need other calculations that waste time. This parameter will help you in such a situation. Of course, there will be
nothing difficult in our indicator that can waste the computer resources. This is only a variant of using indicator
parameters.
So, for adding a parameter click Add (1). After that you may change a variable name (2). In our case we substitute it
for barsToProcess. You may also change the initial value (3), i.e. default value. Change it into 100. Besides you may
change the variable type, but in our case we do not need to change anything, because type int suits perfectly to our
purposes. After all necessary changes are made, click Next:

It is almost ready. Now indicate how the indicator should be drawn: in a separate window or in a chart window. You
may also limit the range. Check Indicator in separate window. Below is an empty field Indexes (data buffers). Here
you may add the necessary number of data buffers (maximum 8). Besides, you may always add or delete a buffer later,
changing the code. Click Add for adding a buffer. Now you may change the way the buffer will be drawn: line,
histogram, section, arrow. We will not change anything, so our type is Line. Set up the color and click OK.
Finally, your first indicator is ready! Well, it does not draw anything, but it is a code! The file with the source code is in
the folder with indicators: MetaTrader4\experts\indicators.

Let us Analyze Each Line


Now let us see, what Meta Editor has created:

//+------------------------------------------------------------------+
//|

myFirstIndicator.mq4 |

//|

Antonuk Oleg |

//|

banderass@i.ua |

//+------------------------------------------------------------------+

As usual the head consisting of one-line comments includes the information you have written earlier. Next:
#property copyright "Antonuk Oleg"

Do you still remember the preprocessor directive #define from the second article? We used it for declaring constants.
So, here is one more directive used for denoting specific properties of an indicator. In our case it is used for
indicating authorship. Please note that is starts with the special sign #, then goes the key word property (without a
space). Then comes a concrete property that we want to set, in our case it is copyright, and then the value of this
property. In our case it is a line with your name. Using the directive #property you may set up many specific aspects of
the indicator. You will see it now. All these properties will be set up by default. Let us go further:
#property link

"banderass@i.ua"

This directive shows, how to contact the author. You may ask where this information (the author's name and contact
information) is, because it is not shown anywhere. But it is included into the executable file. And if you view the
executable file as a common text, you will see this information:

Next:
#property indicator_separate_window

This directive shows, that the indicator must be drawn in a separate subwindow. As you see, there are no additional
parameters, as distinct from the previous directive.

#property indicator_buffers 1

This directive indicates, how many data buffers will be used by the indicator. You may have noticed that directives
are in some way similar to common functions: they also accept some parameters and do something in response. But
there is an important difference: they are executed in the first instance (before compilation).
#property indicator_color1 DarkOrchid

Indicate default color for the first buffer. Note that buffer numeration starts from one, not from zero. Try to remember
it, so that you have no confusion in future. The color is indicated using one of many predetermined names. You may
see key words for all available colors in the help: MQL4 Reference -> Standard Constants -> Web-Colors. Similarly
you may indicate the color for other buffers, simply change the buffer number.
extern int

barsToProcess=100;

This is our parameter of the indicator. We have set it in the Wizard. Note that the only difference from a common
variable is the key word extern before the variable type. This is how the parameter will look like for a user at the
indicator start:

Next:
double ExtMapBuffer1[];

This is a usual array. But the dimensionality is not indicated and initialization is not performed. This array will later be
set up as a data buffer.
Then we declare and describe functions. As distinct from a usual script, each indicator has 3 functions, not 1:





init() - this function is called by the terminal only once, when we start the indicator. Its purpose is to prepare
the indicator for operation, set up data buffers, check parameters (what a user has written) and other
preparatory actions. This function is not obligatory. If you do not perform a code in it, you may delete it.
deinit() - this function is also called only once, when you delete an indicator from a chart. You should prepare
the indicator for the termination of its operation. For example, close opened files, delete graphical objects
from the file (do not worry, you will learn how to do it). This function is also not obligatory.
start() - as distinct from scripts, in indicators this function is called at each tick. I.e. when new quotes appear
from the currency pair, to the chart of which you have attached the indicator, this function is called. Besides,
this function is called at the indicator start, i.e. after the function init().

Let us see what happens in each function:


int init()
{
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
return(0);
}

Here we see the calling of two important functions for setting a data buffer:
SetIndexStyle(0,DRAW_LINE);

This function sets how to draw the data buffer. The first parameter indicates, to what buffer the change should be
applied. Please note, that in this function (and similar functions) the buffer numeration starts from zero, not from one
like in directives. It is an important moment, so be careful. The second parameter indicates, how to draw the chosen
buffer. In our case we use the constant DRAW_LINE, which shows that the buffer will be drawn as a line. Of course,
there are other constants, but we will talk about them later.
SetIndexBuffer(0,ExtMapBuffer1);

This function "binds" an array to a buffer number. I.e. it shows that the buffer with the indicated number will use the
indicated array for storing data. So, changing the elements of this array you will change the value of the buffer.
Actually an array is a data buffer. The first argument is the name of the array that should be bound.
return(0);

End of the function, return zero - the initialization was successful.


int deinit()
{
//---//---return(0);
}

The function of deinitialization is empty by default.


int start()
{
int counted_bars=IndicatorCounted();
//---//---return(0);
}

Now comes the most important function - the main code is located here. Pay attention: the variable counted_bars is
declared beforehand, it is initialized by the function IndicatorCounted(). This variable is usually used for the

optimization and speedup of the indicator operation, this will be analyzed later. And now let us draw something in the
indicator window.

Finishing the Indicator


Let us decide what should be displayed. What will the indicator show us? Something simple. First let's draw random
numbers. Why not? This guarantees 50% of profit signals.
Let's write in our function init() a code for the initialization of the generator of random numbers:
int init()
{
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
// initialization of the generator of random numbers
MathSrand(TimeLocal());
return(0);
}

The initialization is ready, now comes the function start():


int start()
{
int counted_bars=IndicatorCounted();
for(int i=0;i<Bars;i++)
{
ExtMapBuffer1[i]=MathRand()%1001;
}
return(0);
}

Compile - F7. Start the terminal, find the panel Navigator, select the section Custom Indicators and double-click the
name of our indicator:

The indicator will be attached to the active chart:

You see, it all works. Now let us see what the code does:
for(int i=0;i<Bars;i++)

We use the cycle for to go through all elements of the data buffer. As a certain bar corresponds to each element of
the buffer, we use the cycle, starting from the zero bar (the last available) and end with the first available, which is in
succession one less than the variable Bars (because we count bars from zero).
{
ExtMapBuffer1[i]=MathRand()%1001;
}

At each iteration a counter is increased by one, and we move from the last available bar to the first one at the same
time assigning to each buffer element (which corresponds to a certain bar) a random number from 0 to 1000. If it is
difficult for you to understand, how a certain buffer element corresponds to a certain bar, try to change the cycle in the
following way and see the result in the terminal:
for(int i=0;i<Bars;i++)
{
ExtMapBuffer1[i]=i;
}

Now the indicator will show the number of each bar, look:

You see, the bar number increases from the last bar to the first one (from 0 to Bars). Hope now you understand the
correspondence of buffer elements to bars on the chart.

Now let us get back to the code of the "random" indicator. If you used it at least several minutes, you would see that
each indicator tick draws absolutely different chart. I.e. each tick makes recalculations of what was calculated the
previous time. This is inconvenient for us because we cannot see even what happened a tick ago. But this does not
matter, because no one will use such an indicator - we are simply learning to write it. There is one more thing. Imagine,
you indicator makes a lot of complex calculations and calculation of one bar requires large processor resources. In such
a case, if a new price appears, your indicator will calculate the value for each available bar, even if it was done
earlier. Is it clear? Instead of calculating only once, it will calculate again and again. Eliminating such problems
connected with unreasonable waste of resources is called optimization.
How can we solve this problem? Usually it is done in the following way. First an indicator is calculated on all available
candlesticks, and only then when quotes are received, it will recalculate the value only for the last candlestick. This is
reasonable - no unnecessary actions. Now let us optimize the function start(), so that it works in the following way:
int start()
{
int counted_bars=IndicatorCounted(),
limit;
if(counted_bars>0)
counted_bars--;
limit=Bars-counted_bars;
for(int i=0;i<limit;i++)
{
ExtMapBuffer1[i]=MathRand()%1001;
}
return(0);
}

Let us analyze each line:


int counted_bars=IndicatorCounted(),

We declare the variable counted_bars that will store the number of bars calculated by the indicator. Actually the
function IndicatorCounted() returns the number of unchanged bars after the previous call of the function start(). So,
if it is the first start() calling, IndicatorBars() will return 0, because all bars are new for us. If it is not the first calling,
changed is only the last bar, so IndicatorBars() will return a number equal to Bars-1.
limit;

Here is one more variable that will be used as a limiter, i.e. will help the cycle to be completed earlier, omitting already
calculated candlesticks.
if(counted_bars>0)
counted_bars--;

As it was already said, if IndicatorCounted() returns 0, the function start() is called for the first time and all bars are
"new" for us (the indicator was not calculated for them). But if it is not the first calling of start(), the value equal to
Bars-1 will be returned. So, this condition tracks such a situation. After that we diminish the variable counted_bars by
1. Only the last bar can be changed, so why do we do this? The fact is, there are some situations, when the last tick of
the previous bar remains unprocessed, because when the last tick came, the last but one tick was processed. And the

custom indicator was not called and was not calculated. That is why we diminish the variable counted_bars by 1, in
order to eliminate this situation.
limit=Bars-counted_bars;

Here we assign to the variable limit (the limiter) the number of last bars that need to be recalculated. While the variable
counted_bars stores the number of already calculated candlesticks, we simply find the difference between Bars (the
total number of available bars) and counted_bars for defining, how many candlesticks must be calculated.
for(int i=0;i<limit;i++)
{
ExtMapBuffer1[i]=MathRand()%1001;
}

The cycle itself almost did not change. We changed only the condition of implementation. Now the cycle will be
performed while the counter i is less than limit.
Now optimization is over. If you observe the updated version of the indicator, you will see that when a new tick is
received, the value only of last bar changes. Try to use such an optimization constantly, even if your indicator does not
calculate anything difficult. This is haut ton.
Do you remember an indicator parameter barsToProcess that we added in the Wizard. Now it is high time to use it. We
simply need to add a couple of lines before the cycle:
int start()
{
int counted_bars=IndicatorCounted(),
limit;
if(counted_bars>0)
counted_bars--;
limit=Bars-counted_bars;
if(limit>barsToProcess)
limit=barsToProcess;
for(int i=0;i<limit;i++)
{
ExtMapBuffer1[i]=MathRand()%1001;
}
return(0);
}

You see, everything is quite simple. We check if limit is more than barsToProcess. If yes, diminish the limiter through
assigning. As a result, if we set barsToProcess=100, you will see a picture like:

As you see, only the number of bars set by us is calculated.


Our indicator is almost ready. But we do not have clear signals for entering the market. So we need to add more
certainty. For this purpose we will use levels.
Levels are horizontal lines drawn by the indicator using a certain style, color and width. It should be noted here that the
maximal number of levels on one bar is 8. Besides you may set levels using directives or functions. It is more
preferable to use the first variant, if you want to set levels by default. For the dynamic change of levels during the
indicator's operation use functions. So let us set two levels: the first one on the point 800, the second - 200. For this
purpose let us add several directives at the beginning of the indicator code:
//+------------------------------------------------------------------+
//|

myFirstIndicator.mq4 |

//|

Antonuk Oleg |

//|

banderass@i.ua |

//+------------------------------------------------------------------+
#property copyright "Antonuk Oleg"
#property link

"banderass@i.ua"

#property indicator_level1 800.0


#property indicator_level2 200.0
#property indicator_levelcolor LimeGreen
#property indicator_levelwidth 2
#property indicator_levelstyle 0

#property indicator_separate_window

Let us analyze new directives:


#property indicator_level1 800.0

This directive shows, that the level 1 should be places at the point 800.0. Pay attention that buffer numeration starts
with 1, like in the directives for buffer setting. For setting up another level, simply change the level number at the end
of a directive:
#property indicator_level2 200.0

There is an important limitation in setting the external form of levels. You cannot setup each level individually. All
settings are applied absolutely to all levels. If you need to setup each level individually, you should use objects (and do
not use levels at all), which will be described in the next article.
#property indicator_levelcolor LimeGreen

This directive sets color, which will be used for drawing all levels.
#property indicator_levelwidth 2

This directive sets width for drawing lines of all levels. You may set the width from 1 to 5. Do not forget, that if a
width is more than 1, levels will be drawn in a solid line. If you need another style of drawing levels, use only the width
1.
#property indicator_levelstyle STYLE_SOLID

This directive sets style for drawing lines. There are the following preset constants:







STYLE_SOLID - solid line


STYLE_DASH - dashed line
STYLE_DOT - dotted line
STYLE_DASHDOT - dash-dotted line
STYLE_DASHDOTDOT - dash-dotted line with double dots

We have finished developing our "random" indicator. Now let us save the source file with a more appropriate name randomIndicator.mq4. Recompile the source file once again. This indicator will also be used in the following part. The
final version should look like this:

Function iCustom
Now let us dwell on a very useful function - iCustom. It is used for getting values of any custom indicator. Remember,
for built-in indicators we use functions for working with technical indicators described in the previous article (for
example: iADX(), iMACD etc.). For all other indicators (custom indicators) use the function iCustom. This function is
a universal one and can be applied to any custom indicator that meets the following requirements:




the indicator is compiled and is in the form of an executable file (*.ex4)


the indicator is in the folder MetaTrader 4\experts\indicators

The function prototype has the following form:


double iCustom( string symbol, int timeframe, string name, ..., int mode, int
shift);

Parameters:





symbol defines, which financial security (currency pair) should be used for the calculation of a custom
indicator values. Use NULL (or 0), if you need the current (active) security (chart).
timeframe defines, on which timeframe (period) the indicator should be used. Use 0 for the current period
or one of constants (PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1,
PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1).
name the name of the executable file of the custom indicator. Only the name should be indicated: do not
write the extension (.ex4) or the path to the file (experts/indicators/). For example, if the name of the
executable file of the custom indicator is "RandomIndicator.ex4", you should write "RandomIndicator". The
register here is not relevant. It means you may write "RANDOMindicator" and it will work.
... here you should indicate all the values of the custom indicator parameters. For example, in our indicator
RandomIndicator there is only one parameter - barsToProcess. I.e. in our case we write here 100 (or any other




suitable for you value). If the number of parameters is more than one, the are indicated in the same succession
as they are declared in the custom indicator, comma separated. Now we will try to write an indicator based on
this function and you will understand it better.
mode the operation mode of the custom indicator. Actually it is the number of the data buffer, the value of
which you want to get. The numeration starts from zero (not like in directives). If the custom indicator has
only one data buffer, this parameter should be equal to 0.
shift defines, to what bar the custom indicator should be used.

Examples of Usage:
ExtMapBuffer[0]=iCustom(NULL,PERIOD_H1,"Momentum",14,0,0);
// assign to the first element of the array ExtMapBuffer the value of the custom
// indicator Momentum on the last available bar. We use here the active
// security on hour chart. The name of the executable file: Momentum.
// This indicator has only one parameter - period. In our case the period
// is equal to 14. This indicator has only one data buffer, so we use zero,
// in order to get access to its values.
double signalLast=iCustom("EURUSD",PERIOD_D1,"MACD",12,26,9,1,0);
// declare a new variable signalLast and assign to it the value of the custom
// indicator MACD on the last available bar. We use the pair EURUSD on
// a daily chart. The name of the executable file: MACD. This indicator has 3
parameters:
// period for quick average, period for slow average and period for a signal line.
// This indicator also has 2 data buffers. The first one is with values of the main
line. The second one
// with values of a signal line. In our case we take the value of the signal line.

Signal Indicator
Now we will write one more simple indicator. So, imagine the following situation. You have written quite a complex
indicator with many data buffers. Many of them are displayed in a separate window, others are used for intermediary
calculations. You know exactly signals to buy and to sell. But the difficulty is, it is very hard to trace the signals. You
need to constantly look into your monitor, trying to find crossing lines, which are above levels or below them. That is
why you decide to write one more indicator that could do it for you and would only show you the entry signals. For
example, these could be arrows showing in what direction you should open positions. This is only a fantasy showing
where a signal indicator could be appropriate. Our situation is much easier, but still is similar to the first one.
We will write a signal indicator based on the previous indicator RandomIndicator. First we need to define entry
conditions - here we will need our levels. So conditions will be the following:




if a line moves above the upper level (800.0), buy


if a line moves below the lower level (200.0), sell

Now it is high time to write a new indicator. Use Expert Advisor Wizard to create a new custom indicator. Add one
additional parameter as in the previous case:

And the last step (Drawing properties of the Custom indicator program) should be the following:

First add two data buffers that will be used for drawing signals to buy and to sell in the form of arrows. Change the type
of data buffers into Arrow. Change colors and symbol codes. Below are all available symbol codes:

We do not need to draw the indicator in a separate window, because we are going to draw signals in the chart window.
We use two data buffers, because we cannot draw different arrows (symbols) using only one buffer. Each data buffer
that is displayed in the form of symbols can be drawn only by one symbol. Now let us analyze very attentively the
indicator initialization code:
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0,236);
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexEmptyValue(0,0.0);
SetIndexStyle(1,DRAW_ARROW);
SetIndexArrow(1,238);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexEmptyValue(1,0.0);
//---return(0);
}

Pay attention that now another constant for the type of data buffer drawing is used - DRAW_ARROW:
SetIndexStyle(0,DRAW_ARROW);

We also see two new functions that are used for setting the symbol drawing. SetIndexArrow is used to set what
symbol will represent a buffer. The first argument is the buffer number, the second one is the symbol code that will
represent the indicator:

SetIndexArrow(0,236);

SetIndexEmptyValue is used for indicating an "empty" value. It means we indicate the value, at which we need to
draw nothing. It is very convenient in our case, because signals are generated not on every bar. It works the following
way: when we do not need to draw an array on the current bar, you assign to the corresponding data buffer element an
"empty" value, in our case it is 0. The first argument of the function is the number of the data buffer. The second one
is the "empty" value:
SetIndexEmptyValue(0,0.0);

The remaining initialization code sets buffers analogous to the "random" indicator, that we analyzed earlier. Now let us
finish the code in the function start():
int start()
{
int counted_bars=IndicatorCounted(),
limit;
if(counted_bars>0)
counted_bars--;
limit=Bars-counted_bars;
if(limit>barsToProcess)
limit=barsToProcess;
for(int i=0;i<limit;i++)
{
double randomValue=iCustom(NULL,0,"RandomIndicator",barsToProcess,0,i);
if(randomValue>800.0)
ExtMapBuffer1[i]=High[i]+5*Point;
else
ExtMapBuffer1[i]=0.0;
if(randomValue<200.0)
ExtMapBuffer2[i]=Low[i]-5*Point;
else
ExtMapBuffer2[i]=0.0;
}
return(0);
}

The whole code until the cycle is repeated from the "random" indicator. Actually this code is standard in any indicator
and is repeated with small changes. Now let us analyze the cycle in details:
for(int i=0;i<limit;i++)

{
double randomValue=iCustom(NULL,0,"RandomIndicator",barsToProcess,0,i);
if(randomValue>800.0)
ExtMapBuffer1[i]=High[i]+5*Point;
else
ExtMapBuffer1[i]=0.0;
if(randomValue<200.0)
ExtMapBuffer2[i]=Low[i]-5*Point;
else
ExtMapBuffer2[i]=0.0;
}

First we declare the variable randomValue (random value) and assign to it the value of our "random" indicator on the
current bar. For this purpose we use the function iCustom:
double randomValue=iCustom(NULL,0,"RandomIndicator",barsToProcess,0,i);
// get the value of the "random" indicator on the i-th bar. Use the active chart on
the current period.
// The name of the executable file of indicator: RandomIndicator. Single parameter
of "random" indicator
// is number of bars for calculation. In our indicator there is also analogous
variable, that is why
// we use it. In "random" indicator only 1 data buffer, so we use 0, for getting
// access to its values.

If the value of the "random" indicator is more than the upper level (800), this is a signal to buy:
if(randomValue>800.0)
ExtMapBuffer1[i]=High[i]+5*Point;
// if there is signal to buy, assign to current element of data buffer the highest
// value of the current bar. Besides add 5 points, so that the arrow were a little
higher
// than the current price. The predetermined variable Point is used to get
automatically
// a multiplier for presenting points. Otherwise we would have to write something
like
// this: ExtMapBuffer1[i]=High[i]+0.0005;

Otherwise, if there is no Buy signal:


else
ExtMapBuffer1[i]=0.0;
// if no Buy signal, assign to the current element of data
// buffer "empty" value, which is equal to 0.0.

// Now no symbol will be shown on this bar.

If the value of the "random" indicator is below the lower level (200), this is a Sell signal:
if(randomValue<200.0)
ExtMapBuffer2[i]=Low[i]-5*Point;
// if it is signal to sell, assign to the current element of data buffer the lowest
// value of the current bar. Besides diminish the value by 5 points, so that the
arrow were
// a little lower than the current price.

Otherwise, if there is no Sell signal:


else
ExtMapBuffer2[i]=0.0;
// if no Sell signal, assign to the current element of data
// buffer "empty" value. Now no symbol will be shown on this bar.

This was the cycle. Compile the indicator and start it in the terminal:

About the Style

No, this is not the rules of choosing a tie to suit a coat and shirt, though it is always timely. The programing style is
very important, if you do not write your code only for yourselves. Actually, each developer has his own programming
style. Each one designs cycles in his own way, makes different indents (or no indents at all), declares variables etc. You
should find your own programming style, which you will always use later. I would like to give you a several
recommendations that will help you to make your code easy to read and understand:











do not write many operations in one line semi-colon separated (;)


write names of variables and functions in English
in variable names use capitals as delimiters
avoid the excessive use of abbreviations and reductions in the names of variables and functions
make indents of a certain length to have even code blocks
in each new body (of a cycle or a condition) make additional indents
make the grouping of one-type variables
make proper comments for large and difficult code blocks
make proper comments for the functions written by you (their assignment, parameters)

Conclusion
You have learned something new today. You have written two simple indicators. Well, they are useless, but I am not
teaching you to trade successfully! You have seen, how indicators operate, what parameters and properties they have.
You have learned to set buffers and work with them. You have got acquainted with several new functions. The function
iCustom is very important and will further be used even in Expert Advisors. If you meet any difficulties, reread the
article once again, trying to understand. If you still have some questions, please do not hesitate to use forums or write
comments to the article.

Você também pode gostar