Nested For Loops

 

Hello,

I am at the beginning of trying to create a support and resistance indicator which uses swing high and lows.

I have started with a bit of code which should look back looks for two swings highs and checks whether they come within ATR of each other. The issue I am having is I want to run a loop within the overall indicator loop, but it doesn't seem to be running, or isn't outputting what I am looking for. I cant for the life of me find a solution, so I feel like I am missing something! The final indicator will likely need a few nested loops for multiple look backs so I need to understand if I am using nesting loops incorrectly. 

I have used a custom indicator to swings, which is attached. 

//+------------------------------------------------------------------+
//|                                                           SR.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_plots   4
//--- plot TopSupportLine
#property indicator_label1  "TopSupportLine"
#property indicator_type1   DRAW_SECTION
#property indicator_color1  clrOrangeRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot BottomSupportLine
#property indicator_label2  "BottomSupportLine"
#property indicator_type2   DRAW_SECTION
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot TopResistanceLine
#property indicator_label3  "TopResistanceLine"
#property indicator_type3   DRAW_SECTION
#property indicator_color3  clrLawnGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot BottomResistanceLine
#property indicator_label4  "BottomResistanceLine"
#property indicator_type4   DRAW_SECTION
#property indicator_color4  clrLawnGreen
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1


int      handleSHSL;
int      handleATR;

double   SHBuffer[];
double   SLBuffer[];

double   ATRBuffer[];

double   TopSupportLine[];
double   BottomSupportLine[];
double   TopResistanceLine[];
double   BottomResistanceLine[];

input int SHSLperiod = 5;

int OnInit()
  {

   SetIndexBuffer(0,TopSupportLine,INDICATOR_DATA);
   SetIndexBuffer(1,BottomSupportLine,INDICATOR_DATA);
   SetIndexBuffer(2,TopResistanceLine,INDICATOR_DATA);
   SetIndexBuffer(3,BottomResistanceLine,INDICATOR_DATA);
   
   SetIndexBuffer(4,SHBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,SLBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,ATRBuffer,INDICATOR_CALCULATIONS);
   
   handleSHSL = iCustom(NULL,0,"SHSL V2");
   handleATR = iATR(NULL,0,14);
   
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);

   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   IndicatorRelease(handleATR); 
   IndicatorRelease(handleSHSL); 
  }
  

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[])
  {

   // check there is aneough bars for 2 swings to appear. If period is 5 then we need 20 bars for calculation. 
   
   if(rates_total<SHSLperiod*4)
      return(0);
      
   int to_copy; 
   
   //number of values to copy from indicator buffers
   
   if(prev_calculated>rates_total || prev_calculated<=0) 
      to_copy=rates_total; 
   else 
     { 
      to_copy=rates_total-prev_calculated; 

      to_copy++; 
     } 
   
   //copy indicator buffers to arrays
   int copyATR = CopyBuffer(handleATR,0,0,to_copy,ATRBuffer);
   int copySH = CopyBuffer(handleSHSL,0,0,to_copy,SHBuffer);
   int copySL = CopyBuffer(handleSHSL,1,0,to_copy,SLBuffer);
   
   //error checks
   if(copySL<0)
      Print("copy SL failed" + (string)GetLastError());
   if(copySH<0)
      Print("copy SH failed" + (string)GetLastError());
   if(copyATR<0)
      Print("copy ATR failed" + (string)GetLastError());
    
   //set as series
   ArraySetAsSeries(SHBuffer,false);
   ArraySetAsSeries(SLBuffer,false);
   ArraySetAsSeries(ATRBuffer,false);
   
   int limit,i,i2;
    
   // if it the first call, then set the limit to calculate for all bars, otherwise only calculate for new bars. Set arrays to empty
   
   if(prev_calculated <= (SHSLperiod*4)+1)
   
      {
      
      limit = SHSLperiod*4;
      
      ArrayInitialize(BottomSupportLine,EMPTY_VALUE);
      ArrayInitialize(TopSupportLine,EMPTY_VALUE);    
      ArrayInitialize(BottomResistanceLine,EMPTY_VALUE);
      ArrayInitialize(TopResistanceLine,EMPTY_VALUE);
      
      
      }
    
    else limit = rates_total-(SHSLperiod*2);

    
    
    for(i=limit;i<rates_total-1 && !IsStopped();i++)
      {
         //check for a swing high on the current bar, if its true begin a loop which looks back for a second swing high in the last 200 bars
         
         if(SHBuffer[i] != EMPTY_VALUE)
            {            
            for(i2=i-1;i2<i-200 && !IsStopped();i--)
               {
               
               if(SHBuffer[i2] != EMPTY_VALUE)
               //check to see if this new swing high is within ATR above or below the current swing high
                  if(SHBuffer[i2] > SHBuffer[i]-ATRBuffer[i] && SHBuffer[i2] < SHBuffer[i]+ATRBuffer[i])
                     {
                     // if its above, then set the top line to this swing high and the bottom to the current and break. otherwise do the opposite. 
                     if(SHBuffer[i2] > SHBuffer[i])
                        {
                        
                        TopResistanceLine[i2] = high[i2];
                        TopResistanceLine[i] = high[i2];
                        BottomResistanceLine[i2] = high[i];
                        BottomResistanceLine[i] = high[i];
                        break;
                        }
                     else
                        {
                        
                        TopResistanceLine[i2] = high[i];
                        TopResistanceLine[i] = high[i];
                        BottomResistanceLine[i2] = high[i2];
                        BottomResistanceLine[i] = high[i2];
                        break;
                        }
                                    
                     }
                 //otherwise set to empty
                 else
                 {
                 
                 TopResistanceLine[i2] = EMPTY_VALUE;
                 TopResistanceLine[i] = EMPTY_VALUE;
                 BottomResistanceLine[i2] = EMPTY_VALUE;
                 BottomResistanceLine[i] = EMPTY_VALUE;
                 
                 }
         
            }
         }
      }
   
   return(rates_total);
  }
//+------------------------------------------------------------------+


Any help is much appreciated..

Files:
SHSL_V2.mq5  4 kb
 

Before you try to explore every potential error you can make as a beginner here have you searched (top right the lens) for already existing code?

Maybe e.g. fractals will do what you want at least you can look how they have managed to find highs and lows..

But you can search for resistance and support as well.

 
Carl Schreiber:

Before you try to explore every potential error you can make as a beginner here have you searched (top right the lens) for already existing code?

Maybe e.g. fractals will do what you want at least you can look how they have managed to find highs and lows..

But you can search for resistance and support as well.

Hi, thanks for the reply, yes I have searched for a similar code, and have found one which is very similar in the use of for loops for lookbacks, but cant understand why that one works and mine doesn't! I will continue looking however. 
 
  1.            for(i2=i-1;i2<i-200 && !IsStopped();i--)

    If i2 ever becomes negative you have array exceeded.

  2.       to_copy=rates_total-prev_calculated; 
    
          to_copy++; 
         } 
       
       //copy indicator buffers to arrays
       int copyATR = CopyBuffer(handleATR,0,0,to_copy,ATRBuffer);
       int copySH = CopyBuffer(handleSHSL,0,0,to_copy,SHBuffer);
       int copySL = CopyBuffer(handleSHSL,1,0,to_copy,SLBuffer);
    Your i2 loop goes back to the earlier candles, yet you don't provide them.
 
William Roeder:
  1. If i2 ever becomes negative you have array exceeded.

  2. Your i2 loop goes back to the earlier candles, yet you don't provide them.
thanks for the reply, thats a silly mistake, thanks for pointing it out. I have tried to alter to reflect this but doesn't seem to alter the results, which makes me thing the for loop isn't actually running? Shouldn't I have got an array out of range error otherwise? 
   // check there is enough bars 
   
   if(rates_total<barsback)
      return(0);
      
   int to_copy; 
   
   //number of values to copy from indicator buffers
   
   if(prev_calculated>rates_total || prev_calculated<=0) 
      to_copy=rates_total; 
   else 
     { 
      to_copy=rates_total-prev_calculated; 

      to_copy++; 
     } 
   
   //copy indicator buffers to arrays
   int copyATR = CopyBuffer(handleATR,0,0,to_copy,ATRBuffer);
   int copySH = CopyBuffer(handleSHSL,0,0,to_copy,SHBuffer);
   int copySL = CopyBuffer(handleSHSL,1,0,to_copy,SLBuffer);
   
   //error checks
   if(copySL<0)
      Print("copy SL failed" + (string)GetLastError());
   if(copySH<0)
      Print("copy SH failed" + (string)GetLastError());
   if(copyATR<0)
      Print("copy ATR failed" + (string)GetLastError());
    
   //set as series
   ArraySetAsSeries(SHBuffer,false);
   ArraySetAsSeries(SLBuffer,false);
   ArraySetAsSeries(ATRBuffer,false);
   
   int limit,i,i2;
    
   // if it the first call, then set the limit to calculate for all bars, otherwise only calculate for new bars. Set arrays to empty
   
   if(prev_calculated <= barsback +1)
   
      {
      
      limit = barsback;
      
      ArrayInitialize(BottomSupportLine,EMPTY_VALUE);
      ArrayInitialize(TopSupportLine,EMPTY_VALUE);    
      ArrayInitialize(BottomResistanceLine,EMPTY_VALUE);
      ArrayInitialize(TopResistanceLine,EMPTY_VALUE);
      
      
      }
    //else check everytime a new swing could appera.
    else limit = rates_total-(SHSLperiod*2);

    
    
    for(i=limit;i<rates_total && !IsStopped();i++)
      {
         //check for a swing high on the current bar, if its true begin a loop which looks back for a second swing high in the last n bars
         
         if(SHBuffer[i] != EMPTY_VALUE)
            {            
            for(i2=i-1;i2<i-barsback && !IsStopped();i--)
               {
               
               if(SHBuffer[i2] != EMPTY_VALUE)
               //check to see if this new swing high is within ATR above or below the current swing high
                  if(SHBuffer[i2] > SHBuffer[i]-ATRBuffer[i] && SHBuffer[i2] < SHBuffer[i]+ATRBuffer[i])
                     {
                     // if its above, then set the top line to this swing high and the bottom to the current and break. otherwise do the opposite. 
                     if(SHBuffer[i2] > SHBuffer[i])
                        {
                        
                        TopResistanceLine[i2] = high[i2];
                        TopResistanceLine[i] = high[i2];
                        BottomResistanceLine[i2] = high[i];
                        BottomResistanceLine[i] = high[i];
                        break;
                        }
                     else
                        {
                        
                        TopResistanceLine[i2] = high[i];
                        TopResistanceLine[i] = high[i];
                        BottomResistanceLine[i2] = high[i2];
                        BottomResistanceLine[i] = high[i2];
                        break;
                        }
                                    
                     }
                 //otherwise set to empty
                 else
                 {
                 
                 TopResistanceLine[i2] = EMPTY_VALUE;
                 TopResistanceLine[i] = EMPTY_VALUE;
                 BottomResistanceLine[i2] = EMPTY_VALUE;
                 BottomResistanceLine[i] = EMPTY_VALUE;
                 
                 }
         
            }
         }
      }
   
   return(rates_total);
  }
//+------------------------------------------------------------------+
input int SHSLperiod = 5;
input int barsback = 200;
The checks a trading robot must pass before publication in the Market
The checks a trading robot must pass before publication in the Market
  • www.mql5.com
Before any product is published in the Market, it must undergo compulsory preliminary checks, as a small error in the expert or indicator logic can cause losses on the trading account. That is why we have developed a series of basic checks to ensure the required quality level of the Market products. If any errors are identified by the Market...
 
Evan Moore:

Hello,

I am at the beginning of trying to create a support and resistance indicator which uses swing high and lows.

I have started with a bit of code which should look back looks for two swings highs and checks whether they come within ATR of each other. The issue I am having is I want to run a loop within the overall indicator loop, but it doesn't seem to be running, or isn't outputting what I am looking for. I cant for the life of me find a solution, so I feel like I am missing something! The final indicator will likely need a few nested loops for multiple look backs so I need to understand if I am using nesting loops incorrectly. 

I have used a custom indicator to swings, which is attached. 


Any help is much appreciated..

I would also advise you to stay consistent with your code if you use Deinit of void type then use void OnInit function instead of int OnInit function  .

 
Teboho Rakotsoane:

I would also advise you to stay consistent with your code if you use Deinit of void type then use void OnInit function instead of int OnInit function  .

Okay thanks for the advice!
 
I still haven't had any luck with this, any help would be appreciated. 
 
The decrement of your second for loop should be "i2--" not "i--". 
Reason: