prev_calculated - page 6

 
Just don't stab the irons in the nuts.
 
Alexey Viktorov:
This is NOT in the documentation! Consequently, this is an essay on a free subject. Just like my statement about automatic initialization, even cooler. At least mine had a disclaimer...

It is impossible to describe absolutely everything in the documentation.

If "prev_calculate==0" - it means that we have to go through the whole indicator buffer. If "prev_calculate!=0", then only the rightmost bar or several new ones will be calculated (we use 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:

It is impossible to describe absolutely everything in the documentation.

If "prev_calculate==0" - it means that we have to go through the whole indicator buffer. If "prev_calculate!=0", then only the rightmost bar or several new ones will be calculated (we use 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]=чевой-то там;
     }




What is the value? I don't need any values except for the rightmost bar. BUT!!! Then when this rightmost one shifts to the left this data must be saved...

You don't have to write all the buffers, but you could write one with my wishes in mind. If it is the first run, all history should be empty. If prev_calculated was reset as a result of history swapping, ALL that was put into buffer should remain unchanged. Even if there are holes.

 
Karputov Vladimir:

Preliminary conclusions:

1. Indicators cannot rely on initialization of indicator arrays in 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. In indicators it is obligatory to pass through the whole array or only changed elements in OnCalculate().

What are you talking nonsense about? If this initialization is implemented in OnCalculate, it will be initialized without any loops. But if prev_calculated, it clears all data which were accumulated during work...
 
Alexey Viktorov:
Why are you talking nonsense? If this initialization is put into OnCalculate, it is zeroed without any cycles. But if we zeroize prev_calculated, it clears all the data that have been accumulated during the operation...
Please use expressions. And look at examples of indicators from standard delivery: Data Catalogue\MQL5\Indicators\Examples\.
 
Alexey Viktorov:

What's the value??? I don't need any value other than the rightmost bar. BUT!!! Then when this rightmost one shifts to the left, that data needs to be saved...

...

I've already suggested a way:

Forum on trading, automated trading systems and testing of trading strategies

prev_calculated

Karputov Vladimir, 2016.10.18 15:11

Sorry for the delay in replying. The only way to save the calculated values for a given timeframe is to save them to a file. You need to take care of the synchronisation - so that when reading from the file the data are placed on their bars. The most logical way is to synchronize it with the bar open time, but there may be some nuances: for example, the bar open time (saved to a file) was 2016.09.05. 25:02, but now there is a bar on the chart with time equal to 2016.09.05. 25:01.

An indicator is not a database or a repository.

Therefore, if the indicator displays data that then cannot be calculated on the history, then it is only necessary to save the indicator buffer to a file, and then (in case of history swapping) to read and synchronize the file and bars.
 
Karputov Vladimir:

I've already suggested a way:

An indicator is not a database or a repository.

Therefore, if the indicator shows the data, which then can't be calculated on the history, then we have only to save the indicator buffer in a file, and then (in the case of history paging) perform the reading and synchronize the file and the bars.

Alexey Viktorov:

... and preferably without writing to a file or even more so to GV.

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

Vladimir, since you dedicated this topic specifically to prev_calculated, make it useful on this topic. First of all, you should specify the problem that usually occurs with this variable. If you are not familiar with these problems, I will formulate

---

a-- even though it says in the help

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

The reason is (it is written in help + told by developers) that the variable gets reset to zero when the checksum changes, usually because of history swap.

---

b - you can't use prev_calculated == 0 as a flag of first run onCalculate either. For the same reason

---

c - and you can't use prev_calculated == 0 as a history paging flag either

---

To reduce the wear and tear on users, the wording should be brief and unambiguous: if history paging has not happened at the current call of OnCalculate, prev_calculated contains the number of bars processed at the previous call. If it happened - it is reset to zero

---

All 3 mentioned problems can be solved with crutches. However, since MT5 cannot have crutches by definition, Vladimir, could you create an attractive solution for these three problems? An ugly one is something like this:

#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: Code - just an idea, I didn't try it on a chart.

In OnDeinit there is a sample - processing for the indicator that doesn't use buffers, it doesn't care about TF and symbol, at each change of TF/symbol there is no need to start from scratch. For example, it works with existing graphical elements, outputs information about account status, orders, etc.

---

By the way

Karputov Vladimir:

If this option is enabled, it is only necessary to save the indicator buffer to a file and then (in case of history loading) read and synchronize the file and bars.

You don't have to destroy the disk, you can save it to a chart item
 
Alexey Viktorov:
... and preferably without writing to a file or even more so to a GV.
Would that work for you?
 
Konstantin Gruzdev:
Maybe this will suit you?

I didn't get into details, but this is solved by this line of code. Copying an array into itself with an index shift.

double arr[5];
ArrayCopy(arr, arr, 0, 1, 4);
// и дальнейшее заполнение 4го индекса массива.
You may reverse it and copy from the zero index and paste from the first one. Then the zero index of the array will be filled in. And this is quite a different thing...))
Reason: