MT4 iMAOnArray и iBandsOnArray влияние количества элементов на расчёты - страница 2

 
Sergey Efimenko:
В смысле что ожидаю? Я же написал выше, что мне нужны 300 последних (текущих) актуальных значений, а не 300 первых (начальных), при том, что я обращаюсь к массиву по смещению 299-0, а получаю данные по смещению от "конца массива" до "конца массива - 300" значений (в моём случае от 4999 до 4700), то есть по смещению 299 находится значение которое должно находиться по смещению 4999 и аналогично по смещению 0 находится значение, которое должно находится по смещению 4700. Актуально при сокращении количества расчёта массивов получать не начальные исторические данные, а текущие, спрашивается с какой целью идёт расчёт самых старых значений при том, что расчёт текущих не производится?

Если-бы из того что ты написал было понятно, то и вопросов не возникало-бы.

double  iMAOnArray(
   double       array[],          // массив               // С этим понятно...
   int          total,            // количество элементов // Это у тебя 300
   int          ma_period,        // период               // Это ???
   int          ma_shift,         // сдвиг средней        // понятно
   int          ma_method,        // метод усреднения     // понятно
   int          shift             // сдвиг                // А здесь чему равна i???
   );

Тебя просили показать пример кода, а ты показал только кусок примера. Об остальном можно только догадаться что всё это в цикле. При каком значении i ты хочешь получить последние, текущие значения??? При i = 4700 или где?

 
Alexey Viktorov:

Если-бы из того что ты написал было понятно, то и вопросов не возникало-бы.

Тебя просили показать пример кода, а ты показал только кусок примера. Об остальном можно только догадаться что всё это в цикле. При каком значении i ты хочешь получить последние, текущие значения??? При i = 4700 или где?

Если вы пользовались указанными функциями с ограничением длины расчётного массива на практике, то поймёте о чём речь, иначе какой смысл теоретических рассуждений?.. Да и что непонятного в моём куске кода? Я привёл абсолютно идентичные участки с той лишь разницей, что в первом случае я не использую ограничение длины на расчёт массива. В данном случае абсолютно не важно какой период расчёта, сдвиг средней или метод усреднения, т.к. в обоих случаях они одинаковы? Значение сдвиг, как я написал выше, аналогично используется абсолютно одинаковое. Забейте указанные строки в любой индикатор, который сделан нормально и считает только новые бары, замените "i" на вашу переменную смещения в цикле, замените функцию GetValue(i) хотя бы на Open[i], сделайте три указанных массива 3 отображаемыми буферами индикатора и посмотрите как отработает первый вариант и второй. Впрочем вот пример полного кода самого простого варианта индикатора в двух вариантах для упрощения понимания сути проблемы:

//так работает нормально: 
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 clrYellow
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
double Buffer[],BufferMA[],BufferBMA[]; bool firstrun=true;
int init() { firstrun=true; SetIndexBuffer(0,Buffer); SetIndexBuffer(1,BufferMA); SetIndexBuffer(2,BufferBMA); return(0); }
int start() { int i,limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars-1;
   if(firstrun) {ArrayInitialize(Buffer,Open[Bars-1]); ArrayInitialize(BufferMA,Open[Bars-1]); ArrayInitialize(BufferBMA,Open[Bars-1]); firstrun=false; }
   for(i=limit; i>=0; i--) { Buffer[i]=Open[i]; BufferMA[i]=iMAOnArray(Buffer,0,12,0,0,i); BufferBMA[i]=iBandsOnArray(Buffer,0,12,2,0,MODE_MAIN,i); }
return(0); }

//так не работает нормально:

#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 clrYellow
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
double Buffer[],BufferMA[],BufferBMA[]; bool firstrun=true;
int init() { firstrun=true; SetIndexBuffer(0,Buffer); SetIndexBuffer(1,BufferMA); SetIndexBuffer(2,BufferBMA); return(0); }
int start() { int i,limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars-1;
   if(firstrun) {ArrayInitialize(Buffer,Open[Bars-1]); ArrayInitialize(BufferMA,Open[Bars-1]); ArrayInitialize(BufferBMA,Open[Bars-1]); firstrun=false; }
   for(i=limit; i>=0; i--) { Buffer[i]=Open[i]; BufferMA[i]=iMAOnArray(Buffer,300,12,0,0,i); BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);  }
return(0); }

После нанесения индикаторов на график идите в начало (влево) графика и посмотрите на 1 индикатор от 12 бара и далее, именно с него начинается "непустое" заполнение 2 и 3 массива, примерно запомните несколько первых значений, отличных от 0, далее переместите график к текущим котировкам и посмотрите значения начиная от 300 бара, так вот значения 2 (нижнего) индикатора будут равны тем, которые вы видели в начале графика у 1 индикатора, а по идее значения должны совпадать с текущими. Надеюсь понятно пояснил. Кроме того, если нанести графики на он-лайн чарт, то первый будет отрабатывать нормально, а второй "зависнет при своих".

 
Sergey Efimenko:


Мало того, что код без стилизации, так ещё и вставляете код в виде простого текста. Пожалуйста, вставляйте код правильно.
 

Представлю Ваш код в более удобочитаемом виде и в новой нотации (и вправду, сколько уже можно пользоваться в индикаторах этим анахронизмом int start()???):

Индикатор 1:

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 clrYellow
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,INDICATOR_DATA);
//---
   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;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,0,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,0,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Индикатор 2:

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 clrYellow
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,INDICATOR_DATA);
//---
   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;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,300,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

 

И результат выполнения:

Результат

о 

Файлы:
Test.mq4  3 kb
Test300.mq4  3 kb
 
Sergey Efimenko:

Если вы пользовались указанными функциями

Если-бы не пользовался не задавал-бы вопросов с целью натолкнуть на правильное решение.

Какой смысл брать 300 баров если расчёт нужен периодом 12??? Даже если надо именно так, "потомучто" то надо понимать какие 12 элементов будут в расчёте среднего значения. И очень правильная была подсказка о направлении индексации массива.

Для понимания поделай эксперименты с подсчётом вручную на бумаге или на калькуляторе, ну или в Excel`e.

 

Вот смотрю я на ответы и понимаю, что я тут просто теряю время, пытаясь показать суть проблемы, а получая в ответ "красоту" кода (спасибо конечно, но предлагаемый код написан за пару минут только для отображения сути проблемы и ну никак не требует удобочитаемости или прочих преобразований)...

А особо порадовал ответ перед моим постом... Какой калькулятор, какие ручные расчёты, какая индексация? Уважаемые пользователи, вникайте пожалуйста в суть ситуации, чтобы не тратить зря не только своё время, но и чужое. Перечитайте внимательнее мои разжеванные посты, но если сложно, отвечу кратко: направление индексации массива в обоих случаях правильное, размер необходимых расчётов и остальные изменяемые параметры, как это показано в первичном коде задаётся внешними переменными, вариант создания своей функции обсуждался выше (и по сути является единственным верным решением), но, повторюсь, хотелось бы получить это от встроенных в МТ4.

В общем всем спасибо, подведу итоги: или сервисдеск или свои аналоги функций.

 

А меня удручает ответ перед моим постом...

Ну если ты на столько упрям, => в сервисдеск, а там на такие вопросы отвечают исключительно от скуки, а скучают они редко.

Ну попробую ещё раз...

iMAOnArray() берёт, в твоём случае 300 баров и высчитывает среднее значение последних 12-ти баров из трёхсот. Чтобы получить среднее первых 12-ти баров нужно перевернуть индексацию массива, ArraySetAsSeries(BufferMA, false); или взять всего 12 баров.

BufferMA[i]=iMAOnArray(Buffer,12,12,0,MODE_SMA,i);

Вот и получается, что вместо того чтобы вникнуть, понять как работает, как пользоваться, ты просто заявляешь что не работает или работает не правильно. А неправильно это не по-твоему...

Дальше про красоту кода: Ты думаешь кому-то интересно ломать глаза читая твой код, когда всё написано в одну строку??? Ошибаешься. Я лично не читал. Спасибо барабашке за его терпение по несколько раз в день направлять всех ... не туда куда послал-бы я.

 

Хотел ответить очень "подробно", но потом перечитав посты ещё раз, удалил свой ответ, и окончательно понял, что только теряю тут время, объясняя несколько раз одно и тоже разными словами...

PS Всем спасибо и действительное спасибо "Барабашке" (Владимиру), он молодец, но вся эта ситуация не стоила его труда, буду ему ещё более благодарен, если его не затруднит сделать, скрин в ключе предыдущего, добавив третий вариант и показав, что будет если последовать совету со сменой направления индексации. Дабы поставить точку в вопросе работы функции.

 
Sergey Efimenko:

Хотел ответить очень "подробно", но потом перечитав посты ещё раз, удалил свой ответ, и окончательно понял, что только теряю тут время, объясняя несколько раз одно и тоже разными словами...

PS Всем спасибо и действительное спасибо "Барабашке" (Владимиру), он молодец, но вся эта ситуация не стоила его труда, буду ему ещё более благодарен, если его не затруднит сделать, скрин в ключе предыдущего, добавив третий вариант и показав, что будет если последовать совету со сменой направления индексации. Дабы поставить точку в вопросе работы функции.

Вариант 3:

//+------------------------------------------------------------------+
//|                                         Test300AsSeriesFalse.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 clrYellow
#property indicator_color2 clrGreen
#property indicator_color3 clrRed
double Buffer[];
double BufferMA[];
double BufferBMA[];
bool firstrun=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   firstrun=true;
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   SetIndexBuffer(1,BufferMA,INDICATOR_DATA);
   SetIndexBuffer(2,BufferBMA,INDICATOR_DATA);
//---
   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,false);
//---
   int i,limit;
   limit=rates_total-prev_calculated-1;
   if(prev_calculated==0)
     {
      ArrayInitialize(Buffer,open[rates_total-1]);
      ArrayInitialize(BufferMA,open[rates_total-1]);
      ArrayInitialize(BufferBMA,open[rates_total-1]);
     }
   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,300,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,300,12,2,0,MODE_MAIN,i);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

И общий результат: 

Варианты 1, 2 и 3

Файлы:
 

Нет, Владимир. Чуток не так.

В этом случае надо ArraySetAsSeries(массив, false); применять к массиву из трёхсот элементов среди которых считается iMAOnArray(). Но для этого лучше использовать CopyOpen() а не цикл заполнения массива.

Как я понимаю, в этом варианте лучше будет

   for(i=limit; i>=0; i--)
     {
      Buffer[i]=open[i];
      BufferMA[i]=iMAOnArray(Buffer,12,12,0,MODE_SMA,i);
      BufferBMA[i]=iBandsOnArray(Buffer,12,12,2,0,MODE_MAIN,i);
     }
Причина обращения: