Do you like the article?
Share it with others —
Find us on Telegram!
Use new possibilities of MetaTrader 5

#### Similar articles MetaTrader 4Examples | 5 September 2013, 12:57 17 485 6 ### Introduction

I would like to share my experience with novice traders who know the MQL4 basics and I am going to introduce a program that can be helpful when trading in the channel. Before you start trading in the channel, you should have a clear understanding of the channel's underlying principles and how the channel size and direction change depending on the price movement. Each channel line is plotted based on fully formed fractals within the range of visible bars in the chart.

I will leave out the standard program start here. You can find it in the files attached.

First, let's decide on the number of bars for fractal search by periods. Here, we will also set the space value for arrows to be displayed in the chart.

```switch (Period())
{
case 1:     B_F=12; space=0.0002; break;
case 5:     B_F=48; space=0.0003; break;
case 15:    B_F=24; space=0.0004; break;
case 30:    B_F=24; space=0.0004; break;
case 60:    B_F=12; space=0.0007; break;
case 240:   B_F=15; space=0.0012; break;
case 1440:  B_F=10; space=0.0030; break;
case 10080: B_F=6;  space=0.0040; break;
}```

We start creating the channel by searching for datum points (bars) through which channel lines will be drawn. For upper or lower identified points, we will introduce the following conditions at the level of global variables:

• Extrem = (1) - upper fractal found, // any positive number
• Extrem = (-1) - lower fractal found // any negative number

Let's set the initial indeterminacy values for datum points and their positions in the chart as follows:

`NB1=-1; NB2=-1; Extrem=0;`

Testing will start from the third bar (counted as "0") in view of the possible "fractal formation".

`TestBar=2;  // number of the bar being tested`

To identify the cases where the tested bar matches the maximum or the minimum value lying within the above defined ranges, we will add a 'while' loop. The loop condition will be an expression with negative values of bar numbers. In addition, the number of the bar being tested will have to be smaller than the total number of tested bars.

`while(((NB1==-1) || (NB2==-1)) && (TestBar<AllB))`

Let's first assume that the points of extremum lie low and test the bars to see if they match with the minimum values. If two points are found, the loop conditions will become false and the execution of the operator will be terminated.

Below is the snippet of the 'while' loop for identifying lower chart points. The search for higher datum points is implemented in the similar manner.

```//start counting from the third bar (counted as "0") to be able to "identify the fractal"
TestBar=2;  // number of the bar being tested
NB1=-1; NB2=-1; Extrem=0;   // assume that the numbers of bars and the extremum are not determined
while(((NB1==-1) || (NB2==-1)) && (TestBar<AllB))
{//w1
// -------------------------------------------------------------------------------------+
//  If: - the Extrem value is smaller than (1)(two possible options are: "0" and "-1"),
//  and the index of the smallest price value coincides with the index of bar under consideration
// -------------------------------------------------------------------------------------+
if((Extrem<1) && (TestBar==iLowest(Symbol(),Period(),MODE_LOW,B_F*2+1,TestBar-B_F)))
{//w2
// if "0" when there was no extremum at that moment,
if(Extrem==0)
{//w3
// assign: the value of (-1) to the identified point of extremum, thus indicating
// that this is the lower extremum; the number to the determined bar (NB1) and the price value (Pr1).
Extrem=-1; NB1=TestBar; Pr1=Low[NB1];
}//-w3
else  if(Extrem!=0) // the first point was found earlier
// otherwise the number and the price value will be assigned to point 2
{//w4
NB2=TestBar; Pr2=Low[NB2];
}//-w4
// for control purposes, the values can be printed - Print("   bar #= ",NB2," price value= ",Pr2);
}//-w2
// -------------------------------------------------------------------------------------+```

If only one point is found, the loop conditions will remain true and the operator will proceed to higher extrema. If 2 higher points cannot be found, it will mean that there are currently no points to create a channel.

`if((NB1==-1) || (NB2==-1)) // no datum points are found on the last AllB bars`

With two datum points available, we calculate the rate of price change:

`RatePr=(Pr2-Pr1)/(NB2-NB1);`

We then find the first reference point of the channel line as a projection of the first datum point on the "0" bar:

`double Tk1=Pr1-NB1*RatePr;`

The second reference point of the channel line is identified within the visual range in the left side of the chart, e.g. 50 bars to the left from the second datum point.

`double Tk2=Tk1+(NB2+50)*RatePr;`

Let's now plot the opposite channel line parallel to the determined line:

To find the third datum point, we will test bars lying between the other two datum points from NB1 to NB2 (or from "0" to NB2, and from the second bar to NB2). Testing will be done based on extrema that are lying in the direction opposite to the points found. For example, if the points we have determined are higher chart points, the bars will be tested based on Lows. After finding the third datum point, the other two reference points for the opposite channel line are determined in the same section.

The snippet below is provided with detailed comments.

```// Plot the opposite channel line parallel to the determined line.
// Find the datum point for the opposite channel line:
// Take the minimum price of the 2nd bar as the origin of search.
Tk3=Low-2*RatePr; // projection of the 2nd bar on the "0" bar
for(i=3;i<=NB2;i++) // start searching from the 3rd bar
{//2(1)Up
if(Low[i]<Tk3+i*RatePr) // using the minimum value of the price projection on the "0" bar
{//3(1)Up
Tk3=Low[i]-i*RatePr; // third reference point (projection on the "0" bar)
Pr5=Low[i];          // the third datum point for the lower channel line
NB5=i;               // number of the bar of the third datum point
}//-3(1)Up
}//-2(1)Up```

After the third datum point has been found, you can draw these points in the chart, having deleted the existing ones beforehand.

The snippet of the program for drawing datum points in the chart is provided below.

```ObjectDelete("Rep1"); ObjectDelete("Rep2"); ObjectDelete("Rep3"); ObjectDelete("Rep5");
ObjectCreate("Rep1",OBJ_ARROW, 0, TmR1, Pr1+2*space);
ObjectSet("Rep1", OBJPROP_COLOR, Yellow);
ObjectSet("Rep1", OBJPROP_ARROWCODE,72);
ObjectCreate("Rep2",OBJ_ARROW, 0, TmR2, Pr2+2*space);
ObjectSet("Rep2", OBJPROP_COLOR, Yellow);
ObjectSet("Rep2", OBJPROP_ARROWCODE,72);
ObjectCreate("Rep5",OBJ_ARROW, 0, TmR5, Pr5-space);
ObjectSet("Rep5", OBJPROP_COLOR, Yellow);
ObjectSet("Rep5", OBJPROP_ARROWCODE,71);
ObjectDelete("Cross2");```

As a result, you should be able to see marks above/below the datum points in the chart (please see below).  After determining three datum points and four reference points the lines can be plotted in the chart:

```DelObj1();
ObjectCreate("Tr1",OBJ_TREND,0,Tm2,Tk2,Tm1,Tk1);
ObjectSet("Tr1",OBJPROP_COLOR,Lime);
ObjectSet("Tr1",OBJPROP_WIDTH,1); //2
ObjectSet("Tr1",OBJPROP_STYLE,STYLE_SOLID);
ObjectCreate("Tr2",OBJ_TREND,0,Tm2,Tk4,Tm1,Tk3);
ObjectSet("Tr2",OBJPROP_COLOR,Lime);
ObjectSet("Tr2",OBJPROP_WIDTH,1); //2
ObjectSet("Tr2",OBJPROP_STYLE,STYLE_SOLID);
ObjectCreate("Med",OBJ_TREND,0,Tm2,(Tk2+Tk4)/2,Tm1,(Tk1+Tk3)/2);
ObjectSet("Med",OBJPROP_COLOR,Lime);
ObjectSet("Med",OBJPROP_WIDTH,1);
ObjectSet("Med",OBJPROP_STYLE,STYLE_DOT);```  Let's calculate the median values of the channel and channel boundaries on the last 6 bars:

```for(int i=0;i<6;i++)
{
TLUp_[i]=Tk1+i*RatePr;
TLDn_[i]=Tk3+i*RatePr;
Med_[i]=(TLUp_[i]+TLDn_[i])/2;
}```

If the price has crossed the channel line, mark it with an asterisk and add a sound notification:

```if(Bid>TLUp_)
{
bool TrUp=true; //bool TrDn=false;
ObjectDelete("Cross1");  ObjectDelete("Cross2");
ObjectCreate("Cross1",OBJ_ARROW,0,Tm1,High+2*space);
ObjectSet("Cross1",OBJPROP_COLOR,DeepPink);
ObjectSet("Cross1",OBJPROP_ARROWCODE,171);
PlaySound("alert.wav"); // The file must be located under terminal_directory\sounds
}```

If there is a fully formed fractal on the last bars, mark it in the chart:

```ObjectDelete("Fraktal"+(q-1));  //ObjectDelete("Frakt"+(w-1));
ObjectCreate("Fraktal"+q,OBJ_ARROW, 0, Time, High+2*space+0.0002);
ObjectSet   ("Fraktal"+q, OBJPROP_COLOR, Orchid);
ObjectSet   ("Fraktal"+q, OBJPROP_ARROWCODE,217);``` We have just considered certain peculiarities and program snippets related to creating the channel per se.

Let's now say a few words about the possibility of trading in this channel.

Assume, the channel is directed upwards and the current candlestick moved down close to or crossed the lower boundary of the channel. In this event, the possible price behavior can be as follows:

• the price will turn upwards before reaching the lower boundary;
• the price will reach the lower boundary and turn upwards;
• the price will cross the channel line and then turn upwards;
• having crossed the lower boundary, the price will continue moving down (downward breakout).

It should be noted here that we mean the minimum bar value when speaking of crossing the lower boundary by the bar.

On the face of it, the first three price movement patterns are suitable for opening a BUY position. Let's have a look at them. We should bear in mind that the channel in this Expert Advisor is created based on fully formed fractals. Therefore, there is a possibility that the channel may change its direction after the fractal has been fixed, i.e. on the last three bars and we need to take it into consideration.

Let's review the first pattern. Here, the bar following the bar that has the minimum value will be opened higher than the minimum value of the previous bar. And the minimum value of the third (counted from left to right) bar will also be higher than the minimum value of the first bar. So, bar 3 (counted from right to left, i.e. from the 0 bar) is the minimum value for the fractal formation. And if the upward direction of the channel has not changed, we can open a BUY position.

Now a few words regarding the change in the direction of the channel. If the channel has been plotted based on lower datum points, the channel direction will not change because the minimum fractal point will be above the lower channel line.

If the channel has been plotted based on higher datum points, the channel direction will remain the same. The question arising out of the first pattern is what amount of difference between the lower channel boundary and the minimum value of the fractal formed next to that boundary can be considered sufficient. This amount primarily depends on the size of the channel.

The third price movement pattern as a rule leads to the change in the slope of the channel and sometimes even results in the change of the channel direction as the fractal is formed below the lower channel boundary. If the channel was created based on minimum values of the first two datum points while the value of the formed fractal turned out to be lower than the first reference point and higher than the second reference point, the channel slope will be adjusted and the direction will remain upward.

Should the minimum bar value of the formed fractal be also lower than the second reference point, the channel direction will become downward. The same is true for SELL positions, only in the opposite way. Below are the examples of trading using the proposed Expert Advisor.   In the order opening and position tracking blocks, you can find an example of position opening and closing conditions tested in the demo mode. Testing result: The full program code is provided below:

```//+------------------------------------------------------------------+
//|                                             Expert_Ch_v83_2_.mq4 |
//|                                            2009, author - Genkov |
//|                                                     Genkov@bk.ru |
//+------------------------------------------------------------------+
#property copyright "2009, author - Genkov"
//+------------------------------------------------------------------+
extern double SL_B=200;
extern double TP_B=50;
extern double SL_S=200;
extern double TP_S=50;
extern double Lots=1.0;
double TrailingStop=40;
int Magic,i;
extern int AllB=240;        // number of bars for calculations
int TestBar=0;              // index of the bar being tested
double RatePr=0;            // rate of price change - pips/bars
int NB1=-1,NB2=-1,NB3,NB5;  // numbers of bars of datum points
int Extrem=0;               // indices of the points of extremum:
Extrem = (1)  - upper fractal found, (any positive number)
Extrem = (-1) - lower fractal found   (any negative number)
*/
double Pr1=0,Pr2=0,Pr3,Pr5,// prices of datum bars with fractals
Tk1,Tk2,Tk3,Tk4,Tk5; // prices of reference points for plotting the channel lines
double space;               // distance from the price to the "arrow"
double TLUp_,TLDn_,// values of channel boundaries
Med_;
int B_F=0;                  // number of bars for fractals in a period
datetime Tm1,Tm2,Tm3,Tm5;   // time of bars of reference points
string SH;                  // channel slope
bool FraktUp=false;         // flag of the upper fractal mark
bool FraktDn=false;         // flag of the lower fractal mark
int q,w;
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
void DelObj1()
{
ObjectDelete("Tr1");
ObjectDelete("Tr2");
ObjectDelete("Med");
}
//+------------------------------------------------------------------+
void Op_Sell_Ch()
{
{ Print("  Error when opening a SELL order  # ",GetLastError()); }
return(0);
}
//+------------------------------------------------------------------+
{
{ Print("  Error when opening a SELL order  # ",GetLastError()); }
return(0);
}
//+------------------------------------------------------------------+
void Close_B_lot()
{
if(!OrderClose(OrderTicket(),OrderLots(),Bid,2,HotPink)) // closing 0.1 lot
{
Print(" Closed order #= ",OrderTicket(),"Error #= ",GetLastError());
RefreshRates();
}
}
//+------------------------------------------------------------------+
void Close_S_lot()
{
{
Print(" Closed order #= ",OrderTicket(),"Error #= ",GetLastError());
RefreshRates();
}
}
// ===================================================================+
int start()
{
int StopLevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
// number of bars for fractal search by periods
switch(Period())
{
case 1:     B_F=12; space=0.0002; break;
case 5:     B_F=48; space=0.0003; break;
case 15:    B_F=24; space=0.0004; break;
case 30:    B_F=24; space=0.0004; break;
case 60:    B_F=12; space=0.0007; break;
case 240:   B_F=15; space=0.0012; break;
case 1440:  B_F=10; space=0.0030; break;
case 10080: B_F=6;  space=0.0040; break;
}
// ====================================================================================+
// create a channel:
//start counting from the third bar (counted as "0") to be able to "identify the fractal"
TestBar=2;  // number of the bar being tested
NB1=-1; NB2=-1; Extrem=0;   // assume that the numbers of bars and the extremum are not determined
while(((NB1==-1) || (NB2==-1)) && (TestBar<AllB))
{//w1
// -------------------------------------------------------------------------------+
//  If: - the Extrem value is smaller than (1)(two possible options are: "0" and "-1"),
//  and the index of the smallest price value coincides with the index of bar under consideration
// -------------------------------------------------------------------------------+
if((Extrem<1) && (TestBar==iLowest(Symbol(),Period(),MODE_LOW,B_F*2+1,TestBar-B_F)))
{//w2
// if "0" when there was no extremum at that moment,
if(Extrem==0)
{//w3
// assign: the value of (-1) to the identified point of extremum, thus indicating
// that this is the lower extremum; the number to the determined bar (NB1) and the price value (Pr1).
Extrem=-1; NB1=TestBar; Pr1=Low[NB1];
}//-w3
else  if(Extrem!=0) // the first point was found earlier
// otherwise the number and the price value will be assigned to point 2
{//w4
NB2=TestBar; Pr2=Low[NB2];
}//-w4
// for control purposes, the values can be printed - Print("   bar #= ",NB2," price value= ",Pr2);
}//-w2
// -------------------------------------------------------------------------------+
//  If: - the Extrem value is greater than (-1)(possible options are: 0 and 1), and the index of the highest price
//  value coincides with the number of the bar under consideration - (similar to the above)
// -------------------------------------------------------------------------------+
if((Extrem>-1) && (TestBar==iHighest(Symbol(),Period(),MODE_HIGH,B_F*2+1,TestBar-B_F)))
{//w5
// if Extrem==0
if(Extrem==0)
{//w6
// store the bar number (NB1) and the price value (Pr1).
Extrem=1; NB1=TestBar; Pr1=High[NB1];
}//-w6
else // otherwise the number and the price value will be assigned to point 2
{//w7
NB2=TestBar; Pr2=High[NB2];
}//-w7
}//-w5
TestBar++;
}//-w1
// -----------------------------------------------------------------------------------+
if((NB1==-1) || (NB2==-1)) // no datum points found on the last AllB bars
{
DelObj1(); ObjectDelete("Cross1"); ObjectDelete("Cross2");  ObjectDelete("Rep1");
ObjectDelete("Rep2"); ObjectDelete("Rep3"); ObjectDelete("Rep5");
// Print(" === > no bars for the channel "); // for control purposes only (can be deleted)
return(-1);
}
// ---------------------------------
// Calculate the rate of price change.
RatePr=(Pr2-Pr1)/(NB2-NB1);
// if the value is positive, we are dealing with a downward channel, otherwise - upward.
if(RatePr>0) SH="downward"; else  SH="upward";
// determine the time of datum points for the channel lines
Tm1=Time;    Tm2=Time[NB2+50];
// **************************************************************************************
if(Extrem==1) // if a higher extremum has been found first
{//1(Extrem=1)
// with two datum points and the rate of price change available,
// determine reference points of this line:
// the first reference point is the projection of the datum point on the "0" bar
double Tk1=Pr1-NB1*RatePr;
// the second reference point is the projection on the left-hand side of the chart
double Tk2=Tk1+(NB2+50)*RatePr;
// Plot the opposite channel line parallel to the determined line.
// Find the datum point for the opposite channel line:
// Take the minimum price of the 2nd bar as the origin of search.
Tk3=Low-2*RatePr; // projection of the 2nd bar on the "0" bar
for(i=3;i<=NB2;i++) // start searching from the 3rd bar
{//2(1)Up
if(Low[i]<Tk3+i*RatePr) // using the minimum value of the price projection on the "0" bar
{//3(1)Up
Tk3=Low[i]-i*RatePr; // third reference point (projection on the "0" bar)
Pr5=Low[i];          // the third datum point for the lower channel line
NB5=i;               // number of the bar of the third datum point
}//-3(1)Up
}//-2(1)Up
// now take a look at the first two bars: "0" and "1"; their Min values may turn out to be lower than the 2nd bar
// if we consider adjustment of the channel using these two bars, the channel will be
// becoming wider following the downward price movement; if this is ignored, the downward price movement
// can be considered as the channel line breakout (possible beginning of the trend!)
// if(Low<Tk3) {Tk3=Low; Pr5=Low; NB5=0;}
// if(Low<Tk3+RatePr) {Tk3=Tk3+RatePr; Pr5=Low; NB5=1;}
datetime TmR1=Time[NB1];    datetime TmR2=Time[NB2];   datetime TmR5=Time[NB5];
// -------------------------------------------------------------------------------------
// the following operators are intended for visual control of the program performance only (they can be deleted)
// and display the channel slope value, speed rate, numbers and time of the datum points at Extrem=1
string TNB1=TimeToStr(TmR1,TIME_DATE|TIME_MINUTES);
string TNB2=TimeToStr(TmR2,TIME_DATE|TIME_MINUTES);
string TNB5=TimeToStr(TmR5,TIME_DATE|TIME_MINUTES);
//   Print(" channel- ",SH," ; speed = ",DoubleToStr(NormalizeDouble(RatePr,8),8),
//         " pip / bar"," ; Extrem= ",Extrem);
//   Print(" NB2= ",NB2," ; time= ",TNB2," ; NB5= ",NB5,
//         " ; time= ",TNB5," ; NB1= ",NB1," ; time= ",TNB1);
// --------------------------------------------------------------------------------------
// for clarity of the program performance, mark the datum points on the channel lines in the chart
ObjectDelete("Rep1"); ObjectDelete("Rep2"); ObjectDelete("Rep3"); ObjectDelete("Rep5");
ObjectCreate("Rep1",OBJ_ARROW,0,TmR1,Pr1+2*space);
ObjectSet("Rep1",OBJPROP_COLOR,Yellow);
ObjectSet("Rep1",OBJPROP_ARROWCODE,72);
ObjectCreate("Rep2",OBJ_ARROW,0,TmR2,Pr2+2*space);
ObjectSet("Rep2",OBJPROP_COLOR,Yellow);
ObjectSet("Rep2",OBJPROP_ARROWCODE,72);
ObjectCreate("Rep5",OBJ_ARROW,0,TmR5,Pr5-space);
ObjectSet("Rep5",OBJPROP_COLOR,Yellow);
ObjectSet("Rep5",OBJPROP_ARROWCODE,71);
ObjectDelete("Cross2");
// -------------------------------------------------------------------------------------
// calculate prices for coordinates of reference points on the lower channel boundary:
double Tk3=Pr5-RatePr*NB5; // price of the lower channel boundary in the "0" point
double Tk4=Tk3+RatePr*(NB2+50);// price of the lower channel boundary in the left-hand side of the chart
}//- 1(Extrem=1)
// ******************************************************************************************
else  if(Extrem==-1)// if a lower extremum has been found first
{//1(Extrem= -1)
// prices of reference points on the lower channel boundary:
Tk3=Pr1-NB1*RatePr;      // in the "0" point
Tk4=Tk3+(NB2+50)*RatePr; // in the left-hand side point
// Plot the opposite channel line parallel to the determined line.
// Find the datum point for the opposite channel line.
// Take the price of the 2nd bar as the origin of search.
Tk1=High-2*RatePr; // projection of the 2nd bar on the "0" bar
for(i=3;i<=NB2;i++) // start searching from the 3rd bar
{//2(-1)
if(High[i]>Tk1+i*RatePr)
{//3(-1)
Tk1=High[i]-i*RatePr; // the third reference point (projection on the "0" bar)
Pr3=High[i];          // the third datum point for the upper channel line
NB3=i;                // number of the bar of the third datum point
}//-3(-1)
// now take a look at the first two bars: "0" and "1"
// if(High>Tk1) {Tk1=High; Pr3=High; NB3=0;}
// if(High>Tk1+RatePr) {Tk1=Tk1+RatePr; Pr3=High; NB3=1;}
TmR1=Time[NB1];    TmR2=Time[NB2];   datetime TmR3=Time[NB3];
}//- 2(-1)
// ---------------------------------------------------------------------------------
// add the following operators to monitor the performance results
//(they do not affect the program performance and can be deleted),
// they display the channel (speed) slope value, speed rate, as well as numbers
// and time of the datum points at Extrem = -1
// TNB1=TimeToStr(TmR1,TIME_DATE|TIME_MINUTES);
// TNB2=TimeToStr(TmR2,TIME_DATE|TIME_MINUTES);
// string TNB3=TimeToStr(TmR3,TIME_DATE|TIME_MINUTES);
// Print(" channel- ",SH," ; price speed rate= ",DoubleToStr(NormalizeDouble(RatePr,8),8),
//       " pip / bar"," ; Extrem= ",Extrem);
// Print(" ; NB2= ",NB2," ; time= ",TNB2," ; NB3= ",NB3,
//       " ; time= ",TNB3," ; NB1= ",NB1," ; time= ",TNB1);
// ----------------------------------------------------------------------------------
// for clarity, mark the datum points on the channel lines in the chart
ObjectDelete("Rep1"); ObjectDelete("Rep2");
ObjectDelete("Rep3"); ObjectDelete("Rep5");
ObjectCreate("Rep1",OBJ_ARROW,0,TmR1,Pr1-space);
ObjectSet("Rep1",OBJPROP_COLOR,Yellow);
ObjectSet("Rep1",OBJPROP_ARROWCODE,71);
ObjectCreate("Rep2",OBJ_ARROW,0,TmR2,Pr2-space);
ObjectSet("Rep2",OBJPROP_COLOR,Yellow);
ObjectSet("Rep2",OBJPROP_ARROWCODE,71);
ObjectCreate("Rep3",OBJ_ARROW,0,TmR3,Pr3+2*space);
ObjectSet("Rep3",OBJPROP_COLOR,Yellow);
ObjectSet("Rep3",OBJPROP_ARROWCODE,72);
ObjectDelete("Cross1");
// ---------------------------------------------------------------------------------
// calculate prices of the reference points on the upper channel boundary:
Tk1=Pr3-RatePr*NB3; // price of the upper channel boundary in the "0" point
Tk2=Tk1+RatePr*(NB2+50);// price of the upper channel boundary in the left-hand side point
}//-1(Extrem= -1)
// ---------------------------------======================================================
// calculate the median values of the channel and channel boundaries on the last 6 bars
for(int i=0;i<6;i++)
{
TLUp_[i]=Tk1+i*RatePr;
TLDn_[i]=Tk3+i*RatePr;
Med_[i]=(TLUp_[i]+TLDn_[i])/2;
}
// --------------------------------------------------------------------
//If the price has crossed the upper channel line, mark it with an asterisk and add a sound notification
if(Bid>TLUp_)
{
bool TrUp=true; //bool TrDn=false;
ObjectDelete("Cross1");  ObjectDelete("Cross2");
ObjectCreate("Cross1",OBJ_ARROW,0,Tm1,High+2*space);
ObjectSet("Cross1",OBJPROP_COLOR,DeepPink);
ObjectSet("Cross1",OBJPROP_ARROWCODE,171);
PlaySound("alert.wav"); // The file must be located under terminal_directory\sounds
}
//If the price has crossed the lower channel line, mark it with an asterisk and add a sound notification
if(Bid<TLDn_)
{
ObjectDelete("Cross2");  ObjectDelete("Cross1");
/// Print(" there was a crossover of the lower channel line ");
ObjectCreate("Cross2",OBJ_ARROW,0,Tm1,Low-space);
ObjectSet("Cross2",OBJPROP_COLOR,DodgerBlue);
ObjectSet("Cross2",OBJPROP_ARROWCODE,171);
PlaySound("alert.wav"); // The file must be located under terminal_directory\sounds
}
// -------------------------------------------------------------------------------------
// plot the channel boundaries in the chart, having deleted the existing ones beforehand
DelObj1();
ObjectCreate("Tr1",OBJ_TREND,0,Tm2,Tk2,Tm1,Tk1);
ObjectSet("Tr1",OBJPROP_COLOR,Lime);
ObjectSet("Tr1",OBJPROP_WIDTH,1); //2
ObjectSet("Tr1",OBJPROP_STYLE,STYLE_SOLID);
ObjectCreate("Tr2",OBJ_TREND,0,Tm2,Tk4,Tm1,Tk3);
ObjectSet("Tr2",OBJPROP_COLOR,Lime);
ObjectSet("Tr2",OBJPROP_WIDTH,1); //2
ObjectSet("Tr2",OBJPROP_STYLE,STYLE_SOLID);
ObjectCreate("Med",OBJ_TREND,0,Tm2,(Tk2+Tk4)/2,Tm1,(Tk1+Tk3)/2);
ObjectSet("Med",OBJPROP_COLOR,Lime);
ObjectSet("Med",OBJPROP_WIDTH,1);
ObjectSet("Med",OBJPROP_STYLE,STYLE_DOT);
// ---- Block of marking fractals in the chart ---------------------------------
if((High>High && Bid<High && High>High && High>High) ||
(High==High && Bid<High && High>High && High>High))
{
double FraktalUp=High; // upper fractal
double FraktalDn=0;
// if the fractal has formed, put a mark, and if this fractal caused
// a new datum point - delete the mark for the crossover of the upper channel line by the price.
if(High>=TLUp_[i]) ObjectDelete("Cross1");
ObjectDelete("Fraktal"+(q-1));  //ObjectDelete("Frakt"+(w-1));
ObjectCreate("Fraktal"+q,OBJ_ARROW,0,Time,High+2*space+0.0002);
ObjectSet("Fraktal"+q,OBJPROP_COLOR,Orchid);
ObjectSet("Fraktal"+q,OBJPROP_ARROWCODE,217);
bool FraktUp=true; //bool FraktDn=false;// it will be useful when trading
q++;
}
if((Low<Low && Bid>Low && Low<Low && Low<Low) ||
(Low==Low && Bid>Low && Low<Low && Low<Low))
{
FraktalDn=Low; // lower fractal
FraktalUp=0;
if(Low>=TLUp_[i]) ObjectDelete("Cross2");
ObjectDelete("Frakt"+(w-1)); //ObjectDelete("Fraktal"+(q-1));
ObjectCreate("Frakt"+w,OBJ_ARROW,0,Time,Low-2*space);
ObjectSet("Frakt"+w,OBJPROP_COLOR,Orchid);
ObjectSet("Frakt"+w,OBJPROP_ARROWCODE,218);
FraktDn=true; FraktUp=false;
w++;
}
// ---------------------------------------------------------------+
// Block of position opening conditions.   This is just an example  +
// and it should not be deemed a recommendation for use!+
// ---------------------------------------------------------------+
{
// - 16- SELL ---
if(Extrem==1 && // two upper datum points
RatePr>0 && // channel directed downwards
(Tk1-Tk3)>20*Point && // channel size > 20pip
Bid<High && // the price is lower than the previous bar
(TLUp_-High)<3*Point) // the first bar is within 3pip from the upper channel line
{
Print(" Open - 16-SELL === ");
//   SL_S=50;
//   if(SL_S<StopLevel) SL_S=StopLevel;
//   TP_S=80;
Op_Sell_Ch();
return(0);
}
if(Extrem==-1 && // two lower datum points
RatePr<0 && // channel directed upwards
(Tk1-Tk3)>20*Point && // channel size > 20pip
Bid>Low && // the price is higher than the previous bar
(Low-TLDn_)<3*Point) // the 1st bar is within 3pip from the lower channel line
{
Print(" Open - 18-BUY === ");
//    SL_B=50;
//    if(SL_B<StopLevel) SL_B=StopLevel;
//    TP_B=80;
return(0);
}
}
//------------------------------------------------------------------------+
// Tracking open SELL positions                                    |
//+=======================================================================+
for(i=OrdersTotal()-1;i>=0;i--) // SELL order selection loop
{//1-position selection loop
{Print("Order selection error = ",GetLastError()); }
if(OrderType()==OP_SELL) // if there is an open Sell order
{ //2-type_Sell
if((FraktalDn<=TLDn_ ||
Low<=TLDn_) &&
(Bid>Low && Low<=TLDn_) &&
(OrderOpenPrice()-Bid)*Point>0) // not at a loss!
{//5
Print(" close by the lower channel line ");
Close_S_lot();
// and if the channel is directed upwards
if(RatePr<0)
{
Print(" Open a Buy position ");
}
}//-5
}//-2 type_Sell
//------------------------------------------------------------------------+
// Tracking open BUY positions                   |
//+=======================================================================+
else
if((FraktalUp>=TLUp_ ||
High>=TLUp_) &&
// If the channel is created based on the lower datum points and is directed upwards,
// while the price has crossed the upper boundary,  and is about to move down,
//bar "1" was higher than bar "0" and higher than bar "2" which was situated on the upper channel line,
// this looks like the upper fractal formation and channel size increase.
// At the same time, Stochastic is above 80.0
// and it starts going down to cross the signal line.
// So we should not expect bar "0" to get fully formed as it is highly likely
// that the price will go down. Therefore close the BUY position.
(Bid<High && High>=TLUp_) &&
(Ask-OrderOpenPrice())*Point>0) // not at a loss!
{//5
Print(" close by the upper channel line ");
Close_B_lot();
// and if the channel is directed downwards
if(RatePr>0)
{
Print(" Open a Sell position ");
Op_Sell_Ch();
}
}//-5
}//-1 position selection loop
//----------------
return(0);
}
//+------------------------------------------------------------------+```

### Conclusion

I believe that the question regarding the possibility of trading in the channel should be answered in the affirmative. I am looking forward to any critical feedback to be able to further improve the Expert Advisor. And I am hopeful that my experience will be useful not only to novice traders.

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/1375

Attached files |
StrategyTester.zip (17.1 KB)

#### Other articles by this author

Last comments | Go to discussion (6) | 27 Jan 2015 at 00:42

Hi,

Is it possible to adjust this EA to trade outside the channel? So a buy or a sell order when the prince moves out of the boundaries?

I want to create my own breakout EA (new to programming) and I hope to hear from someone. | 15 Jul 2015 at 03:44

Hi Genkov, your system seems very interesting. Also personally because I'm particularly interested in 'fractal' by CouponDropDown">analysis.

Having had a glance at the code (I'm an ex experienced programmer), and also at one picture included in your article, you consider all the timeframes, the smallest (m1) included.

I was wondering if the expert would work consistently on all timeframes, since I'm interested in swing trading, long term by CouponDropDown">trading, and, in the initial stage of my trading work,

in scalping (this latter strategy in an attempt to initially grow my account till a certain 'thresold', so you know, the more the frequencies of trades you put,

the more the negative effect of spreads to consider.

It's been a long time since this article was published, and so because you wrote

" (I'm an ex experienced programmer)" ......... "I was wondering if the expert would work consistently on all timeframes"

Hoping to benefit from your established  experience in this matter, I imagine you've had enough time to do Strategy Testing on all the timeframes.

What has been the result? | 27 Sep 2016 at 08:12
I have compiled this code, there are 11 errors and 18 warning. I don't know why it can work | 4 May 2022 at 10:24
White Rose #:
I have compiled this code, there are 11 errors and 18 warning. I don't know why it can work

a very interesting concept let me convert it to mq5 and add my ideas and post it here | 4 May 2022 at 10:25
Martijn de Boer #:

Hi,

Is it possible to adjust this EA to trade outside the channel? So a buy or a sell order when the prince moves out of the boundaries?

I want to create my own breakout EA (new to programming) and I hope to hear from someone.

did you manage to create one Extending MQL5 Standard Library and Reusing Code
MQL5 Standard Library makes your life as a developer easier. Nevertheless, it does not implement all the needs of all developers in the world, so if you feel that you need some more custom stuff you can take a step further and extend. This article walks you through integrating MetaQuotes' Zig-Zag technical indicator into the Standard Library. We get inspired by MetaQuotes' design philosophy to achieve our goal. Trading Signal Generator Based on a Custom Indicator
How to create a trading signal generator based on a custom indicator? How to create a custom indicator? How to get access to custom indicator data? Why do we need the IS_PATTERN_USAGE(0) structure and model 0? Creating Neural Network EAs Using MQL5 Wizard and Hlaiman EA Generator
The article describes a method of automated creation of neural network EAs using MQL5 Wizard and Hlaiman EA Generator. It shows you how you can easily start working with neural networks, without having to learn the entire body of theoretical information and writing your own code. Simple Methods of Forecasting Directions of the Japanese Candlesticks
Knowing the direction of the price movement is sufficient for getting positive results from trading operations. Some information on the possible direction of the price can be obtained from the Japanese candlesticks. This article deals with a few simple approaches to forecasting the direction of the Japanese candlesticks.