prev_calculated - страница 6

 
Просто не надо колоть утюги орехами.
 
Alexey Viktorov:
Этого в документации НЕТУ!!! Следовательно это сочинения на вольную тему. Равно как и моё заявление об автоматической инициализации, даже круче. Моё хоть с оговоркой было...

Абсолютно всё описать в документации невозможно.

Получили "prev_calculate==0" - значит нужно пройтись по всему индикаторному буферу. Если "prev_calculate!=0" значит в этом случае считаем только или самый правый бар или несколько новых (используем limit):

                const int &spread[])
  {
//---
   if(prev_calculated==0)
     {
      Print("prev_calculated==0");
            for(int i=0;i<rates_total;i++)
              {
               //--- здесь принудительно каждому элементу массива присваиваем значение (мне лень писать эти массивы :) )
      
              }
      return(rates_total);
     }
//--- экономный пересчёт только самого правого бара или новых баров
   int limit=rates_total-prev_calculated+1;

//--- а ниже нужно использовать цикл для обсчета самого правого бара или новых баров
   for(int i=0;i<limit;i++)
     {
      ExtBuffer[i]=чевой-то там;
     }




 

 
Karputov Vladimir:

Абсолютно всё описать в документации невозможно.

Получили "prev_calculate==0" - значит нужно пройтись по всему индикаторному буферу. Если "prev_calculate!=0" значит в этом случае считаем только или самый правый бар или несколько новых (используем limit):

                const int &spread[])
  {
//---
   if(prev_calculated==0)
     {
      Print("prev_calculated==0");
            for(int i=0;i<rates_total;i++)
              {
               //--- здесь принудительно каждому элементу массива присваиваем значение (мне лень писать эти массивы :) )
      
              }
      return(rates_total);
     }
//--- экономный пересчёт только самого правого бара или новых баров
   int limit=rates_total-prev_calculated+1;

//--- а ниже нужно использовать цикл для обсчета самого правого бара или новых баров
   for(int i=0;i<limit;i++)
     {
      ExtBuffer[i]=чевой-то там;
     }




 

Какое значение??? Мне не нужны никакие значения кроме самого правого бара. НО!!! Потом когда этот самый правый смещается влево эти засунутые туда данные надо сохранить...

Не обязательно писать все буферы, а один можно было и написать с учётом моих пожеланий. Если это первый запуск - вся история должна быть пустой. Если-же обнуление prev_calculated произошло в следствии подкачки истории то ВСЁ что было в буфер засунуто должно остаться в неизменном виде. Пусть даже появятся дыры.

 
Karputov Vladimir:

Предварительные выводы:

1. В индикаторах нельзя полагаться на инициализация индикаторных массивов в OnInit():

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
...
   ArrayInitialize(balance, 0.0);    // принудительная
   ArrayInitialize(equityMax, 0.0);  // инициализация
   ArrayInitialize(equityMaxB, 0.0); // всех
   ArrayInitialize(equityMin, 0.0);  // буферов
   ArrayInitialize(equityMinB, 0.0); // индикатора

...
//---
   return(INIT_SUCCEEDED);
  }

2. В индикаторах обязательно нужно проходить по всему массиву или только по изменённым элементам в OnCalculate(). 

Чё ахинею нести? Если такую инициализацию засунуть в OnCalculate то обнуляется на ура без каких либо циклов. Но если обнуляется prev_calculated то обнуляет все данные которые были накоплены в процессе работы...
 
Alexey Viktorov:
Чё ахинею нести? Если такую инициализацию засунуть в OnCalculate то обнуляется на ура без каких либо циклов. Но если обнуляется prev_calculated то обнуляет все данные которые были накоплены в процессе работы...
Выражениями выбирайте, пожалуйста. И изучите примеры индикаторов из стандартной поставки: каталог данных\MQL5\Indicators\Examples\
 
Alexey Viktorov:

Какое значение??? Мне не нужны никакие значения кроме самого правого бара. НО!!! Потом когда этот самый правый смещается влево эти засунутые туда данные надо сохранить...

...

Я уже предлагал способ:

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

prev_calculated

Karputov Vladimir, 2016.10.18 15:11

Извините за задержку с ответом. Единственный вариант сохранения рассчитанных значений для данного таймфрейма - это сохранять в файл. При этом нужно озаботиться синхронизацией - чтобы при чтении из файла данные разместились по своим барам. Самое логичное - это синхронизация по времени открытия бара, но здесь могут быть нюансы: например время открытия бара (сохранённое в файл) было 2016.09.05. 25:02, а теперь на графике есть бар у которого время равно 2016.09.05. 25:01.

Индикатор - это не база данных и не хранилище. 

Поэтому если индикатор отображает данные которые потом не могут быть рассчитаны на истории, то остаётся только сохранять индикаторный буфер в файл, а потом (в случае подкачки истории) проводить чтение и синхронизировать файл и бары.
 
Karputov Vladimir:

Я уже предлагал способ:

 

Индикатор - это не база данных и не хранилище. 

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

Alexey Viktorov:

... и желательно без записи в файл или тем более в GV.

prev_calculated
prev_calculated
  • www.mql5.com
Форум трейдеров MQL5.community
 

Владимир, раз вы выделили этот топик спецом под prev_calculated, сделайте его полезным именно по этой теме. Во-первых, надо обозначить проблему в которую обычно упираются с этой переменной. Если вам эти проблемы не знакомы, я сформулирую

---

а - хоть в справке и написано

prev_calculated  // обработано баров на предыдущем вызове

использовать её именно для этого нельзя - в любой момент может показать фигу. Причина в том (написано в справке + сказано разработчиками), что переменная обнуляется при изменении контрольной суммы, обычно - из-за подкачки истории

---

б - использовать prev_calculated == 0 в кач-ве флага первого запуска OnCalculate тоже нельзя. По той же причине

---

в - и как флаг подкачки истории prev_calculated == 0 тоже использовать нельзя

---

Чтобы уменьшить износ граблей пользователями, сформулировать желательно кратко и однозначно: если подкачки истории не случилось на текущем вызове OnCalculate, то prev_calculated содержит кол-во баров обработанных на предыдущем. Если случилось - она обнуляется

---

Все 3 перечисленных затыка можно обойти с помощью костылей. Но раз в MT5 костылей быть не может по определению, вы бы, Владимир, сочинили бы красивое решение для этих 3х задач. Некрасивое примерно такое:

#property indicator_chart_window
#property indicator_buffers  0
#property indicator_plots    0


struct BROWNIE {
  int   i_Prew_Calculated;  // кол-во посчитанных баров
  bool  b_First_Run;        // флаг первого запуска
  bool  b_History_Updated;  // флаг обновления истории
  
  BROWNIE() {
    i_Prew_Calculated = WRONG_VALUE;
    b_First_Run = true;
    b_History_Updated = false;
  }
  
  void f_Reset(bool b_Reset_First_Run = true) {
    i_Prew_Calculated = WRONG_VALUE;
    if(b_Reset_First_Run) b_First_Run = true;
    b_History_Updated = false;
  }
  
  void f_Update(int i_New_Prew_Calculated = WRONG_VALUE) {
    if(i_New_Prew_Calculated > -1) {
      b_History_Updated = i_New_Prew_Calculated == 0 && i_Prew_Calculated > WRONG_VALUE;
      if(b_First_Run) b_First_Run = false;
      
      if(i_Prew_Calculated == WRONG_VALUE) i_Prew_Calculated = i_New_Prew_Calculated;
      else if(i_New_Prew_Calculated > 0) i_Prew_Calculated = i_New_Prew_Calculated;
    }
  }
};
BROWNIE go_Brownie;


int OnInit(void) {return(INIT_SUCCEEDED);}


void OnDeinit(const int reason) {
  go_Brownie.f_Reset(reason != REASON_CHARTCHANGE);
}



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 &TickVolume[],
    const long &Volume[],
    const int &Spread[]
) {
  if(go_Brownie.b_First_Run) {/* обработка 1го запуска */}
  if(go_Brownie.b_History_Updated) {/* обработка обновления истории */}
  go_Brownie.f_Update(prev_calculated);
  
  return(rates_total);
}

Disclaimer: код - голая идея, на графике не гонял

В OnDeinit прописан образец - обработка для индикатора, который буферов не использует, ему пофиг на ТФ и символ, при каждой смене ТФ/символа начинать всё с нуля не нужно. Напр, работает с существующими граф.элементами, выводит инфу о состоянии счёта, ордерах и тд

---

Кстати

Karputov Vladimir:

то остаётся только сохранять индикаторный буфер в файл, а потом (в случае подкачки истории) проводить чтение и синхронизировать файл и бары.

Винт терзать не обязательно, можно сохранять в граф.элементах на чарте
 
Alexey Viktorov:
... и желательно без записи в файл или тем более в GV.
Может Вам это подойдет?
 
Konstantin Gruzdev:
Может Вам это подойдет?

В подробности не вникал, но такое решается оной строкой кода. Копирование массива самого в себя со сдвигом индекса.

double arr[5];
ArrayCopy(arr, arr, 0, 1, 4);
// и дальнейшее заполнение 4го индекса массива.
Можно перевернуть и копировать с нулевого а вставлять с первого. Тогда заполняется нулевой индекс массива. И это совсем из другой оперы...)))
Причина обращения: