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

 

Por favor, ayuda con el error.

Texto de error "2018.07.05 15:21:32.080 StBB0 (EURUSD,M5) array out of range in 'StBB0.mq5' (139,33)"

No entiendo por qué se calculan los valores de todo el array, aunque he especificado explícitamente sólo los 5 primeros candeleros (la sustitución con values_to_copy no ayuda).

//+------------------------------------------------------------------+
//|                                                         StBB0.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
//#property indicator_chart_window 
//#property indicator_minimum 1
//#property indicator_maximum 100

#property indicator_buffers 4 
#property indicator_plots   1 

//--- построение Middle 
#property indicator_label1  "Middle" 
#property indicator_type1   DRAW_LINE 
#property indicator_color1  clrMediumSeaGreen 
#property indicator_style1  STYLE_SOLID 
#property indicator_width1  1 
//--- построение Upper 
#property indicator_label3  "Upper" 
#property indicator_type3  DRAW_LINE 
#property indicator_color3  clrMediumSeaGreen 
#property indicator_style3  STYLE_SOLID 
#property indicator_width3  1 
//--- построение Lower 
#property indicator_label2  "Lower" 
#property indicator_type2   DRAW_LINE 
#property indicator_color2  clrMediumSeaGreen 
#property indicator_style2  STYLE_SOLID 
#property indicator_width2  1 


//--- индикаторные буферы 
double         UpperBuffer[];
double         LowerBuffer[];
double         MiddleBuffer[];

double         Buffer[];

input int                  bands_period=20;           // период скользящей средней 
input int                  bands_shift=0;             // сдвиг 
input double               deviation=2.0;             // кол-во стандартных отклонений  
input ENUM_APPLIED_PRICE   applied_price=PRICE_CLOSE; // тип цены 

//--- переменная для хранения хэндла индикатора iBands 
int    handle;
//--- будем хранить количество значений в индикаторе Bollinger Bands 
int    bars_calculated=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
//--- привязка массивов к индикаторным буферам 
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(2,UpperBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(1,LowerBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,MiddleBuffer,INDICATOR_CALCULATIONS);
//--- зададим смещение для каждой линии 
   PlotIndexSetInteger(0,PLOT_SHIFT,bands_shift);
//PlotIndexSetInteger(1,PLOT_SHIFT,bands_shift);
//PlotIndexSetInteger(2,PLOT_SHIFT,bands_shift);

//---- индексация элементов в буферах как в таймсериях  
   ArraySetAsSeries(UpperBuffer,true);
   ArraySetAsSeries(LowerBuffer,true);
   ArraySetAsSeries(MiddleBuffer,true);
   ArraySetAsSeries(Buffer,true);
//--- создадим хэндл индикатора 

   handle=iBands(_Symbol,PERIOD_CURRENT,bands_period,bands_shift,deviation,applied_price);

//--- если не удалось создать хэндл 
   if(handle==INVALID_HANDLE)
     {
      //--- сообщим о неудаче и выведем номер ошибки 
      PrintFormat("Не удалось создать хэндл индикатора iBands для пары %s/%s, код ошибки %d",_Symbol,EnumToString(PERIOD_CURRENT),GetLastError());       //--- работа индикатора завершается досрочно 
      return(INIT_FAILED);
     }

//---
   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[])
  {
//--- количество копируемых значений из индикатора iBands 
   int values_to_copy;
//--- узнаем количество рассчитанных значений в индикаторе 
   int calculated=BarsCalculated(handle);
   if(calculated<=0)
     {
      PrintFormat("BarsCalculated() вернул %d, код ошибки %d",calculated,GetLastError());
      return(0);
     }
//--- если это первый запуск вычислений нашего индикатора или изменилось количество значений в индикаторе iBands 
//--- или если необходимо рассчитать индикатор для двух или более баров (значит что-то изменилось в истории) 
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
     {
      //--- если размер индикаторных массивов больше, чем значений в индикаторе iBands на паре symbol/period, то копируем не все  
      //--- в противном случае копировать будем меньше, чем размер индикаторных буферов 
      if(calculated>rates_total) values_to_copy=rates_total;
      else                       values_to_copy=calculated;
     }
   else
     {
      //--- значит наш индикатор рассчитывается не в первый раз и с момента последнего вызова OnCalculate()) 
      //--- для расчета добавилось не более одного бара 
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- заполняем массив значениями из индикатора Bollinger Bands 
//--- если FillArraysFromBuffer вернула false, значит данные не готовы - завершаем работу 
   if(!FillArraysFromBuffers(MiddleBuffer,UpperBuffer,LowerBuffer,bands_shift,handle,values_to_copy)) return(0);
//--- сформируем сообщение 
   string comm=StringFormat("%s ==>  Обновлено значений в индикаторе %s: %d",
                            TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS),values_to_copy);
//--- выведем на график служебное сообщение 
//Comment(comm); 
   if(ArraySize(UpperBuffer)>0)
     {
      for(int bar=0; 0<5 && !IsStopped(); bar++)   
      {
         double _max=UpperBuffer[bar];
         double _min=LowerBuffer[bar];
         double _Close=iClose(_Symbol,PERIOD_CURRENT,bar);
         Buffer[bar]=MathAbs((((_max+_min)/2)-_Close));
        };

     };

//Print(bars_calculated);
//--- запомним количество значений в индикаторе Bollinger Bands 
   bars_calculated=calculated;
//--- вернем значение prev_calculated для следующего вызова 
   return(rates_total);
  }
//+------------------------------------------------------------------+ 
//| Заполняем индикаторные буферы из индикатора iBands               | 
//+------------------------------------------------------------------+ 
bool FillArraysFromBuffers(double &base_values[],     // индикаторный буфер средней линии Bollinger Bands 
                           double &upper_values[],    // индикаторный буфер верхней границы 
                           double &lower_values[],    // индикаторный буфер нижней границы 
                           int shift,                 // смещение 
                           int ind_handle,            // хэндл индикатора iBands 
                           int amount                 // количество копируемых значений 
                           )
  {
//--- сбросим код ошибки 
   ResetLastError();
//--- заполняем часть массива MiddleBuffer значениями из индикаторного буфера под индексом 0 
   if(CopyBuffer(ind_handle,0,-shift,amount,base_values)<0)
     {
      //--- если копирование не удалось, сообщим код ошибки 
      PrintFormat("Не удалось скопировать данные из индикатора iBands, код ошибки %d",GetLastError());
      //--- завершим с нулевым результатом - это означает, что индикатор будет считаться нерассчитанным 
      return(false);
     }

//--- заполняем часть массива UpperBuffer значениями из индикаторного буфера под индексом 1 
   if(CopyBuffer(ind_handle,1,-shift,amount,upper_values)<0)
     {
      //--- если копирование не удалось, сообщим код ошибки 
      PrintFormat("Не удалось скопировать данные из индикатора iBands, код ошибки %d",GetLastError());
      //--- завершим с нулевым результатом - это означает, что индикатор будет считаться нерассчитанным 
      return(false);
     }

//--- заполняем часть массива LowerBuffer значениями из индикаторного буфера под индексом 2 
   if(CopyBuffer(ind_handle,2,-shift,amount,lower_values)<0)
     {
      //--- если копирование не удалось, сообщим код ошибки 
      PrintFormat("Не удалось скопировать данные из индикатора iBands, код ошибки %d",GetLastError());
      //--- завершим с нулевым результатом - это означает, что индикатор будет считаться нерассчитанным 
      return(false);
     }
//--- все получилось 
   return(true);
  }
//+------------------------------------------------------------------+ 
//| Indicator deinitialization function                              | 
//+------------------------------------------------------------------+ 
void OnDeinit(const int reason)
  {
//--- почистим график при удалении индикатора 
   Comment("");
  }
//+------------------------------------------------------------------+
 
SEM:

Por favor, ayuda con el error.

Texto de error "2018.07.05 15:21:32.080 StBB0 (EURUSD,M5) array out of range in 'StBB0.mq5' (139,33)"

No está claro por qué los valores se calculan para toda la matriz, a pesar de que he seleccionado explícitamente sólo las 5 primeras velas (la sustitución con values_to_copy no ayuda).

¿En qué se equivoca? Por favor, marque la línea con el color.

 

¡О!

¿Por qué el "0" DIGITAL se compara con el número "5"?

      for(int bar=0; 0<5 && !IsStopped(); bar++)
 
Vladimir Karputov:

¡О!

¿Y por qué el "0" DIGITAL se compara con el número "5"?

Me confundí, lo sustituí por "bar<valores_a_copiar ", todo funciona)

Gracias.

 
Vladimir Karputov:

La solución es la siguiente: en el módulo de señales


En el Asesor Experto que fue generado por el Asistente MQL5:


El resultado final:


Vladimir, gracias por el código - ¡todo funciona! La única pregunta que queda es por qué mi enum no puede ser declarado directamente en el módulo de señales, sino sólo en el código principal del Asesor Experto.

 
Andy:

Vladimir, gracias por el código - ¡todo funciona! Sólo queda una pregunta: ¿por qué no puedo declarar mi enum directamente en el módulo de señales, sino sólo en el código principal del EA?

No lo sé. Yo sólo supondría que en la época en que se inventaron los módulos de señales, nadie pensó que enum pudiera utilizarse como tipo de variable. Es decir, no estaba previsto.

 
Sí, supongo que sí. Y toma las enumeraciones de los MAs de la biblioteca estándar - puedes ponerlas directamente en la descripción de tu módulo de señales.
 
Andy:
Sí, supongo que sí. Y toma los enums de los MAs de la biblioteca estándar y puedes ponerlos directamente en la descripción de tu módulo de señales.

Me refería a que no se proporcionaba el enum personalizado.

 
Sí, ¡y hay transferencias incorporadas desde MA!
 
Andy:
Sí, pero los enums incorporados de MA lo son.