refurbished bars??

 

Hi,

I re-wrote an indicator to make it faster. It calculates in principle EMA( EMA (Volume[i]) ) in two buffers of the Indicator and does s.th with it. So practically I do not need the intermediate EMAs to be stored and shown.

Well instead of having the EMAs in buffers with iMAOnArray() for the next value, which (I guess) have to be shifted and recalculated each new bar I tried:

int start() {
    static datetime newBar=-1;
    int i,counted_bars=IndicatorCounted();
    //---- check for possible errors
    if(counted_bars<0) return(-1);
    //---- last counted bar will be recounted
    if(counted_bars>0) counted_bars--;
    int limit=Bars-counted_bars;
    //----
    i=limit;
    if ( newBar != Time[0] ) {
        if (newBar < 0) {
            // do the ini stuff
        }// ini stuff
        newBar = Time[0];
        ema1prv = Volume[i]; // global (or static?) defined
        ema2prv = ema1;       // global (or static?) defined
        while(i>2) { // calc the history: [Bars]..[2]
           ema1 = constEma1*(Volume[i]-ema1prv) + ema1prv;  // cEma1=2.0/(PerEma1+1.0)   
           ema2 = constEma2*(ema1-ema2prv) + ema2prv;        // cEma2=2.0/(PerEma2+1.0) 
           IndBuff[i] = calcIndi(ema2prv);
        }//while
        // Now calc the [1]-bar
        i = 1; // safty and easier for copy and paste
        ema1prv = constEma1*(Volume[i]-ema1prv) + ema1prv;  // cEma1=2.0/(PerEma1+1.0)   
        ema2prv = constEma2*(ema1prv-ema2prv) + ema2prv;     // cEma2=2.0/(PerEma2+1.0) 
        IndBuff[i] = calcIndi(ema2prv);
    }// newBar
    // Now calc the [1]-bar
    i = 0; // safty and easier for copy and paste
    ema1act = constEma1*(Volume[i]-ema1prv) + ema1prv;  // cEma1=2.0/(PerEma1+1.0)   
    ema2act = constEma2*(ema1act-ema2prv) + ema2prv;     // cEma2=2.0/(PerEma2+1.0) 
    IndBuff[i] = calcIndi(ema2act);
}

Now yesterday right before the market closed I experienced that the ema-values of my indicatos created some ridiculous values, which disappeared at once as soon as I let the Indicator re-calcultate the whole history.

I installed two different Indicators of this kind at a 1min-Bar-chart EURUSD at about Friday noon and both worked perfectly the whole day until Friday 22:09 when the quotes suddenly jump from 1.29857 to 1.30066. The IndBuff raises  in a way I cannot understand.

There were other 'jumps' (1.2946 .. 1.30033) where it behaves as expected..

I have realized that most of the time IndicatorCounted() returns 3 which means that not the previous bar but the last two bars (and [0]) has been changed by the Broker - is that correct?

So my questions:

   Is it a good idea to replace several indi.Buffers (if you can do that) in the above shown way: no Buffer but global variables to skip a lot recalculations?
   If not - why?
(Please not: why do you do it if you see it does not work - why doesn't it work, as a first step to a better solution!)

Thanks in davance,
Gooly

 
gooly: I re-wrote an indicator to make it faster. It calculates in principle EMA( EMA (Volume[i]) ) in two buffers of the Indicator and does s.th with it. So practically I do not need the intermediate EMAs to be stored and shown.

  1. Play video
    Please edit your post.
    For large amounts of code, attach it.

  2. while(i>2) { // calc the history: [Bars]..[2]
    I is never decremented.
  3. You don't recalculate anything, Indicator counted goes to zero but your code keys off of Time[0]. Drop your Time[0] completely and only use limit/i
  4. No need for the decrement Contradictory information on IndicatorCounted() - MQL4 forum
  5. Is it a good idea to replace several indi.Buffers
    I re-wrote an indicator to make it faster
    You didn't make it faster, no it is not a good idea. Your code break when you loose connection and on reconnection, several bars occur.
 

WHRoeder:



  1. I is never decremented.
  2. Sie müssen nicht neu berechnen nichts geht Indicator gezählt, um Null, aber der Code-Schlüssel aus der Zeit [0]. Lassen Sie Ihre Zeit [0] vollständig und nur limit / i
  3. No need for the decrement Contradictory information on IndicatorCounted() - MQL4 forum
  4. Is it a good idea to replace several indi.Buffers
    I re-wrote an indicator to make it faster
    You didn't make it faster, no it is not a good idea. Your code break when you loose connection and on reconnection, several bars occur.

add 1) I (think I) used SRC and I see int and two ifs were 'blued' ?? Could be that part of the code I wrote within that box.

add 2) yes, sorry my fault.

add 4 ) it takes some tome to read it..

add 5) that's the point! I haven't thought of it - OK!


one add. question, if I write an EA the function IndicatorCounted() will give the same results as if been called in an indicator?

Thanks Gooly

 
You can  NOT  call IndicatorCounted() in a EA. I use this pattern for EAs:
int init(){ OnInitRCS(); ... }
int start(){ .. ComputeRCS(); ... }
:
datetime rcsAnalyzed;                     void OnInitRCS(){ rcsAnalyzed = 0;  }
void     ComputeRCS(){
for(int iBar = iBarShift(NULL,0, rcsAnalyzed); iBar >= 0; iBar--){  ... }
rcsAnalyzed = Time[0];

Remember buffers do NOT auto-resize in EAs

See Also Transferring an Indicator Code into an Expert Advisor - Articles - MQL4

 

Tanks a lot, WHRoeder, that really helps!

one more question:
     Am I right assuming, that arrays set as series are automatically 'shifted' - the oldest bar is dropped and the previous bar[0] becomes bar[1] and an new empty bar[0] is created -
             or do I have to shift all values of this array my self one bar up?

I haven't found any hint on that. The code of various articles just don't show the shift been coded.

Thanks Gooly

 
gooly:

Tanks a lot, WHRoeder, that really helps!

one more question:
     Am I right assuming, that arrays set as series are automatically 'shifted' - the oldest bar is dropped and the previous bar[0] becomes bar[1] and an new empty bar[0] is created -
             or do I have to shift all values of this array my self one bar up?

It's in the article that WHRoeder   gave a link to, ( Emulation of Indicator Buffers in an Expert Advisor )   -  you have to do all the shifting yourself. 
 
  1. What part of
    Remember buffers do NOT auto-resize in EAs
    was not clear?
  2. If you're going that route, see my resizeBuffer code.
 
WHRoeder:
  1. What part of
    Remember buffers do NOT auto-resize in EAs
    was not clear

1) The arrays of an INDICATOR I defined by ArraySetAsSeries(arr) do auto-shift or auto-resize?

2) In this code-example you mentioned https://www.mql5.com/en/articles/1456  arrays are resized and completely rewritten and calculated if the amount of bars becomes bigger than the array-size.

But - in my understanding - an new bar[0] does not mean automatically that the number of bars of the chart (=Bars) has to increase as well.
The oldest bar(s) can be dropped, or is the amount of bars of the chart rising until the chart is .. (crashing)?

Later in that code-example the arrays are initialized with 0.0 but there is no shift.
On the otherhand I can't believe that all the arrays with the size of Bars which is around 68'000 (on my m1-chart) are completely re-calculated every new bar.

Isn't that a fairly stupid way of wast of cpu-time? One of my indicator needs 10 series-arrays. Applied on a m1-chart it has almost 700'000 calculations.

Imagine this on several currency-chart, and they all will come up at the very same moment.

Thanks, Gooly

 
  1. Only indicator buffers are resized, auto-shifted and initialized (EmptyValue) All other arrays, you have to handle yourself. I gave you a link to my resize/shift function.
  2. On the otherhand I can't believe that all the arrays with the size of Bars which is around 68'000 (on my m1-chart) are completely re-calculated every new bar.
    Have you looked at using indicatorCounted() Did you read the link on not decrementing it? Had you you would not have said that. You would know that normally a properly coded indicator only recalculates bar zero.
 

Well RHRoeder,

I was/am expecting at new-bar-formed a shift of all indi-bars to the now correct position, so s.th. like:

extern int BarsBack; // increase to see more..
// ...
double indi[];
int start() {
        static datetime tLastCalcBar=0;
        int iBarToCalc;

   int i,b,counted_bars=IndicatorCounted();
//---- check for possible errors
   if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   int limit=Bars-counted_bars-1;


        // ini the array(s)
        if(ArraySize(indi) < BarsBack) {
                ArraySetAsSeries(indi,  false);
                if ( BarsBack+1 < Bars-1 ) i = BarsBack+1;
                else Alert("..."); 
                ArrayResize(indi,  i); 
                ArraySetAsSeries(indi,  true);
                i--;
        } else i = MathMin(limit,BarsBack);

        if ( tLastCalcBar != Time[0] ) { // calBr[0] 
                iBarToCalc = MathMin(i, iBarShift(NULL, 0, tLastCalcBar) );
                tLastCalcBar = Time[0];
                for( b=tLastCalcBar;b>0;b--){ // 
                        for(i=BarsBack;i>iBarToCalc;i--){ // shift all the bars down to bar[1]
                                indi[i]  = indi[i-iBarToCalc];
                        }
                        // no calc bars Bar[iBarToCalc] - Bar[1] ...
                        indi[b] = whatever( indi[b+1], indi,[b+2]); // new
                } 
        }       
        // calc. Bar[0]
        indi[0] = func(indi[1],Ask,Bid);
        return(0);
}

I never saw this:

indi[i]  = indi[i-iBarToCalc];

where all bars that remain are shifted, so that the previous last formed bar ( normally bar[1]) now becomes (normally) bar[2] and the bar[1] is newly calculated and bar[0] is ready for every new tick.

Is there a mistake in my expectations or a more simply way to do that?

Gooly

 
for(i=BarsBack;i>iBarToCalc;i--){ // shift all the bars down to bar[1]
 indi[i]  = indi[i-iBarToCalc];
}

How many times do you need to be told.

  1. You have to resize non-buffer arrays
  2. You have to move the elements
  3. Did you bother to look at my resizeBuffer that does both? Obviously not!
  4. Decrement unnecessary. Did you bother to look at the link? Obviously not!
double indi[];
int start(){
   ResizeBuffer(indi, Bars); // No shifting inside a loop necessary.
   for(int i=Bars - 1 - indicatorCounted(); i>=0; i--){
      indi[i] = func(indi[i+1],Ask,Bid);  // fill in your buffers. 
 }  }
///////////////////////////////////////////////////////////////////////////////
bool     ResizeBuffer(double& buffer[], int size){ // buffer can be 1D or 2D
   if(ArrayRange(buffer,0) != size){      // ArrayRange allows 1D or 2D arrays
      ArraySetAsSeries(buffer, false);    // Shift values B[2]=B[1]; B[1]=B[0]
      if(ArrayResize(buffer, size) <= 0){ DisableTrading(
         "ArrayResize("+size+") failed: " + GetLastError() );  return(false); }
      ArraySetAsSeries(buffer, true);
   }
   return(true);
}
Reason: