초보자의 질문 MQL5 MT5 MetaTrader 5 - 페이지 896

 

오류 수정을 도와주세요.

오류 텍스트 "2018.07.05 15:21:32.080 StBB0(EURUSD,M5) 배열이 'StBB0.mq5'(139,33)의 범위를 벗어났습니다."

처음 5개의 양초만 명시적으로 표시했지만(values_to_copy로 바꾸는 것은 도움이 되지 않음) 전체 배열의 값이 계산되는 이유는 분명하지 않습니다.

 //+------------------------------------------------------------------+
//|                                                         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 :

오류 수정을 도와주세요.

오류 텍스트 "2018.07.05 15:21:32.080 StBB0(EURUSD,M5) 배열이 'StBB0.mq5'(139,33)의 범위를 벗어났습니다."

처음 5개의 양초만 명시적으로 표시했지만(values_to_copy로 바꾸는 것은 도움이 되지 않음) 전체 배열의 값이 계산되는 이유는 분명하지 않습니다.

오류는 어디에 있습니까? 색상으로 선을 강조 표시합니다 .

 

영형!

그리고 DIGIT "0"이 숫자 "5"와 비교되는 이유는 무엇입니까?

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

영형!

그리고 DIGIT "0"이 숫자 "5"와 비교되는 이유는 무엇입니까?

계단식, "bar<values_to_copy"로 대체, 모든 것이 작동함)

고맙습니다!

 
Vladimir Karputov :

솔루션은 다음과 같습니다. 신호 모듈에서


MQL5 마법사에 의해 생성된 Expert Advisor에서:


결과:


블라디미르, 코드 감사합니다 - 모든 것이 작동합니다! 남은 질문은 하나뿐입니다. 왜 enum을 signal 모듈에서 즉시 선언할 수 없고 EA의 메인 코드에서만 선언할 수 있습니까?

 
Andy :

블라디미르, 코드 감사합니다 - 모든 것이 작동합니다! 남은 질문은 하나뿐입니다. 왜 enum을 signal 모듈에서 즉시 선언할 수 없고 EA의 메인 코드에서만 선언할 수 있습니까?

모르겠어요. 신호 모듈이 발명되었을 때 enum을 변수 유형으로 사용할 수 있다고 생각한 사람은 아무도 없었다고 가정하겠습니다. 제공되지 않습니다.

 
예, 아마도. 또한 표준 라이브러리 의 MA에서 열거를 가져옵니다. 즉시 신호 모듈의 설명에 넣을 수 있습니다.
 
Andy :
예, 아마도. 또한 표준 라이브러리 의 MA에서 열거형을 가져와서 즉시 해당 신호 모듈의 설명에 넣을 수 있습니다.

사용자 정의 열거형이 제공되지 않았음을 의미합니다.

 
예, 하지만 MA에서 기본 제공 열거형이 있습니다!
 
Andy :
예, 하지만 MA에서 기본 제공 열거형이 있습니다!