Simple Expert Advisor
This section dwells on the principles of creating a simple trading Expert Advisor.
|
Problem 29. Create a trading Expert Advisor. |
Preliminary Arguments
Before starting to program a trading Expert Advisor, it is necessary
to define general principles of a future program. There are no strict
program creating rules. However, once having created a program, a
programmer usually continues to improve it. To be able to easily
understand the program in future, it must be created in accordance with a
well-thought and easy-to-understand scheme (it is especially important
if a program will be further improved by another programmer). The most
convenient program is the one that consists of functional blocks, each
of which is responsible for its part of calculations. To create an
algorithm of a trading Expert Advisor, let‘s analyze what an operating
program should do.
One of the most important data in the formation of trade orders is
the information about orders that already exist in a client terminal.
Some of trading strategies allow only one unidirectional order.
Generally, if a trading strategy allows, several orders can be open in a
terminal at the same time, though their number should be reasonably
limited. When using any strategy, trade decisions should be made taking
into account the current situation. Before a trade decision is made in a
program, it is necessary to know what trading orders have already been
opened or placed. First of all a program must contain a block of orders
accounting which is among the first to be executed.
During an EA execution trading decisions should be made, the
implementation of which leads to the execution of trade operations. Code
part responsible for trade orders formation is better written in a
separate block. An Expert Advisor can form a trade request to open a new
pending or market order, close or modify any of existing orders or
perform no actions at all. An EA must also calculate order prices
depending on a user‘s desire.
Trade decisions should be made in a program on the bases of trade
criteria. The success of the whole program depends on the correctness of
detecting trade criteria in the program. When calculating trade
criteria a program can (and must) take into account all information that
can be useful. For example, an Expert Advisor can analyze combination
of technical indicator values, time of important news releases, current
time, values of some price levels, etc. For convenience, the program
part responsible for the calculation of trading criteria should be
written in a separate block.
A trading Expert Advisor must necessarily contain error processing
block. Analyzing errors that may occur in the execution of trade
operation allows, on the one side, to repeat a trade request and, on the
other hand, to inform a user about a possible conflict situation.
Structure of a Simple Expert Advisor
Below is a structural scheme of a simple Expert Advisor constructed
on the basis of several functional blocks, in each block a certain
detached part of calculations.
Fig. 109. Structural scheme of a simple Expert Advisor.
On the following EA development stage there is no program code yet.
At the same time the algorithm of a program is to a great extent formed.
How the EA built on the bases of the offered scheme will operate can be
easily understood simply looking on the scheme and orienting upon block
names and relations arrays (control passing) between them.
After program start control is passed to the block of preliminary
processing. In this block some general parameters can be analyzed. For
example, if there are not enough bars in a window (bars necessary for
calculating parameters of technical indicators), an EA will not be able
to operate adequately. In such a case an EA must terminate operation
preliminarily informing a user about it and reporting about the reason
of termination. If there are no contraindicatons of a general character,
control is passed to order accounting block.
In the block of accounting orders the number and quality of orders
existing in a client terminal for a security (to the window of which the
EA is attached) is detected. In this block orders of other securities
must be eliminated. If a programmed trading strategy requires using only
market orders (and does not use pending orders) the fact of presence of
pending orders must be detected. If a strategy admits only one market
order and there are actually several orders, this fact should also be
known. The task of the order accounting block (in this scheme) is in
defining whether the current trading situation corresponds with an
expected one, i.e. that in which the EA can adequately operate. If the
situation corresponds, control must be passed to the next block to
continue the EA‘s operation; if not, the EA‘s operation must be
terminated and this fact must be reported to a user.
If there are no orders in the terminal or the number and quality of
existing orders corresponds to what was expected, control is passed to
the block of defining trading criteria. In this block all criteria
necessary for making trade decisions are calculated, namely criteria for
opening, closing and modifying orders. Further control is passed to the
block of closing orders.
It is easy to understand why in the offered scheme the block of
closing orders is executed earlier than the block of opening orders. It
is always more reasonable to process first existing orders (close or
modify) and only after that to open new orders. Generally, it is correct
to be guided by the desire to have as little orders as possible. During
the execution of this block all orders, for which the closing criterion
has been activated, must be closed.
After all necessary orders has been closed, control is passed to a
block of new orders size calculation. There are a lot of algorithms for
calculating an order volume. The simplest of them is using a constant,
fixed lot size. It is convenient to use this algorithm in a program for
testing strategies. More popular method of defining an order size is
setting the number of lots depending on the amount of free margin, for
example 30-40% of it. If free margin is not enough, the program
terminates its operation having informed a user about the reason.
After the number of lots for opening new orders is defined, control
is passed to order opening block. If any of criteria calculated earlier
points to the necessity of opening an order of a certain type, a trade
request to open an order is formed in this block.
There is also error analyzing block in an Expert Advisor. If any
trade operation failed, control (only in this case) is passed to the
error processing block. If an error returned by a server or client
terminal is not crucial, one more attempt is made to perform a trade
operation. If a crucial error is returned (for example, an account is
blocked), an EA must terminate its operation. Remember, in MQL4 there is
no possibility of program terminating an EA‘s operation in a security
window (as distinct from scripts, see Special Functions).
What can be done in a program way is the termination of start(). At a
new start of the function start() on a new tick the value of a certain
variable-flag prohibiting trading (in this case enabled as a result of a
critical error) can be analyzed and control can be passed for the
termination of the special function operation; thus formation of new
trade request is not permitted. In the offered scheme the flag value is
analyzed in the block of preliminary processing.
Trading Strategy
Market prices are constantly moving. Market state at any moment of
time can be conditionally characterized either as a trend - strong
unidirectional price change (rise or fall), or as a flat - lateral price
movement with weak deviations from a certain average. These market
characteristics are conditional, because there are no clear criteria,
according to which trend or flat can be identified. For example, long
lateral movements with strong deviations that can be traced neither to a
flat nor to a trend. Generally it is assumed that the market is mainly
in the state of lateral movement and trends usually take place 15-20% of
time.
Fig. 110. Flat and trend in the market.
All trading strategies also can be conventionally divided into two
main groups. The first group contains flat-oriented strategies. The main
idea of such strategies is that after an evident deviation price must
return to the previous position, that‘s why orders are opened in the
direction contrary to the last price movement. The second group
strategies are trend strategies, when orders are opened in the same
direction as the salt price movement. There are more complicated
(combined) strategies. Such strategies take into account many different
factors that characterize market; as a result trading can be executed
both on flat and trend. It is not hard to implement trading according to
this or that strategy technically - MQL4 contains all necessary means
for it. The main work in the creation of once own strategy consists in
the search of trading criteria.
Trading Criteria
In this example we will try to construct a trend Expert Advisor, i.e.
the one that will open orders in the price movement direction. So, we
need to find among various technical indicators those that detect a
trend beginning. One of the simplest methods of searching trading
criteria is based on the analysis of the combination of MAs with
different averaging periods. Fig. 111 and Fig. 112 show the position of
two different MA (with periods of averaging 11 and 31) on different
market parts. Averages with small averaging period (red lines) are
closer to a price chart, twisty and movable. Moving averages with larger
period of averaging (blue line) are more inert, have larger lag and are
situated farther from market prices. Let‘s pay attention to places
where MAs with different averaging periods cross and try to decide,
whether the fact of MA crossing can be used as a reading criterion.
Fig. 111. Crossing of MA(11) and MA(31) when price movement direction changes.
In Fig. 111 we see a market part where opening orders in the
direction of price movement at MA crossing is justified. In point A the
red line crosses the blue one from bottom upwards, after that the market
price continues growing for some time. Further reverse MA crossing
indicates the price movement direction change. If we open a Buy order at
point A and close it at B, we will get profit proportional to
difference of A and B prices.
Fig. 112. Crossing of MA(11) and MA(31) when price movement direction changes.
At the same time there are other moments in the market when MA cross,
but this does not lead to further considerable price rise or fall (Fig.
112). Orders opened at MA crossing at such moments will lead to losses.
If Sell is opened at A and closed at B, such trading will bring losses.
The same can be said about a Buy order opened at B and closed at C.
The success of the whole strategy implemented on the basis of MA
crossing depends on the number of parts that can be characterized as
trend and flat. In flat often MA crossing is a regular event that
interferes with any trend strategy. Numerous false signals as a rule
lead to losses. That is why this sign - crossing of MAs with different
averaging period - can be used for building trading strategies only in
combination with other signs proving a trend. In this example (for
constructing a simple Expert Advisor) we will have to refuse using this
sign.
We will use another sign. Analyzing visually the character of price
changes in the market, we can see that a long one-direction price rise
or fall often appears as a result of a short strong movement. In other
words, if within a short period a strong movement happened, we may
expect its continuation in a medium-term period.
Fig. 113. Strong price movement can lead to a trend development.
Fig. 113 shows the market period when a strong movement resulted in
the continuation of the price change in the same direction. As the "a
strong movement" we may use the difference of MAs with different
averaging periods. The stronger the movement, the larger is the lag of
MA with larger averaging period from MA with a small period of
averaging. Moreover, even strong discontinuous price movements with
further return do not result in a large difference between MAs, i.e.
numerous false signals do not appear. For example, price jump by 50
points with further return (in the center in Fig. 113) entailed increase
of difference between MAs only by 20 points. At the same time a really
strong movement (which is not usually accompanied by a considerable
correction) in point A resulted in the difference increase up to 25 - 30
points.
If Buy order is opened when a certain value of difference between MAs
is reached, for example in A, most probably the order will be
profitable when a price reaches a preset Stop order value. Let‘s use
this value as a trading criterion in our Expert Advisor.
Number of Orders
In this example we analyze an Expert Advisor that admits presence of
only one market order, pending orders are not provided. Such an approach
is justified not only in this certain example, but can be used as the
basis for any strategy.
Pending orders are usually used when a developer has quite a reliable
criterion for forecasting the future price change with high
probability. If there is no such criterion, no need to use pending
orders.
The situation when several opposite orders for one security are open
also cannot be considered reasonable. It was written earlier that from
economical point of view opposite orders are considered to be senseless,
especially if the order prices are equal (see Closing and Deleting Orders).
In such a case we should close one order by another one and wait for a
signal to open one market order in a certain direction.
Relation of Trading Criteria
From this position it becomes clear what relations are possible
between trading criteria. Fig. 114 shows three variants of correlation
of trading criteria, when each criterion is important (valid). Actions
(opening and closing market orders) take place clockwise on the
following pictures.
Fig. 114. Order opening and closing criteria correlation (a and b - correct, c - incorrect).
The most popular variant of a correctly formed trading criteria is the variant a.
After being opened a market order Buy is held upon till the moment when
criterion requiring its closing triggers. After that a pause occurs
when no orders are opened. Further a market order Sell can be opened.
Conditions for closing a Sell order (in accordance with correctly
formed criteria) occur earlier, than conditions for opening a Buy order.
However, a Buy order can be opened once again, if a trading criterion
requires this. But according to this variant a market order cannot be
opened if there is an open market order in the contrary direction.
Similar criteria correlation is in the variant b. The
difference is that a criterion for opening any market order is at the
same time a criterion for closing the opposite order. This variant like
the variant a does not allow several orders opened in the terminal at the same time on one security.
The variant of criteria correlation is incorrect. According to this
variant opening of a market order is allowed when contrary orders are
not closed yet, which is senseless. There can be rare cases when this
variant is partially justified. Opening of an opposite order is
sometimes acceptable for compensating losses occurring at small
corrections after strong price movements. In such cases an opposite
order can be opened of the same or smaller value than the already
existing one and then closed when the correction is over. Such a tactic
allows not to interfere with the "main" order opened in the trend
direction.
In general case several one-direction orders are also possible. This
may be justified when an earlier opened order is protected by a Stop
order and the criterion pointing at the price development in the same
direction triggered once again. However, when creating such a strategy, a
developer must be fully aware that in case of a sharp price movement
change the placed stop orders may be unexecuted by some brokers at the
first price touch. And the loss will be proportionate to the total value
of one-directional market orders.
In our example we use variant b of trading criteria
correlation. All opened market orders are closed either by a stop order
or after a criterion of opening an order in opposite direction triggers
(here criterion of closing Buy coincides with that of opening Sell and
vice versa).
Size of Opened Orders
In any trading strategy order sizes should be reasonably limited. In a
simple case a fixed order size is used in an Expert Advisor. Before EA
operation start, a user can set any size of future orders and leave it
unchanged for some time. Further if balance changes, a user can set up a
new value of lot numbers of opened orders.
A too small order size provides more confidence in operation at the
unpredictable market change, but the profit in case of success will be
not so large. If the order size is too large, large profit can be
acquired, but such an EA will be too risky. Usually the size of opened
orders is set up so, that margin requirements do not exceed 2-35%
percent of the balance or free margin (if a strategy allows only one
opened order, balance and free margin at the moment before the order
opening will be equal).
In this example both variants are implemented. A user may choose
either to indicate directly values of orders or set the value in
percentage from the free margin.
Programming Details
A simple trend Expert Advisor tradingexpert.mq4 constructed on the basis of previous arguments can look like this:
Describing Variables
One more criterion in program estimation is its readability. A program is considered to be correctly written, if it can be easily read by other programmers, that‘s why all main program parts and main moments characterizing the strategy must be commented. This is also why it is recommended to declare and comment all variables at the beginning of the program.
In the block 1-2 external and global variables are described.
According to rules, external and global variables must be opened before their first usage (see Types of Variables),
that‘s why they are declared in the program head part. All local variables of the function start() are gathered and described in the upper function part (block 2-3) immediately after the function header. Rules of declaring local variables do not require it, but also do not prohibit. If a programmer faces difficulties in understanding the meaning of a variable when reading the program, he can refer to the upper program part and find out the meaning and type of any variable. It is very convenient in programming practice.
Block of preliminary processing
In this example the preprocessing consists of two parts (block 3-4). The program terminates operation if there are not enough bars in a security window; in such a case it is impossible to detect correctly (in block 5-6) values of moving averages necessary for calculating criteria. Besides here the value of the variable Work is analyzed. In the normal EA operation the variable value is always ‘true‘ (it is set once during initialization). If a critical error occurs in the program operation, ‘false‘ is assigned to this variable and start() finishes its operation. This value will not change in future, that is why the following code is not executed. In such a case the program operation must be stopped and the reason for the critical error must be detected (if needed, a dealing center must be contacted). After the situation is solved, the program can be started once again, i.e. the EA can be attached to a security window.
Accounting orders
The described Expert Advisor allows working only with one market order. The task of the orders accounting block (block 4-5) is to define characteristics of an opened order, if there is one. In the loop going through orders ‘for‘ all existing market and pending orders are checked, namely from the first (int i=1) to the last one
(i<=OrdersTotal()). In each cycle iteration the next order is selected by the function OrderSelect(). The selection is made from a source of opened and pending orders (SELECT_BY_POS).
if (OrderSelect(i-1,SELECT_BY_POS)==true)
If the selection is executed successfully (i.e. there is one more order in the terminal), further this order and the situation must be analyzed: whether the order is opened for the security, at which the EA operates, whether the order is market or pending; it also must be taken into account when counting orders. In the line:
if (OrderSymbol()!=Symb)continue;
all orders opened for another security are eliminated. Operator ‘continue‘ stops the iteration and characteristics of such an order are not processed. But if the order is opened for the security, to the window of which the EA is attached, it is further analyzed.
If OrderType() returns value more than 1 (see Types of Trades), the selected order is a pending one. But in this Expert Advisor managing pending orders is not provided. It means the execution of start() must be terminated, because a conflict situation occurred. In such a case after a message about the operation termination start() execution is stopped by the operator ‘return‘.
If the last check showed that the analyzed order is a market order, the total number of orders for a security is calculated and analyzed. For the first of such orders all necessary characteristics are defined. If in the next iteration the order counter (variable Total) finds the second market order, the situation is also considered to be conflict, because the EA cannot manage more than one market order. In such a case start() execution is stopped after showing a corresponding message.
As a result of the order accounting block execution (if all checks were successful) the variable Total preserves its zero value if there are no market orders, or gets the value 1 if there is a market order for our security. In the latter case some variables set in correspondence with the order characteristics (number, type, opening price, stop levels and order value) also get their values.
Calculating Trading Criteria
In the analyzed example definition of trading criteria (block 5-6) is calculated on the bases of difference between Moving Averages with different periods of averaging. According to accepted criteria a chart is bull-directed if the current value of the MA with smaller period is larger than the value of MA with larger period, and the difference between the values is larger than a certain value. In a bear movement MA with smaller period is lower than MA with larger period and the difference is also larger than a certain critical value.
At the block beginning values of MAs with averaging periods Period_MA_1 and
Period_MA_2 are calculated. The fact of significance of any trading criterion is expressed via the value of a corresponding variable. Variables Opn_B and Opn_S denote the criterion triggering for opening Buy and Sell orders, variables Cls_В and Cls_S - for closing. For example, if a criterion for opening Buy has not triggered, the value of Opn_B
remains ‘false‘ (set at the variable initialization); if it has triggered, Opn_B gets the value ‘true‘. In this case the criterion for closing Sell coincides with that for opening Buy, criterion for opening Sell coincides with that for closing Buy.
|
Trading criteria accepted in this example are used for educational purpose only and must not be considered as a guideline when trading on a real account. |
Closing Orders
It was written earlier that this Expert Advisor is intended for operation only with one market order opened for a security, to which window the EA is attached. To the moment when control in the program is passed to the order closing block it is known for sure that at the current moment there are either no orders for the security, or there is only one market order. That‘s why the code in orders closing block is written so that only one order can be closed successfully.
This block is based on the infinite loop ‘while‘, the body of which consists of two analogous parts: one for closing a Buy order, another for closing a Sell order. ‘While‘ is used here for the purpose that in case of a trade operation failure it could be repeated once again.
In the header of the first operator ‘if‘ condition for closing a Buy order is calculated (Sell orders are closed in the analogous way). If the type of an earlier opened order corresponds to Buy (see Types of Trades) and the sign for closing Buy is relevant, control is passed to the body of ‘if‘ operator where a request to close is formed. As an order closing price in the function OrderClose() the value of a two-sided quote corresponding to the order type is indicated (see Requirements and Limitations in Making Trades). If a trade operation is executed successfully, after a message about the order closing is shown the current ‘while‘ iteration is stopped and the execution of the order closing block is over. But if the operation fails, the user-defined function for processing errors Fun_Error() is called (block 10-11).
Processing Errors
As a passed parameter in Fun_Error() the last error code calculated by GetLastError() is used. Depending on the error code Fun_Error() returns 1 if the error is not critical and the operation can be repeated, and 0 if the error is critical. Critical errors are divided into two types - those, after which a program execution can be continued (for example, a common error) and those, after which execution of any trade operations must be stopped (for example, blocked account).
if after an unsuccessful trade operation the user-defined function returns 1, the current ‘while‘ iteration is terminated and during the next iteration another attempt is made to execute the operation - to close the order. If the function returns 0, the current start() execution is stopped. On the next tick start() will be started by the client terminal again and if еору conditions for order closing are preserved, another attempt to close the order will be made.
If during error processing it is found out that further program execution is senseless (for example the program operates on an old client terminal version) during the next start the execution of the special function start() will be terminated in the block of preliminary processing when analyzing the value of the variable Work.
Calculating Amount of Lots for New Orders
Amount of lots can be calculated in accordance with a user‘s settings following one of the two variants. The first variant is a certain constant value set up by a user. According to the second variant the amount of lots is calculated on the basis of a sum equal to a certain percentage (set by a user) of a free margin.
At the beginning of the block of defining the amount of lots for new orders (block 7-8) necessary values of some variables are calculated - minimal allowed amount of lots and step of lot change set up by a broker, free margin and price of one lot for the security.
In this example the following is provided. If a user has set up a certain non-zero value of the external variable Lts, for example 0.5, it is accepted as the amount of lots Lts when a trade request to open an order is formed. If 0 is assigned to Lts, the number of lots Lts is defined on the basis of the variable Prots (percentage), free margin and conditions set up by a broker.
After Lts is calculated, a check is conducted. If this value is lower than the minimal allowed value, the minimal allowed value is accepted. but if free margin is not enough, after a corresponding message the start() execution is terminated.
Opening Orders
The block of opening orders (block 8-9) like the bloke of opening orders is an infinite loop ‘while‘. In the header of the first operator ‘if‘ conditions for opening a Buy order are calculated: if there are no orders for the security (variable Total is equal to 0) and the sign for opening a Buy order is relevant (Opn_B is true ), control is passed to ‘if‘ operator body for opening an order. In such a case after rates are refreshed prices for stop levels are calculated.
Values of stop levels are initially set by a user in external variables StopLoss and TakeProfit. In a general case a user can set values for this parameters smaller that a broker allows. Besides a broker may change the minimal allowed distance at any moment (it is an often case at strong market movements, for example, before important news release). That‘s why before each order opening stop levels must be calculate taking into account values set bu a user and the minimal allowed value set up by a broker.
For calculating stop levels the user-defined function New_Stop() is used; as a passed parameter the stop level value set by a user is used. In New_Stop() first the current minimal allowed distance is calculated. If the value set by a user corresponds to a broker‘s requirements, this value is returned. If it is smaller than the allowed value, the value allowed by a broker is used. Prices of stop requests are calculated from the corresponding two-sided quote (see Requirements and Limitations in Making Trades).
A trade request to open an order is formed using the function
OrderSend(). For the calculation of order opening price and prices of stop requests the two-sided quote values corresponding to the order type are used. If a trade operation was successful (i.e. a server returned the number of an opened order) after a message about a successful order opening is shown. start() execution is finished. If an order was not opened and the client terminal returned an error, the error is processed according to the algorithm described earlier.
Some Code Peculiarities
The analyzed Expert Advisor code is oriented to the implementation of a certain strategy. Note, some program lines contain variables and calculations that would be changed, if the strategy were changed.
For example, according to the accepted strategy the Expert Advisor is developed to work only with one order. This allowed to use the variable Ticket both for the identification of a closing order number (in block of closing 6-7) and for the identification of a success of a trade operation execution when opening an order (in the block of opening 8-9). In this case such a solution is acceptable. However, if we take the analyzed code as the basis for the implementation of another strategy (for example allow opposite orders) we will have to introduce one or several variables to be able to recognize numbers of opened orders and identify the success of trade operations.
In further strategy modifications we will have to change come program lines containing part of logics contained in the source strategy. Namely in the order accounting block we will not have to terminate the program operation if there are several open orders for a security. Besides, conditions for opening and closing orders will alslo change. This will entail the code changing in blocks of opening and closing orders.
On the basis of this analysis we can easily conclude that the described simple Expert Advisor is not perfect. In a general case, for the implementation of order accounting one should use a universal function based on using data arrays and not containing logics of a certain strategy. The same can be said about the blocks of opening and closing orders. A more complete program must contain a main analytical function, all other user-defined functions must be subordinate to it. This analytical function must contain a program code, in which all conditions for the implementation of any strategy are analyzed; all subordinate functions must perform limited actions. The function of accounting orders must only account orders, functions of opening and closing orders must only open and close orders, and the analytical function must "think" and manage all other functions, i.e. call them when needed.