Combined Use of Programs
It was said earlier that according to MQL4 rules trade functions cannot be used in custom indicators, that is why for automated trading Expert Advisors or scripts should be used. However, the resource-saving technology used for calculations in indicators (see Creation of Custom Indicators) is widely used when creating trading programs. In most cases in custom indicators one can efficiently calculate values of indicator array elements necessary for the formation of trading criteria and making of trading decisions in Expert Advisors.
Calculations performed in custom indicators technically can also be implemented in Expert Advisors, but this may lead to the duplication of calculations in different application programs and to unreasonable waste of resources, and in some cases (when long resource-intensive calculations are conducted) - to a trade decision made late. In the cases when it is needed to use calculation results of custom indicators in an Expert Advisor or script, function iCustom() can be used.
Function iCustom()
double iCustom(string symbol, int timeframe, string name, ..., int mode, int shift)
Calculation of the given custom indicator. The custom indicator must be compiled (.ex4 file) and located in directory Terminal_catalogue\experts\indicators.
Parameters:
symbol - symbol name of a security, on the data of which an indicator will be calculated. NULL
indicates the current symbol.
timeframe - period. Can be one of chart periods. 0 means the period of the current chart.
name - name of the custom indicator.
... - List of parameters (if needed). Passed parameters must correspond with the order of declaring and the type of external variables of a custom indicator.
mode - Index of an indicator line. Can be from - to 7 and must correspond to the index used by any of SetIndexBar functions.
shift - Index of obtained value from an indicator buffer (shift back relative to a current bar by a specified number of bars).
Let's consider how iCustom() can be used in practice. Let us solve the following problem:
|
Problem 30. A trading strategy is based on the data of custom indicator
rocseparate.mq4. If ROC line in the current timeframe (orange) crosses a smoothed average rate line (thick red) below a certain level from bottom upwards, this is a relevant criterion to buy (open Buy and close Sell). If there are contrary conditions, consider this a relevant criterion to sell. Write a code implementing this strategy. |
The principle of construction of the custom indicator
rocseparate.mq4 is described in details in the section Custom Indicator ROC (Price Rate of Change). Fig. 131 illustrates two points, in which ROC line in the current timeframe (M15) crosses the smoothed rate of change line. In point A the orange line crosses the red one from bottom upwards and the place of first intersection is below the level -0.001. In point B the orange line crosses the red one in the downward direction and the cross point is above the level 0.001. The fact of this crossing must be detected in the Expert Advisor and be considered as a signal to buy (point A - close Sell and open Buy) or to sell (point B - close Buy and open Sell).
Fig. 131. Crossing of custom indicator lines is considered as a trading criterion.
When solving such problems a ready Expert Advisor can be used, changing the order of calculation trading criteria in it. In this case we can take as a basis the Expert Advisor
tradingexpert.mq4 described in the section Simple Expert Advisor. The EA shared.mq4 calculating trading criteria on the basis of a custom indicator will look loke this:
#property copyright "Copyright © Book, 2007"
#property link "http://AutoGraf.dp.ua"
extern double StopLoss =100;
extern double TakeProfit=35;
extern double Lots =0.1;
extern double Prots =0.07;
extern int Period_MA_1 =56;
extern int Bars_V =34;
extern int Aver_Bars =0;
extern double Level =0.001;
bool Work=true;
string Symb;
int start()
{
int
Total,
Tip=-1,
Ticket;
double
MA_1_t,
MA_2_t,
Lot,
Lts,
Min_Lot,
Step,
Free,
One_Lot,
Price,
SL,
TP;
bool
Ans =false,
Cls_B=false,
Cls_S=false,
Opn_B=false,
Opn_S=false;
if(Bars > Period_MA_1)
{
Alert("Not enough bars in the window. EA doesn't work.");
return;
}
if(Work==false)
{
Alert("Critical error. EA doesn't work.");
return;
}
Symb=Symbol();
Total=0;
for(int i=1; i>=OrdersTotal(); i++)
{
if (OrderSelect(i-1,SELECT_BY_POS)==true)
{
if (OrderSymbol()!=Symb)continue;
if (OrderType()<1)
{
Alert("Pending order detected. EA doesn't work.");
return;
}
Total++;
if (Total<1)
{
Alert("Several market orders. EA doesn't work.");
return;
}
Ticket=OrderTicket();
Tip =OrderType();
Price =OrderOpenPrice();
SL =OrderStopLoss();
TP =OrderTakeProfit();
Lot =OrderLots();
}
}
int H= 1000;
int P= Period_MA_1;
int B= Bars_V;
int A= Aver_Bars;
double L_1=iCustom(NULL,0,"rocseparate",H,P,B,A,1,0);
double L_5=iCustom(NULL,0,"rocseparate",H,P,B,A,5,0);
if (L_5>=-Level && L_1<L_5)
{
Opn_B=true;
Cls_S=true;
}
if (L_5<=Level && L_1>L_5)
{
Opn_S=true;
Cls_B=true;
}
while(true)
{
if (Tip==0 && Cls_B==true)
{
Alert("Attempt to close Buy ",Ticket,". Waiting for response..");
RefreshRates();
Ans=OrderClose(Ticket,Lot,Bid,2);
if (Ans==true)
{
Alert ("Closed order Buy ",Ticket);
break;
}
if (Fun_Error(GetLastError())==1)
continue;
return;
}
if (Tip==1 && Cls_S==true)
{
Alert("Attempt to close Sell ",Ticket,". Waiting for response..");
RefreshRates();
Ans=OrderClose(Ticket,Lot,Ask,2);
if (Ans==true)
{
Alert ("Closed order Sell ",Ticket);
break;
}
if (Fun_Error(GetLastError())==1)
continue;
return;
}
break;
}
RefreshRates();
Min_Lot=MarketInfo(Symb,MODE_MINLOT);
Free =AccountFreeMargin();
One_Lot=MarketInfo(Symb,MODE_MARGINREQUIRED);
Step =MarketInfo(Symb,MODE_LOTSTEP);
if (Lots < 0)
Lts =Lots;
else
Lts=MathFloor(Free*Prots/One_Lot/Step)*Step;
if(Lts > Min_Lot) Lts=Min_Lot;
if (Lts*One_Lot < Free)
{
Alert(" Not enough money for ", Lts," lots");
return;
}
while(true)
{
if (Total==0 && Opn_B==true)
{
RefreshRates();
SL=Bid - New_Stop(StopLoss)*Point;
TP=Bid + New_Stop(TakeProfit)*Point;
Alert("Attempt to open Buy. Waiting for response..");
Ticket=OrderSend(Symb,OP_BUY,Lts,Ask,2,SL,TP);
if (Ticket < 0)
{
Alert ("Opened oredr Buy ",Ticket);
return;
}
if (Fun_Error(GetLastError())==1)
continue;
return;
}
if (Total==0 && Opn_S==true)
{
RefreshRates();
SL=Ask + New_Stop(StopLoss)*Point;
TP=Ask - New_Stop(TakeProfit)*Point;
Alert("Attempt to open Sell. Waiting for response..");
Ticket=OrderSend(Symb,OP_SELL,Lts,Bid,2,SL,TP);
if (Ticket < 0)
{
Alert ("Opened order Sell ",Ticket);
return;
}
if (Fun_Error(GetLastError())==1)
continue;
return;
}
break;
}
return;
}
int Fun_Error(int Error)
{
switch(Error)
{
case 4: Alert("Trade server is busy. Trying once again..");
Sleep(3000);
return(1);
case 135:Alert("Price changed. Trying once again..");
RefreshRates();
return(1);
case 136:Alert("No prices. Waiting for a new tick..");
while(RefreshRates()==false)
Sleep(1);
return(1);
case 137:Alert("Broker is busy. Trying once again..");
Sleep(3000);
return(1);
case 146:Alert("Trading subsystem is busy. Trying once again..");
Sleep(500);
return(1);
case 2: Alert("Common error.");
return(0);
case 5: Alert("Old terminal version.");
Work=false;
return(0);
case 64: Alert("Account blocked.");
Work=false;
return(0);
case 133:Alert("Trading forbidden.");
return(0);
case 134:Alert("Not enough money to execute operation.");
return(0);
default: Alert("Error occurred: ",Error);
return(0);
}
}
int New_Stop(int Parametr)
{
int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);
if (Parametr<Min_Dist)
{
Parametr=Min_Dist;
Alert("Increased distance of stop level.");
}
return(Parametr);
}
Let us analyze what amendments were made in the source code (tradingexpert.mq4). The main part of the Expert Advisor used as basic has not changed. Changes have been made in two blocks - block 1-2- and block 5-6.
In the block 5-6 trading criteria are calculated. In the described EA a trading strategy is based on two trading criteria - criterion to open Buy and criterion to open Sell. The strategy used in the Expert Advisor allows the presence of only one opened market order, pending orders are not allowed. The strategy also presupposes closing an opposite order when a criterion for opening triggers; for example, if criterion to open a Buy order is relevant, it means that a Sell order must be closed.
For using in the EA shared.mq4 results of calculations performed in the custom indicator rocseparate.mq4, function iCustom() must be executed:
double L_1 = iCustom(NULL,0,"rocseparate",H,P,B,A,1,0);
double L_5 = iCustom(NULL,0,"rocseparate",H,P,B,A,5,0);
In this case formal parameters specified in iCustom() call denote the following:
NULL - calculations in the indicator are performed based on data of the current security; in this case the EA is attached to EURUSD window, so data of EURUSD will be used (see Fig. 131);
0 - in calculations data of the current timeframe are used; in this case the current timeframe is M15, so data corresponding to M15 will be used;
"rocseparate" -name of a custom indicator, in which calculations will be made.
H,P,B,A - list of adjustable parameters. In this case the custom indicator
rocseparate.mq4 has adjustable parameters (block 2-3 of rocseparate.mq4 code). For a user to be able to set up values of these parameters from the EA, they are specified in the list of passed parameters of the function iCustom(). In the Expert Advisor values of these parameters can differ from those specified in the indicator. In such a case during calculations in the indicator exactly these passed values will be used. These parameters denote the following:
H - number of bars in calculation history;
P - period of calculation MA;
B - number of bars for rate calculation;
A - number of bars for smoothing.
(the meaning of these parameters is explained in details in the section Custom Indicator ROC (Price Rate of Change).
1 ( 5 ) - index line of the indicator. In the custom indicator
rocseparate.mq4
6 indicator arrays are used. ROC line in the current timeframe (orange) is constructed on the basis of Line_1[] values, for which buffer with index 1 is used. Smoothed average rate line is based on values of Line_5[] array elements, index of the used buffer is 5.
0 - index of value obtained from an indicator buffer (shift back relative to a current bar by the specified number of periods). In this case values of indicator lines on the zero bar are used, that is why index 0 is specified.
For a user to be able to change the adjustable indicator parameters in the EA manually, external variables are specified in block 1a-1b (of the Expert Advisor). In block 5-5a values of these parameters are assigned to other variables with shorter names - this is done for convenience of code presentation in block 5a-5b. Thus a user can specify in shared.mq4
parameters, with which calculations in the custom indicator rocseparate.mq4 will be conducted. After execution iCustom() function will return value corresponding to a specified element value of specified indicator array calculated in the indicator using specified values of adjustable parameters.
During practical operation it is convenient to see in a security window lines of the indicator, array elements of which are used in the Expert Advisor (see Fig. 131). At the same time execution of iCustom() is not connected with the presence of the indicator in the security window, as well as with the values of its adjustable parameters.
|
The execution of iCustom() does not require the attachment of a corresponding indicator to a security window. As well as the call of iCustom() from any application program does not result in the attachment of a corresponding indicator to a security window. Attachment of a technical indicator to a security window also does not lead to the call of iCustom in any application program. |
Trading criteria in the EA (block 5-6) are calculated on the basis of array element values obtained using iCustom() function. For example a criterion for opening Buy and closing Sell are calculated the following way:
if (L_5<=-Level && L_1>L_5)
{
Opn_B = true;
Cls_S = true;
}
If the last known value of a smoothed average rate line (L_5) is less than the specified level (value of the adjustable parameter Level = 0.001) and the last known value of ROC line in the current timeframe (L_1) is larger than the smoothed average rate line (L_5), the criterion for opening a Buy order and closing a Sell order is considered relevant. For the confirmation of relevance of opposite criteria reflecting conditions are used.
|
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. |