How to keep previous buffer if condition is not met??

 

Hi everyone, I would like an indicator buffer to be equal to it's previous value if a condition is not met. 

For example, I have PipsLenght = 0.001 (10pips) 

   int limit;
   limit=rates_total-prev_calculated;
   if(prev_calculated>0)
      limit++;
   
    for(int i=limit-1; i>=0; i--)
    {
     
      double middle;
      
      if(iHigh(Symbol(),1,i)>B_UHighLine[i+1]) middle=iHigh(Symbol(),1,i)-PipsLenght/2;
      
      if(iLow(Symbol(),1,i)<B_UHighLine[i+1]) middle=iLow(Symbol(),1,i)+PipsLenght/2;
      
      B_UHighLine[i]=middle;
      
     

As you can see: 

1) The first middle value (when the calculation begins at the extreme left of the chart) should be current high - PipsLenght/2... In other words, current high minus 10 pips. 

2) If the current high is not greater than previous middle value + 10pips, or if the current low is not lower than previous middle value - 10 pips, then actual middle value should be equal to previous middle value. 

3) If current high is greater than previous middle value + 10pips then current middle value should be equal to current high - 10 pips. If current low is lower than previous middle value - 21pips then current middle value should be equal to current low + 10 pips. 

As you can see I've tried several things, in the code I posted my last try but unfortunately no success. I'm still learning, so if you please can point me what I'm doing wrong I would appreciate and hopefully learn something new. 


Thanks. 

Averaging Price Series for Intermediate Calculations Without Using Additional Buffers
Averaging Price Series for Intermediate Calculations Without Using Additional Buffers
  • www.mql5.com
This article is about traditional and unusual algorithms of averaging packed in simplest and single-type classes. They are intended for universal usage in almost all developments of indicators. I hope that the suggested classes will be a good alternative to 'bulky' calls of custom and technical indicators.
 
  1. ironhak: I would like an indicator buffer to be equal to it's previous value if a condition is not met. 
    for(…){
       buffer[i]=buffer[i+1];
       if(condition) buffer[i]=newValue;
  2. if(iHigh(Symbol(),1,i)>B_UHighLine[i+1])

    Handle look back of one
              How to do your lookbacks correctly #9#14 & #19

 
William Roeder #:
  1. Handle look back of one
              How to do your lookbacks correctly #9#14 & #19

Hi, thank's for replying. I've did what you suggest but nothing plot on the chart: 

   for(int i=limit-1; i>=0; i--)
    {      
      B_UHighLine[i]=B_UHighLine[i+1];
      
      
      if(iHigh(Symbol(),1,i)>B_UHighLine[i+1]+0.001) B_UHighLine[i]=iHigh(Symbol(),1,i)-0.001;
      
      if(iLow(Symbol(),1,i)<B_UHighLine[i+1]-0.001) B_UHighLine[i]=iLow(Symbol(),1,i)+0.001;
    }

Any further suggestion on why this does not work? Thank's. 

 
ironhak:

Hi everyone, I would like an indicator buffer to be equal to it's previous value if a condition is not met. 

For example, I have PipsLenght = 0.001 (10pips) 

As you can see: 

1) The first middle value (when the calculation begins at the extreme left of the chart) should be current high - PipsLenght/2... In other words, current high minus 10 pips. 

2) If the current high is not greater than previous middle value + 10pips, or if the current low is not lower than previous middle value - 10 pips, then actual middle value should be equal to previous middle value. 

3) If current high is greater than previous middle value + 10pips then current middle value should be equal to current high - 10 pips. If current low is lower than previous middle value - 21pips then current middle value should be equal to current low + 10 pips. 

As you can see I've tried several things, in the code I posted my last try but unfortunately no success. I'm still learning, so if you please can point me what I'm doing wrong I would appreciate and hopefully learn something new. 


Thanks. 

What's wrong?

U can't code the condition, get the previous buffer value... 
Where is the else if in your code?
 
_MAHA_ #:
What's wrong?

U can't code the condition, get the previous buffer value... 
Where is the else if in your code?

Hi, thanks for reply. I didn’t put an else because there is no else. If the conditions are not met then I simply want current buffer to equal than previous.

I see the problem is that in my code when the loop start buffer has no value and code goes to watch it’s previous value (whic does not exists). How can I assign an initial value to the buffer?

 
    for(int i=limit-1; i>=0; i--)
    {
      
      B_UHighLine[i]=iHigh(Symbol(),1,i);      
      
      if(MathIsValidNumber(B_UHighLine[i+1]))
      {
      
      if(iHigh(Symbol(),1,i)>B_UHighLine[i+1]+0.001) B_UHighLine[i]=iHigh(Symbol(),1,i)-0.001;
      else B_UHighLine[i]=B_UHighLine[i+1];
      
      if(iLow(Symbol(),1,i)<B_UHighLine[i]-0.001) B_UHighLine[i]=iLow(Symbol(),1,i)+0.001;
      else B_UHighLine[i]=B_UHighLine[i+1];
      
      }
      

I've tried assign an initial value to the buffer and then running ifs statements only if previous value exist in order to trying to solve the problem... still anything plot on the chart. I know this is a simple question but I can't find solution as I'm a beginner, any further help is appreciated. 

 
ironhak #:

I've tried assign an initial value to the buffer and then running ifs statements only if previous value exist in order to trying to solve the problem... still anything plot on the chart. I know this is a simple question but I can't find solution as I'm a beginner, any further help is appreciated. 

Go to MQL5 folder > Indicators > Examples > ZigZag.mq5

Zigzag works the same. See how it is managed, and make yours.
Btw paste your full code
 
_MAHA_ #:
Go to MQL5 folder > Indicators > Examples > ZigZag.mq5

Zigzag works the same. See how it is managed, and make yours.
Btw paste your full code

Hi, I, using mt4 not 5. Also, zig zag is based on time, it just connect fractals points, what I’m trying to code does not require a period, it just moves with price. 

I think I was clear in explaining how it work, also there is no ode code, there’s just the oninit standard function parameters. 

Is it really that complicated to achieve such a simple thing?

 
ironhak: Hi everyone, I would like an indicator buffer to be equal to it's previous value if a condition is not met. 

If you are coding an indicator based on current symbol, you should not be using IHigh or iLow functions, but instead the actual parameters passed in the OnCalculate event handler.

Based on the little code you have posted, I suspect that your whole indicator is poorly coded and will require some restructuring. When your skeleton code is incorrect it becomes more difficult to resolve simple issues like the one you are having.

It is best to properly structure your code, so I suggest you post your entire code, so that you can get some guidance on how to properly code it.

 
Fernando Carreiro #:

If you are coding an indicator based on current symbol, you should not be using IHigh or iLow functions, but instead the actual parameters passed in the OnCalculate event handler.

Based on the little code you have posted, I suspect that your whole indicator is poorly coded and will require some restructuring. When your skeleton code is incorrect it becomes more difficult to resolve simple issues like the one you are having.

It is best to properly structure your code, so I suggest you post your entire code, so that you can get some guidance on how to properly code it.

Hi thank's, in this case so I should use High[] and Low[] instead of iHigh() and iLow() correct? If I may ask, why?

Anyway this is the code:

#property strict
#property indicator_chart_window

#property indicator_buffers 1
input double PipsLenght    = 0.002; //Total pips 
double B_UHighLine[];
#define UHighLine 0


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   SetIndexStyle(UHighLine,DRAW_LINE, STYLE_SOLID, 3, clrDodgerBlue);
   SetIndexBuffer(UHighLine, B_UHighLine);
   SetIndexLabel(UHighLine,"High Line");


//---
   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 limit;
   limit=rates_total-prev_calculated;
   if(prev_calculated>0)
      limit++;

    for(int i=limit-1; i>=0; i--)
    {      
      B_UHighLine[i]=iHigh(Symbol(),1,i);            
      
      if(iHigh(Symbol(),1,i)>B_UHighLine[i+1]+PipsLenght/2) B_UHighLine[i]=iHigh(Symbol(),1,i)-PipsLenght/2;
      else B_UHighLine[i]=B_UHighLine[i+1];
      
      if(iLow(Symbol(),1,i)<B_UHighLine[i]-PipsLenght/2) B_UHighLine[i]=iLow(Symbol(),1,i)+PipsLenght/2;
      else B_UHighLine[i]=B_UHighLine[i+1];
    }
   
   
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

I re-post what I'm trying to achieve in order to avoid you to read everything from top:

1) The first middle value (when the calculation begins at the extreme left of the chart) should be current high - PipsLenght/2... In other words, current high minus 10 pips. 

2) If the current high is not greater than previous middle value + 10pips, or if the current low is not lower than previous middle value - 10 pips, then actual middle value should be equal to previous middle value. 

3) If current high is greater than previous middle value + 10pips then current middle value should be equal to current high - 10 pips. If current low is lower than previous middle value - 21pips then current middle value should be equal to current low + 10 pips. 


Thank's for your help guys. 

 
ironhak #: in this case so I should use High[] and Low[] instead of iHigh() and iLow() correct? If I may ask, why?

No. The parameters passed by the OnCalculate are high[] and low[], not High[] nor Low[]. Why you ask?

Because the Indicator may be placed on an "Offline Chart" in the case of MT4 ("Custom Symbol" in the case of MT5) and in those cases iHigh, iLow, High[] and Low[] will ALL return the wrong data. Also, even if the indicator is on a normal chart, there is no guarantee that the data presented by the OnCalculate parameters are synchronised with the chart data. They may in fact be out of sync at certain times.

The correct way is to always to use the data passed by the event handler function.

Now for the code. Your logic seems suspect, so I changed it a little to what I believe you want, but you will have to review it to see if that is the case.

//--- Setup

   #property strict
   #property indicator_chart_window

   // Define number of buffers
      #property indicator_buffers   1

   // Define visual appearance of plots

      #property indicator_label1    "High Line"
      #property indicator_type1     DRAW_LINE
      #property indicator_color1    clrDodgerBlue
      #property indicator_style1    STYLE_SOLID
      #property indicator_width1    3

//--- Indicator Settings

   input double   i_dbPriceRange = 0.002; // Price Range

//--- Global variable declarations

   // Indicator buffers
      double g_adbHighLine[];

   // Other global variables
      double dbHalfRange;

//--- Event handling functions

   // Initialisation event handler
      int OnInit(void)
      {
         // Set number of significant digits (precision)
            IndicatorSetInteger( INDICATOR_DIGITS, _Digits );

         // Set Indicator buffers
            SetIndexBuffer( 0, g_adbHighLine, INDICATOR_DATA );
            
         // Set global variables            
            dbHalfRange = i_dbPriceRange * 0.5;
         
         return INIT_SUCCEEDED;  // Successful initialisation of indicator
      };

   // Calculation event handler
      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[]
         )
      {
         // Define maximum index for the buffer array
            int iMaxIndex = rates_total - 1;
         
         // Main loop — fill in the arrays with data values
            for( int i = rates_total - ( prev_calculated < 1 ? 1 : prev_calculated ); i >= 0; i-- )
            {
               double dbHighLine;
                  
               if( i < iMaxIndex )
               {
                  double dbHighLinePrev = g_adbHighLine[ i + 1 ];
                  
                  if( high[ i ] > ( dbHighLinePrev + dbHalfRange ) )
                     dbHighLine = dbHighLinePrev + dbHalfRange;
                  else
                  {
                     if( low[ i ] < ( dbHighLinePrev - dbHalfRange ) )
                        dbHighLine = dbHighLinePrev - dbHalfRange;
                     else
                        dbHighLine = dbHighLinePrev;
                  };
               }
               else
                  dbHighLine = high[ i ];

               g_adbHighLine[ i ] = dbHighLine;
            };
      
         // Return value of prev_calculated for next call
            return rates_total;
      };

EDIT: My apologies, but I re-edited this post multiple times.

Reason: