Questions from Beginners MQL5 MT5 MetaTrader 5 - page 919

 
Artyom Trishkin:

Your indicator calculation is from the beginning to the end (from the most recent historical data to the most recent current data). This is an indication of indexing as in timeseries. So the arrays must be indexed accordingly, which is what you have.

What's wrong with it?

It all works the same as my port in MQL5 from MQL4, but I see that the code is ugly because ofArraySetAsSeries(), that's why I asked

here are both codes

teach me how to write this indicator for MT5! - My code is not nice, full stop! )))

ZSZ don't remember how to write indicators for MT5, sat down and rewrote it in 40 minutes using Help, but the result ... imho, not so good ((!

Files:
PTL.mq4  8 kb
PTL.mq5  13 kb
 
Igor Makanu:

Yes, everything works exactly as my port in MQL5 from MQL4, but I see that the code is ugly because ofArraySetAsSeries(), so I asked

here are both codes

teach me how to write this indicator for MT5! - My code is not nice, full stop! )))

When you reverse the loop, you must necessarily make the arrays timeseries, otherwise the indexing of buffers in the loop will not coincide with the indexing of required data - the loop index in the array of indicator buffers will go from the beginning to the end, while in open[], high[], low[], close[] and others - from end to beginning. Or, you can reverse the loop to match its indexing of arrays open[], high[], low[], close[] and the rest with indexing of buffers, which is more complicated.

If you want an allegory to make it clearer, here's an allegory for you:

You're standing at the railroad tracks and looking at two trains. They either go in one direction - both from left to right (ArraySetAsSeries(array,true) - first train and a loop from limit to 0 - second train),
Or they go towards each other - (ArraySetAsSeries(array,false) - right-to-left - first train, and the loop from limit to 0 - left-to-right - second train)

And, yes: I didn't look through the code - I don't want to download, save (there's already a lot of unnecessary code from the forum), compare them with each other...

It would be easier to put them in codes in message - one and second - then it would be visible at once what to what.

 
Artyom Trishkin:

Or flip the loop to match its indexing of arrays open[], high[], low[], close[] and the rest, which is harder.

I've been reversing it all night today, my patience has run out (((

As far as I understand the problem:

- in MT5 the arrays that are assigned to indicator buffers are indexed from left to right by default;

- in MT5 time seriesopen[], high[], low[], close[] available from OnCalculate() are always passed indexed from right to left

- i.e. based on steps 1 and 2, in order to calculate the indicator from the end of the history to the zero bar

a) or reassign the buffer arrays indexing

b) or to make a loop in which the array elements will be recalculated from left to right, and in another loop from right to left:

for(i=limit;i>=0;i--)
     {
      BufBarsBuffer1[limit - i] = open[i];
      ...
      }


i.e.,there is no beautiful solution to my question? option a) - in my sources is implemented, option b) - I do not see the point of doing extra calculations

sources:

MT5:

//+------------------------------------------------------------------+
//|                                          Perfect_Trend_Lines.mq5 |
//|                                                            IgorM |
//|                                                                  |
//+------------------------------------------------------------------+
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 9
#property indicator_plots   5
//--- plot BufBars
#property indicator_label1  "BufBars"
#property indicator_type1   DRAW_COLOR_BARS
#property indicator_color1  clrRed,clrAqua,clrNONE
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3
//--- plot BufASELL
#property indicator_label2  "BufASELL"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  5
//--- plot BufABUY
#property indicator_label3  "BufABUY"
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  5
//--- plot BufLSELL
#property indicator_label4  "BufLSELL"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2
//--- plot BufLBUY
#property indicator_label5  "BufLBUY"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrRed
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2
//--- input parameters
input int SlowLength         = 7; //Slow length
input int SlowPipDisplace    = 0; //Slow pip displace
input int FastLength         = 3; //Fast length
input int FastPipDisplace    = 0; //Fast pip displace
//--- indicator buffers
double         BufBarsBuffer1[];
double         BufBarsBuffer2[];
double         BufBarsBuffer3[];
double         BufBarsBuffer4[];
double         BufBarsColors[];
double         BufASELLBuffer[];
double         BufABUYBuffer[];
double         BufLSELLBuffer[];
double         BufLBUYBuffer[];
static int trend=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BufBarsBuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,BufBarsBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,BufBarsBuffer3,INDICATOR_DATA);
   SetIndexBuffer(3,BufBarsBuffer4,INDICATOR_DATA);
   SetIndexBuffer(4,BufBarsColors,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(5,BufASELLBuffer,INDICATOR_DATA);
   SetIndexBuffer(6,BufABUYBuffer,INDICATOR_DATA);
   SetIndexBuffer(7,BufLSELLBuffer,INDICATOR_DATA);
   SetIndexBuffer(8,BufLBUYBuffer,INDICATOR_DATA);
   for(int i=0;i<9;i++)
     {
      PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,FastLength+1);
      PlotIndexSetDouble(i,PLOT_EMPTY_VALUE,0.0);
     }
   ArraySetAsSeries(BufBarsBuffer1,true);
   ArraySetAsSeries(BufBarsBuffer2,true);
   ArraySetAsSeries(BufBarsBuffer3,true);
   ArraySetAsSeries(BufBarsBuffer4,true);
   ArraySetAsSeries(BufBarsColors,true);
   ArraySetAsSeries(BufABUYBuffer,true);
   ArraySetAsSeries(BufASELLBuffer,true);
   ArraySetAsSeries(BufLBUYBuffer,true);
   ArraySetAsSeries(BufLSELLBuffer,true);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(1,PLOT_ARROW,234);
   PlotIndexSetInteger(2,PLOT_ARROW,233);
   PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,-20);
   PlotIndexSetInteger(2,PLOT_ARROW_SHIFT,20);
   trend=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int i,limit;
   double thigh1,tlow1,thigh2,tlow2,trendUp,trendDn;
   ArraySetAsSeries(open,true); ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); ArraySetAsSeries(close,true);
   if(prev_calculated==0)
     {
      limit=rates_total-1;
      BufLSELLBuffer[limit]=high[limit];
      BufLBUYBuffer[limit]=low[limit];
      limit--;
     }
   else limit=rates_total-prev_calculated+1;
   for(i=limit;i>=0;i--)
     {
      thigh1= high[iHighest(NULL,0,MODE_HIGH,SlowLength,i)]+SlowPipDisplace * _Point;
      tlow1 = low[iLowest(NULL,0,MODE_LOW,SlowLength,i)]-SlowPipDisplace * _Point;
      thigh2= high[iHighest(NULL,0,MODE_HIGH,FastLength,i)]+FastPipDisplace * _Point;
      tlow2 = low[iLowest(NULL,0,MODE_LOW,FastLength,i)]-FastPipDisplace * _Point;
      if(close[i]>BufLBUYBuffer[i+1])  trendUp=tlow1;  else trendUp=thigh1;
      if(close[i]>BufLSELLBuffer[i+1]) trendDn=tlow2;  else trendDn=thigh2;
      BufLSELLBuffer[i]= trendDn;
      BufLBUYBuffer[i] = trendUp;
      BufBarsBuffer1[i] = 0.0;
      BufBarsBuffer2[i] = 0.0;
      BufBarsBuffer3[i] = 0.0;
      BufBarsBuffer4[i] = 0.0;
      BufBarsColors[i]  = 2;
      if(close[i]<trendUp && close[i]<trendDn)
        {
         BufBarsBuffer1[i] = open[i];
         BufBarsBuffer2[i] = high[i];
         BufBarsBuffer3[i] = low[i];
         BufBarsBuffer4[i] = close[i];
         BufBarsColors[i]  = 0;
        }
      if(close[i]>trendUp && close[i]>trendDn)
        {
         BufBarsBuffer1[i] = open[i];
         BufBarsBuffer2[i] = high[i];
         BufBarsBuffer3[i] = low[i];
         BufBarsBuffer4[i] = close[i];
         BufBarsColors[i]  = 1;
        }
      if(close[i]>trendUp && close[i]>trendDn && trend!=1)
        {
         BufABUYBuffer[i]=trendDn;
         BufASELLBuffer[i]=0.0;
         trend=1;
        }
      if(close[i]<trendUp && close[i]<trendDn && trend!=2)
        {
         BufASELLBuffer[i]=trendUp;
         BufABUYBuffer[i]=0.0;
         trend=2;
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

MT4:

//+------------------------------------------------------------------+
//|                                            PerfecTrend Lines.mq4 |
//|                 Copyright © 2005-2007, MetaQuotes Software Corp. |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_color3 Red
#property indicator_color4 Aqua
#property indicator_color5 Blue
#property indicator_color6 Red

extern int SlowLength         = 7; // Slow length
extern int SlowPipDisplace    = 0; // Slow pip displace
extern int FastLength         = 3; // Fast length
extern int FastPipDisplace    = 0; // Fast pip displace

double Buf_NTLine1[],Buf_NTLine2[],Buf_NTBar1[],Buf_NTBar2[],Buf_NTSig1[],Buf_NTSig2[];
static int trend=0;
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(6);
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
   SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2);
   SetIndexBuffer(0,Buf_NTLine1);
   SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,2);
   SetIndexBuffer(1,Buf_NTLine2);
   SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_SOLID,2);
   SetIndexBuffer(2,Buf_NTBar1);
   SetIndexStyle(3,DRAW_HISTOGRAM,STYLE_SOLID,2);
   SetIndexBuffer(3,Buf_NTBar2);
   SetIndexStyle(4,DRAW_ARROW,STYLE_DASH,3);
   SetIndexArrow(4,108);
   SetIndexBuffer(4,Buf_NTSig1);
   SetIndexStyle(5,DRAW_ARROW,STYLE_DASH,3);
   SetIndexArrow(5,108);
   SetIndexBuffer(5,Buf_NTSig2);
   IndicatorShortName("NeuroTrend");
   SetIndexLabel(0,"NTLine1");
   SetIndexLabel(1,"NTLine2");
   SetIndexLabel(2,"NTBar1");
   SetIndexLabel(3,"NTBar2");
   SetIndexLabel(4,"NTSig1");
   SetIndexLabel(5,"NTSig2");
   SetIndexDrawBegin(0,FastLength+1);
   SetIndexDrawBegin(1,FastLength+1);
   SetIndexDrawBegin(2,FastLength+1);
   SetIndexDrawBegin(3,FastLength+1);
   SetIndexDrawBegin(4,FastLength+1);
   SetIndexDrawBegin(5,FastLength+1);
   trend=0;
   return (0);
  }
//+------------------------------------------------------------------+
int deinit()
  {
   return (0);
  }
//+------------------------------------------------------------------+
int start()
  {
   int i,limit;
   double thigh1,tlow1,thigh2,tlow2,trendA,trendB,trendUP,trendDN;
   if(Bars <= FastLength) return (0);
   if(IndicatorCounted()==0) limit=Bars-1;
   if(IndicatorCounted()>0) limit=Bars-IndicatorCounted()-1;
   for(i=limit;i>=0;i--)
     {
      thigh1= High[iHighest(NULL,0,MODE_HIGH,SlowLength,i)]+SlowPipDisplace * Point;
      tlow1 = Low[iLowest(NULL,0,MODE_LOW,SlowLength,i)]-SlowPipDisplace * Point;
      thigh2= High[iHighest(NULL,0,MODE_HIGH,FastLength,i)]+FastPipDisplace * Point;
      tlow2 = Low[iLowest(NULL,0,MODE_LOW,FastLength,i)]-FastPipDisplace * Point;
      if(Close[i] > Buf_NTLine1[i+1]) trendA = tlow1; else trendA = thigh1;
      if(Close[i] > Buf_NTLine2[i+1]) trendB = tlow2; else trendB = thigh2;
      Buf_NTLine1[i] = trendA;
      Buf_NTLine2[i] = trendB;

      trendUP = 0.0;
      trendDN = 0.0;
      if(Close[i] < trendA && Close[i] < trendB) { trendUP = High[i]; trendDN = Low[i]; }
      if(Close[i] > trendA && Close[i] > trendB) { trendUP = Low[i];  trendDN = High[i];}
      Buf_NTBar1[i] = trendUP;
      Buf_NTBar2[i] = trendDN;
      if(Close[i] > trendB && Close[i] > trendA && trend != 1) { Buf_NTSig1[i] = trendB; Buf_NTSig2[i] = EMPTY_VALUE; trend = 1; }
      if(Close[i] < trendB && Close[i] < trendA && trend != 2) { Buf_NTSig2[i] = trendB; Buf_NTSig1[i] = EMPTY_VALUE; trend = 2; }
     }
   return (0);
  }
//+------------------------------------------------------------------+
 
Igor Makanu:

I've been flipping all night tonight, but my patience has run out (((

as far as i understand the problem:

- in MT5 the arrays that are assigned to indicator buffers are indexed from left to right by default;

- in MT5 time seriesopen[], high[], low[], close[] available from OnCalculate() are always passed indexed from right to left

- i.e. based on steps 1 and 2, in order to calculate the indicator from the end of the history to the zero bar

a) or reassign the buffer arrays indexing

b) or to make a loop in which the array elements will be recalculated from left to right, and in another loop from right to left:


i.e., there isno beautiful solution to my question? variant a) - in my source code is implemented, variant b) - I don't see the point in doing extra calculations

All arrays are indexed from right to left. Therefore, to fully comply with the loop from left to right (and it is from left to right - from limit to 0), you need to set all used arrays to required indexing: buffers in OnInit(), used timeservers - in OnCalculate().

Or, do the cycle from 0 to limit, which is not always easy to do when mql4 is ported to mql5.

Therefore, the ArraySetAsSeries() option is better in this case.

 
Artyom Trishkin:

All arrays are indexed from right to left. Therefore, to fully comply with the loop from left to right (and it is from left to right from limit to 0), you need to set all used arrays to required indexing: buffers in OnInit(), used timeservers - in OnCalculate().

Or, you have to do the cycle from 0 to limit, which is not always easy to do when mql4 is ported to mql5.

That's why in this case the ArraySetAsSeries() method works better.

Look, remove allArraySetAsSeries() from your code(above in Init() and OnCalculate() in first lines) and corrected the loop:

for(i=0;i<limit;i++)

Theoretically, everything should fit together! But no! The charts turned out different - this is what I cannot figure out!

Files:
1.jpg  747 kb
 
Igor Makanu:

Look, I removed allArraySetAsSeries() from my code(at the top in Init() and in OnCalculate() in the first lines) and fixed the loop:

for(i=0;i<limit;i++)

In theory, everything should fit together! But no! The charts turned out different, and that's what I cannot figure out!

I'm telling you - it's more complicated than that. You have to change the logic. It's not enough just to invert the loop.

Here's one small example: in the code there is

Buf_NTLine1[i+1])

Where will the i+1 index go when the arrays are indexed differently?

And there's a lot of it. IHighest() - start and number. Where does it start at one indexation and where does it start at another?

And so on ...

 
Artyom Trishkin:

and there's a lot of it. IHighest() - start and number of... Where does it start at one indexing and at the other?

oh man! that's right! well done!!! yeah, that's the tricky part!!!

Yeah... a lot of differences in MT5, a lot of checks and all sorts of precautions on the programmer's head...

When I saw it not long ago I had a message that in MT5 not always everythingis initialized correctly inInit(), it looks likeInit() may end even if timeframes are not ready.

I saw a bug yesterday: if this indicator in MT5 switches timeframes, sometimes indicator buffers may not be empty - it seems the old values remain if not to assign a specific value to each element in the indicator array in OnCalculate(), I triedto put ArrayInitialize(arr, 0.0) inInit()- it works too, then not...

as far as I understand it correctly:

- in MT5, at initialization inInit(), indicator buffers are not initialized automatically? (in MT4 I do not remember anything remained in buffers)

- in MT5 inInit() the sizes of buffer arrays may be unknown if the history is not loaded, that is whyArrayInitialize(arr, 0.0) also does not always initialize buffers correctly?

 
Igor Makanu:

Damn it! That's right! Well done!!! Yeah, that's the fun part!!!

Yeah... There are a lot of differences in MT5, the programmer has a lot of checks and all sorts of precautions...

When I saw it not long ago I had a message that in MT5 not always everythingis initialized correctly inInit(), it looks likeInit() may end even if timeframes are not ready.

I saw a bug yesterday: if this indicator in MT5 switches timeframes, sometimes indicator buffers may not be empty - it seems the old values remain if not to assign a specific value to each element in the indicator array in OnCalculate(), I triedto put ArrayInitialize(arr, 0.0) inInit()- it works too, then not...

as far as I understand it correctly:

- in MT5, at initialization inInit(), indicator buffers are not initialized automatically? (in MT4 I do not remember anything remained in buffers)

- in MT5 inInit() the sizes of buffer arrays may be unknown if the history is not loaded, that is whyArrayInitialize(arr, 0.0) also does not always initialize buffers correctly?

//+------------------------------------------------------------------+
//|                                            PerfecTrend Lines.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 9
#property indicator_plots   5
//--- plot Top
#property indicator_label1  "Top"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Bottom
#property indicator_label2  "Bottom"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Candles
#property indicator_label3  "Open;High;Low;Close"
#property indicator_type3   DRAW_COLOR_CANDLES
#property indicator_color3  clrDodgerBlue,clrOrangeRed,clrDarkGray
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot ArrowUP
#property indicator_label4  "ArrowUP"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot ArrowDN
#property indicator_label5  "ArrowDN"
#property indicator_type5   DRAW_ARROW
#property indicator_color5  clrBlue
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1
//--- input parameters
input uint     InpPeriodSlow     =  7;    // Slow length
input uint     InpDistanceSlow   =  0;    // Slow pip displace
input uint     InpPeriodFast     =  3;    // Fast length
input uint     InpDistanceFast   =  0;    // Fast pip displace
//--- indicator buffers
double         BufferTop[];
double         BufferBottom[];
double         BufferCandlesOpen[];
double         BufferCandlesHigh[];
double         BufferCandlesLow[];
double         BufferCandlesClose[];
double         BufferColors[];
double         BufferArrowUP[];
double         BufferArrowDN[];
//--- global variables
int            period_slow;
int            period_fast;
int            period_max;
double         distance_slow;
double         distance_fast;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- set global variables
   period_fast=int(InpPeriodFast<1 ? 1 : InpPeriodFast);
   period_slow=int(InpPeriodSlow<1 ? 1 : InpPeriodSlow);
   period_max=fmax(period_fast,period_slow);
   distance_fast=InpDistanceFast*Point();
   distance_slow=InpDistanceSlow*Point();
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferTop,INDICATOR_DATA);
   SetIndexBuffer(1,BufferBottom,INDICATOR_DATA);
   SetIndexBuffer(2,BufferCandlesOpen,INDICATOR_DATA);
   SetIndexBuffer(3,BufferCandlesHigh,INDICATOR_DATA);
   SetIndexBuffer(4,BufferCandlesLow,INDICATOR_DATA);
   SetIndexBuffer(5,BufferCandlesClose,INDICATOR_DATA);
   SetIndexBuffer(6,BufferColors,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(7,BufferArrowUP,INDICATOR_DATA);
   SetIndexBuffer(8,BufferArrowDN,INDICATOR_DATA);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(3,PLOT_ARROW,108);
   PlotIndexSetInteger(4,PLOT_ARROW,108);
//--- setting indicator parameters
   IndicatorSetString(INDICATOR_SHORTNAME,"NeuroTrend");
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//--- setting buffer arrays as timeseries
   ArraySetAsSeries(BufferTop,true);
   ArraySetAsSeries(BufferBottom,true);
   ArraySetAsSeries(BufferCandlesOpen,true);
   ArraySetAsSeries(BufferCandlesHigh,true);
   ArraySetAsSeries(BufferCandlesLow,true);
   ArraySetAsSeries(BufferCandlesClose,true);
   ArraySetAsSeries(BufferColors,true);
   ArraySetAsSeries(BufferArrowUP,true);
   ArraySetAsSeries(BufferArrowDN,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- Установка массивов буферов как таймсерий
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
//--- Проверка и расчёт количества просчитываемых баров
   if(rates_total<fmax(period_max,4)) return 0;
   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-period_max-1;
      ArrayInitialize(BufferTop,EMPTY_VALUE);
      ArrayInitialize(BufferBottom,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesOpen,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesHigh,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesLow,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesClose,EMPTY_VALUE);
      ArrayInitialize(BufferArrowUP,EMPTY_VALUE);
      ArrayInitialize(BufferArrowDN,EMPTY_VALUE);
     }
//---
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      int bhs=Highest(period_slow,i);
      int bls=Lowest(period_slow,i);
      int bhf=Highest(period_fast,i);
      int blf=Lowest(period_fast,i);
      if(bhs==WRONG_VALUE || bls==WRONG_VALUE || bhf==WRONG_VALUE || blf==WRONG_VALUE)
         continue;
      double thigh1=high[bhs]+distance_slow;
      double tlow1=low[bls]-distance_slow;
      double thigh2=high[bhf]+distance_fast;
      double tlow2=low[blf]-distance_fast;
      
      double trendA=(close[i]>BufferTop[i+1] ? tlow1 : thigh1);
      double trendB=(close[i]>BufferBottom[i+1] ? tlow2 : thigh2);
      BufferTop[i]=trendA;
      BufferBottom[i]=trendB;

      double trendUP=0;
      double trendDN=0;
      
      BufferCandlesOpen[i]=open[i];
      BufferCandlesHigh[i]=high[i];
      BufferCandlesLow[i]=low[i];
      BufferCandlesClose[i]=close[i];
      BufferColors[i]=2;
      if(close[i]<trendA && close[i]<trendB)
        {
         BufferColors[i]=1;
         trendUP=high[i];
         trendDN=low[i];
        }
      else if(close[i]>trendA && close[i]>trendB)
        {
         BufferColors[i]=0;
         trendUP=low[i];
         trendDN=high[i];
        }
      else
        {
         BufferCandlesOpen[i]=EMPTY_VALUE;
         BufferCandlesHigh[i]=EMPTY_VALUE;
         BufferCandlesLow[i]=EMPTY_VALUE;
         BufferCandlesClose[i]=EMPTY_VALUE;
        }
      static int trend=0;
      BufferArrowUP[i]=BufferArrowDN[i]=EMPTY_VALUE;
      if(close[i]>trendB && close[i]>trendA && trend!=1)
        {
         BufferArrowDN[i]=trendB;
         BufferArrowUP[i]=EMPTY_VALUE;
         trend=1;
        }
      if(close[i]<trendB && close[i]<trendA && trend!=2)
        {
         BufferArrowUP[i]=trendB;
         BufferArrowDN[i]=EMPTY_VALUE;
         trend=2;
        }
     }
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Возвращает индекс максимального значения таймсерии High          |
//+------------------------------------------------------------------+
int Highest(const int count,const int start,const bool as_series=true)
  {
   double array[];
   ArraySetAsSeries(array,as_series);
   return(CopyHigh(NULL,PERIOD_CURRENT,start,count,array)==count ? ArrayMaximum(array)+start : WRONG_VALUE);
  }
//+------------------------------------------------------------------+
//| Возвращает индекс минимального значения таймсерии Low            |
//+------------------------------------------------------------------+
int Lowest(const int count,const int start,const bool as_series=true)
  {
   double array[];
   ArraySetAsSeries(array,as_series);
   return(CopyLow(NULL,PERIOD_CURRENT,start,count,array)==count ? ArrayMinimum(array)+start : WRONG_VALUE);
  }
//+------------------------------------------------------------------+

Didn't really get into the logic of it.

 
Artyom Trishkin:

Didn't really get into the logic of it.

This is the right way to go: don't put entry points at max/min price - better at the opening price.

//+------------------------------------------------------------------+
//|                                            PerfecTrend Lines.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 9
#property indicator_plots   5
//--- plot Top
#property indicator_label1  "Top"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Bottom
#property indicator_label2  "Bottom"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Candles
#property indicator_label3  "Open;High;Low;Close"
#property indicator_type3   DRAW_COLOR_CANDLES
#property indicator_color3  clrDodgerBlue,clrOrangeRed,clrDarkGray
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot ArrowUP
#property indicator_label4  "ArrowUP"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot ArrowDN
#property indicator_label5  "ArrowDN"
#property indicator_type5   DRAW_ARROW
#property indicator_color5  clrBlue
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1
//--- input parameters
input uint     InpPeriodSlow     =  7;    // Slow length
input uint     InpDistanceSlow   =  0;    // Slow pip displace
input uint     InpPeriodFast     =  3;    // Fast length
input uint     InpDistanceFast   =  0;    // Fast pip displace
//--- indicator buffers
double         BufferTop[];
double         BufferBottom[];
double         BufferCandlesOpen[];
double         BufferCandlesHigh[];
double         BufferCandlesLow[];
double         BufferCandlesClose[];
double         BufferColors[];
double         BufferArrowUP[];
double         BufferArrowDN[];
//--- global variables
int            period_slow;
int            period_fast;
int            period_max;
double         distance_slow;
double         distance_fast;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- set global variables
   period_fast=int(InpPeriodFast<1 ? 1 : InpPeriodFast);
   period_slow=int(InpPeriodSlow<1 ? 1 : InpPeriodSlow);
   period_max=fmax(period_fast,period_slow);
   distance_fast=InpDistanceFast*Point();
   distance_slow=InpDistanceSlow*Point();
//--- indicator buffers mapping
   SetIndexBuffer(0,BufferTop,INDICATOR_DATA);
   SetIndexBuffer(1,BufferBottom,INDICATOR_DATA);
   SetIndexBuffer(2,BufferCandlesOpen,INDICATOR_DATA);
   SetIndexBuffer(3,BufferCandlesHigh,INDICATOR_DATA);
   SetIndexBuffer(4,BufferCandlesLow,INDICATOR_DATA);
   SetIndexBuffer(5,BufferCandlesClose,INDICATOR_DATA);
   SetIndexBuffer(6,BufferColors,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(7,BufferArrowUP,INDICATOR_DATA);
   SetIndexBuffer(8,BufferArrowDN,INDICATOR_DATA);
//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(3,PLOT_ARROW,108);
   PlotIndexSetInteger(4,PLOT_ARROW,108);
//--- setting indicator parameters
   IndicatorSetString(INDICATOR_SHORTNAME,"NeuroTrend");
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//--- setting buffer arrays as timeseries
   ArraySetAsSeries(BufferTop,true);
   ArraySetAsSeries(BufferBottom,true);
   ArraySetAsSeries(BufferCandlesOpen,true);
   ArraySetAsSeries(BufferCandlesHigh,true);
   ArraySetAsSeries(BufferCandlesLow,true);
   ArraySetAsSeries(BufferCandlesClose,true);
   ArraySetAsSeries(BufferColors,true);
   ArraySetAsSeries(BufferArrowUP,true);
   ArraySetAsSeries(BufferArrowDN,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- Установка массивов буферов как таймсерий
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
//--- Проверка и расчёт количества просчитываемых баров
   if(rates_total<fmax(period_max,4)) return 0;
   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-period_max-1;
      ArrayInitialize(BufferTop,EMPTY_VALUE);
      ArrayInitialize(BufferBottom,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesOpen,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesHigh,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesLow,EMPTY_VALUE);
      ArrayInitialize(BufferCandlesClose,EMPTY_VALUE);
      ArrayInitialize(BufferArrowUP,EMPTY_VALUE);
      ArrayInitialize(BufferArrowDN,EMPTY_VALUE);
     }
//---
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      int bhs=Highest(period_slow,i);
      int bls=Lowest(period_slow,i);
      int bhf=Highest(period_fast,i);
      int blf=Lowest(period_fast,i);
      if(bhs==WRONG_VALUE || bls==WRONG_VALUE || bhf==WRONG_VALUE || blf==WRONG_VALUE)
         continue;
      double thigh1=high[bhs]+distance_slow;
      double tlow1=low[bls]-distance_slow;
      double thigh2=high[bhf]+distance_fast;
      double tlow2=low[blf]-distance_fast;
      
      double trendA=(close[i]>BufferTop[i+1] ? tlow1 : thigh1);
      double trendB=(close[i]>BufferBottom[i+1] ? tlow2 : thigh2);
      BufferTop[i]=trendA;
      BufferBottom[i]=trendB;
      
      BufferCandlesOpen[i]=open[i];
      BufferCandlesHigh[i]=high[i];
      BufferCandlesLow[i]=low[i];
      BufferCandlesClose[i]=close[i];
      BufferColors[i]=2;
      if(close[i]<trendA && close[i]<trendB)
         BufferColors[i]=1;
      else if(close[i]>trendA && close[i]>trendB)
         BufferColors[i]=0;
      else
        {
         BufferCandlesOpen[i]=EMPTY_VALUE;
         BufferCandlesHigh[i]=EMPTY_VALUE;
         BufferCandlesLow[i]=EMPTY_VALUE;
         BufferCandlesClose[i]=EMPTY_VALUE;
        }
      static int trend=0;
      BufferArrowUP[i]=BufferArrowDN[i]=EMPTY_VALUE;
      if(close[i]>trendB && close[i]>trendA && trend!=1)
        {
         BufferArrowDN[i]=open[i];
         BufferArrowUP[i]=EMPTY_VALUE;
         trend=1;
        }
      if(close[i]<trendB && close[i]<trendA && trend!=2)
        {
         BufferArrowUP[i]=open[i];
         BufferArrowDN[i]=EMPTY_VALUE;
         trend=2;
        }
     }
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Возвращает индекс максимального значения таймсерии High          |
//+------------------------------------------------------------------+
int Highest(const int count,const int start,const bool as_series=true)
  {
   double array[];
   ArraySetAsSeries(array,as_series);
   return(CopyHigh(NULL,PERIOD_CURRENT,start,count,array)==count ? ArrayMaximum(array)+start : WRONG_VALUE);
  }
//+------------------------------------------------------------------+
//| Возвращает индекс минимального значения таймсерии Low            |
//+------------------------------------------------------------------+
int Lowest(const int count,const int start,const bool as_series=true)
  {
   double array[];
   ArraySetAsSeries(array,as_series);
   return(CopyLow(NULL,PERIOD_CURRENT,start,count,array)==count ? ArrayMinimum(array)+start : WRONG_VALUE);
  }
//+------------------------------------------------------------------+

And the lines should be removed - what for are they on the chart? If only to drag a stop on them?

 

declaration without type

If I compile a include file, there's no error. If I compile the main program file where I include this include file, there is a declaration without type error. It doesn't see the object declared in the include file protected CSomeClass *object. The include file has the #include "SomeClass.mqh" directive. And in the main file, an object of the class of the included file is created and one of the methods is called.