The simplest way for a beginner to study the process of writing expert advisors is a detailed analysis of the expert advisors written by me specially for this purpose. At this stage (and later in my articles) the aim isn’t to write a genius expert advisor which can earn steadily tens of percents per month. The main aim is to show all the aspects of programming expert advisors, and not to write a «Grail».
So, study attentively the code of the expert below, but don’t worry that currently you don’t understand anything so far. In the next articles each line of this expert will be analyzed in details.
//+------------------------------------------------------------------+
//| My First Expert.mq4 |
//| Copyright © 2006, Andrey Vedikhin |
//| http://www.vedikhin.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Andrey Vedikhin"
#property link "http://www.vedikhin.ru"
#define STATE_SQUARE 0
#define STATE_LONG 1
#define STATE_SHORT 2
//---- input parameters
extern int MAPeriod=13;
extern double LotsNumber=1.0;
//---- global variables
int CurrentState;
int MyOrderTicket;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
if (iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0) > Close[0])
CurrentState = STATE_SHORT;
else CurrentState = STATE_LONG;
MyOrderTicket = 0;
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
int err;
double MA;
MA = iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);
if ( CurrentState == STATE_LONG)
{
if (MA > Close[1]) //moving average higher than the closing price
{
CurrentState = STATE_SHORT;
//we reverse the position an go short
//---close the position, if it was open
if ( MyOrderTicket != 0)
{
if (!OrderClose(MyOrderTicket, LotsNumber, Bid, 3, CLR_NONE))
{
err = GetLastError();
Print("Error at closing a position: ", err);
return(0);
}
MyOrderTicket = 0;
}
RefreshRates();
//--- the long position was closed successfully
//--- now we will open a short position
//--- check the availability of free funds
if (!CheckForEnoughMargin()) return(0);
MyOrderTicket = OrderSend(Symbol(), OP_SELL, LotsNumber, Bid, 3, 0, 0,
NULL, 0, 0, CLR_NONE);
if (MyOrderTicket<0)
{
err = GetLastError();
Print("Error at opening a position: ", err);
MyOrderTicket = 0;
}
}
}
else
{
if (MA < Close[1]) //moving average is lower than the closing price
{
CurrentState = STATE_LONG;
//we reverse the position and go long
//---close the position if it was open
if ( MyOrderTicket != 0)
{
if (!OrderClose(MyOrderTicket, LotsNumber, Ask, 3, CLR_NONE))
{
err = GetLastError();
Print("Error at closing a position: ", err);
return(0);
}
MyOrderTicket = 0;
}
RefreshRates();
//--- the short position was closed successfully
//--- now we will open a long position
//--- check the availability of free funds
if (!CheckForEnoughMargin()) return(0);
MyOrderTicket = OrderSend(Symbol(), OP_BUY, LotsNumber, Ask, 3, 0, 0,
NULL, 0, 0, CLR_NONE);
if (MyOrderTicket<0)
{
err = GetLastError();
Print("Error at opening a position: ", err);
MyOrderTicket = 0;
}
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
//| Check of the availability of free margin |
//+------------------------------------------------------------------+
bool CheckForEnoughMargin()
{
if (GetOneLotMargin(Symbol())*LotsNumber
At first let’s analyze what the following lines mean:
#define STATE_SQUARE 0
#define STATE_LONG 1
#define STATE_SHORT 2
These lines give the possibility to use more understandable names STATE_SQUARE, STATE_LONG or STATE_SHORT instead of writing number 0, 1 or 2 that aren’t very informative. The result will be absolutely the same — if the program meets in the text STATE_SQUARE, STATE_LONG or STATE_SHORT, it will change them for 0, 1 and 2 respectively. Such a program will be more readable.
Also constants are used in such cases when some value is used in several places of the program and there is a probability that the trader may need to change this value in the future. If constant is used it will be enough to do this only in one place in the #define directive.
To declare a constant use the following construction :
#define name value
The examples of constants :
#define AUTHOR "Vedikhin Andrey"
#define Lots 1.1
#define ItemsNumber 77
The next two lines are absolutely identical, but the first one is more readable :
for(x=1;x<=ItemsNumber;x++) Print(Lots*x);
for(x=1;x<=77;x++) Print(1.1*x);
A constant may be of any type: int, bool, datetime, double, color, string
Next article: "Storing data in variables"