Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 919

 
Artyom Trishkin:

El cálculo de su indicador es desde el principio hasta el final (desde los datos históricos más recientes hasta los datos actuales más recientes). Esto es una indicación de indexación como en las series temporales. Así que las matrices deben ser indexadas en consecuencia, que es lo que tienes.

¿Qué tiene de malo?

Todo funciona igual que mi port en MQL5 desde MQL4, pero veo que el código es feo por culpa deArraySetAsSeries(), por eso preguntaba

aquí están los dos códigos

¡enséñame a escribir este indicador para MT5! - Mi código no es agradable, ¡y punto! )))

ZSZ no recuerdo cómo escribir indicadores para MT5, se sentó y lo reescribió en 40 minutos usando la Ayuda, pero el resultado ... ¡imho, no tan bueno ((!

Archivos adjuntos:
PTL.mq4  8 kb
PTL.mq5  13 kb
 
Igor Makanu:

Sí, todo funciona exactamente como mi puerto en MQL5 desde MQL4, pero veo que el código es feo debido aArraySetAsSeries(), así que pregunté

aquí están los dos códigos

¡enséñame a escribir este indicador para MT5! - Mi código no es agradable, ¡y punto! )))

Cuando se invierte el bucle, hay que hacer las matrices de series de tiempo, de lo contrario la indexación de los búferes en el bucle no coincidirá con la indexación de los datos requeridos - el índice del bucle en la matriz de los búferes del indicador irá desde el principio hasta el final, mientras que en open[], high[], low[], close[] y otros - desde el final hasta el principio. O bien, puede invertir el bucle para que coincida con su indexación de arrays open[], high[], low[], close[] y el resto con la indexación de buffers, lo cual es más complicado.

Si quieres una alegoría para que quede más claro, aquí tienes una alegoría:

Estás parado en las vías del tren y mirando dos trenes. O bien van en una dirección - ambos de izquierda a derecha (ArraySetAsSeries(array,true) - primer tren y un bucle de límite a 0 - segundo tren),
O van hacia el otro - (ArraySetAsSeries(array,false) - de derecha a izquierda - primer tren, y el bucle de límite a 0 - de izquierda a derecha - segundo tren)

Y, sí: no he mirado el código - no quiero descargar, guardar (ya hay mucho código innecesario del foro), compararlos entre sí...

Sería más fácil ponerlos en códigos en el mensaje - uno y otro - entonces sería visible de una vez qué a qué.

 
Artyom Trishkin:

O dar la vuelta al bucle para que coincida con su indexación de arrays open[], high[], low[], close[] y el resto, que es más difícil.

Llevo toda la noche dando marcha atrás, se me ha acabado la paciencia (((

Por lo que entiendo el problema:

- en MT5 las matrices que se asignan a los buffers de los indicadores se indexan de izquierda a derecha por defecto;

- en MT5 las series temporalesopen[], high[], low[], close[] disponibles en OnCalculate() se pasan siempre indexadas de derecha a izquierda

- es decir, basándose en los pasos 1 y 2, para calcular el indicador desde el final de la historia hasta la barra cero

a) o reasignar la indexación de las matrices del buffer

b) o hacer un bucle en el que los elementos del array se recalculen de izquierda a derecha, y en otro bucle de derecha a izquierda:

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


es decir,no hay una solución hermosa a mi pregunta? opción a) - en mis fuentes se implementa, la opción b) - no veo el punto de hacer cálculos adicionales

fuentes:

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:

He estado flipando toda la noche, pero se me ha acabado la paciencia (((

por lo que entiendo el problema:

- en MT5 las matrices que se asignan a los buffers de los indicadores se indexan de izquierda a derecha por defecto;

- en MT5 las series temporalesopen[], high[], low[], close[] disponibles en OnCalculate() se pasan siempre indexadas de derecha a izquierda

- es decir, basándose en los pasos 1 y 2, para calcular el indicador desde el final de la historia hasta la barra cero

a) o reasignar la indexación de las matrices del buffer

b) o hacer un bucle en el que los elementos del array se recalculen de izquierda a derecha, y en otro bucle de derecha a izquierda:


es decir,no hay una solución bonita a mi pregunta... variante a) - en mis fuentes está implementada, variante b) - no veo el sentido de hacer cálculos extra

Todas las matrices están indexadas de derecha a izquierda. Por lo tanto, para cumplir plenamente con el bucle de izquierda a derecha (y es de izquierda a derecha - de límite a 0), es necesario establecer todas las matrices utilizadas a la indexación requerida : buffers en OnInit(), timeservers utilizados - en OnCalculate().

O bien, hacer el ciclo de 0 a límite, que no siempre es fácil de hacer al portar de mql4 a mql5.

Por lo tanto, la opción ArraySetAsSeries() es mejor en este caso.

 
Artyom Trishkin:

Todas las matrices están indexadas de derecha a izquierda. Por lo tanto, para cumplir plenamente con el bucle de izquierda a derecha (y es de izquierda a derecha desde el límite hasta el 0), es necesario establecer todas las matrices utilizadas a la indexación requerida : buffers en OnInit(), timeservers utilizados - en OnCalculate().

O bien, tienes que hacer el ciclo de 0 a límite, que no siempre es fácil de hacer cuando mql4 es portado a mql5.

Por eso en este caso el método ArraySetAsSeries() funciona mejor.

Mira, elimina todos losArraySetAsSeries() de tu código(arriba en Init() y OnCalculate() en las primeras líneas) y corrige el bucle:

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

En teoría, todo debería encajar, pero no, los gráficos son diferentes, y eso es lo que no puedo entender.

Archivos adjuntos:
1.jpg  747 kb
 
Igor Makanu:

Mira, he eliminado todos losArraySetAsSeries() de mi código(al principio en Init() y en OnCalculate() en las primeras líneas) y he arreglado el bucle:

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

En teoría, todo debería encajar, pero no, los gráficos resultaron diferentes y eso es lo que no puedo entender.

Te digo que es más complicado que eso. Hay que cambiar la lógica. No basta con invertir el bucle.

He aquí un pequeño ejemplo: en el código hay

Buf_NTLine1[i+1])

¿Dónde irá el índice i+1 cuando las matrices estén indexadas de forma diferente?

Y hay mucho. IHighest() - inicio y número. ¿Dónde empieza en una indexación y dónde en otra?

Y así sucesivamente...

 
Artyom Trishkin:

y hay mucho. IHighest() - inicio y número de... ¿Dónde empieza en una indexación y en la otra?

¡¡¡Oh, hombre!!! ¡¡¡Bien hecho!!! ¡¡¡Sí, esa es la parte difícil!!!

Sí... muchas diferencias en MT5, muchas comprobaciones y todo tipo de precauciones en la cabeza del programador...

Cuando lo vi no hace mucho tenía un mensaje de que en MT5 no siemprese inicializa todocorrectamente enInit(), parece queInit() puede terminar incluso si los timeframes no están listos.

Ayer vi un error: si este indicador en MT5 cambia de timeframe, a veces los buffers del indicador pueden no estar vacíos - parece que los valores antiguos permanecen si no para asignar un valor específico a cada elemento del array del indicador en OnCalculate(), intentéponer ArrayInitialize(arr, 0.0) enInit()- también funciona, luego no...

por lo que entiendo correctamente:

- en MT5, en la inicialización enInit(), los buffers de los indicadores no se inicializan automáticamente? (en MT4 no recuerdo que haya quedado nada en los buffers)

- en MT5 enInit() los tamaños de las matrices debuffers pueden ser desconocidos si el historial no está cargado, por esoArrayInitialize(arr, 0.0) tampoco inicializa siempre los buffers correctamente?

 
Igor Makanu:

¡Maldita sea! ¡Eso es! ¡Bien hecho! ¡Sí, esa es la parte divertida!

Sí... Hay muchas diferencias en MT5, el programador tiene muchas comprobaciones y todo tipo de precauciones...

Cuando lo vi no hace mucho tenía un mensaje de que en MT5 no siemprese inicializa todocorrectamente enInit(), parece queInit() puede terminar incluso si los timeframes no están listos.

Ayer vi un error: si este indicador en MT5 cambia de timeframe, a veces los buffers del indicador pueden no estar vacíos - parece que los valores antiguos permanecen si no para asignar un valor específico a cada elemento del array del indicador en OnCalculate(), intentéponer ArrayInitialize(arr, 0.0) enInit()- también funciona, luego no...

por lo que entiendo correctamente:

- en MT5, en la inicialización enInit(), los buffers de los indicadores no se inicializan automáticamente? (en MT4 no recuerdo que haya quedado nada en los buffers)

- en MT5 enInit() los tamaños de las matrices debuffers pueden ser desconocidos si el historial no está cargado, por esoArrayInitialize(arr, 0.0) tampoco inicializa siempre los buffers correctamente?

//+------------------------------------------------------------------+
//|                                            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);
  }
//+------------------------------------------------------------------+

No se ha entrado en la lógica de la misma.

 
Artyom Trishkin:

No se ha entrado en la lógica de la misma.

Este es el camino correcto: no ponga puntos de entrada en el precio máximo/mínimo, mejor en el precio de apertura.

//+------------------------------------------------------------------+
//|                                            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);
  }
//+------------------------------------------------------------------+

Y las líneas deberían eliminarse: ¿para qué están en el gráfico? ¿Aunque sólo sea para arrastrar una parada sobre ellos?

 

declaración sin tipo

Si compilo un archivo de inclusión, no hay error. Si compilo el archivo del programa principal donde incluyo este archivo de inclusión, hay una declaración sin error de tipo. No ve el objeto declarado en el archivo de inclusión protected CSomeClass *object. El archivo de inclusión tiene la directiva #include "SomeClass.mqh". Y en el archivo principal se crea un objeto de la clase del archivo incluido y se llama a uno de los métodos.
Razón de la queja: