//+------------------------------------------------------------------+
//|                                                 FractalsTrue.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012, zznbrm"
                          
//---- indicator settings
#property indicator_chart_window
#property  indicator_buffers 4 
#property  indicator_color1 Aqua
#property  indicator_color2 Red
#property  indicator_color3 Aqua
#property  indicator_color4 Red
#property  indicator_width1 1
#property  indicator_width2 1
#property  indicator_width3 1
#property  indicator_width4 1

#define    NONE   0
#define    UP     1
#define    UP_F   2
#define    DOWN   -1
#define    DOWN_F -2

//---- input parameters
extern int eintFractalBars = 3;

//---- indicator buffers
double gadblFractalUpArrow[];
double gadblFractalDnArrow[];
double gadblTrueUpArrow[];
double gadblTrueDnArrow[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   SetIndexBuffer( 0, gadblFractalUpArrow );
   SetIndexEmptyValue( 0, 0.0 );
   SetIndexStyle( 0, DRAW_ARROW );
   SetIndexArrow( 0, 161 ); 
   SetIndexLabel( 0, "FractalUp" );
   
   SetIndexBuffer( 1, gadblFractalDnArrow );
   SetIndexEmptyValue( 1, 0.0 );
   SetIndexLabel( 1, "FractalDn" );
   SetIndexStyle( 1, DRAW_ARROW );
   SetIndexArrow( 1, 161 );    
   
   SetIndexBuffer( 2, gadblTrueUpArrow );
   SetIndexEmptyValue( 2, 0.0 );
   SetIndexStyle( 2, DRAW_ARROW );
   SetIndexArrow( 2, 159 ); 
   SetIndexLabel( 2, "TrueUp" );
   
   SetIndexBuffer( 3, gadblTrueDnArrow );
   SetIndexEmptyValue( 3, 0.0 );
   SetIndexStyle( 3, DRAW_ARROW );
   SetIndexArrow( 3, 159 ); 
   SetIndexLabel( 3, "TrueDn" );
    
   IndicatorDigits( 5 );
     
   //---- name for DataWindow and indicator subwindow label
   IndicatorShortName( "FractalsTrue(" + eintFractalBars + ")" );
   
   return( 0 );
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   return( 0 );
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int counted_bars = IndicatorCounted();
   
   if (counted_bars < 0) return (-1);
   if (counted_bars > 0) counted_bars--;
   int intLimit = Bars - counted_bars;
   int intHigh, intLow;

   for( int inx = intLimit; inx >= 0; inx-- )
   {          
      gadblFractalUpArrow[inx] = 0.0;
      gadblFractalDnArrow[inx] = 0.0;
      gadblTrueUpArrow[inx] = 0.0;
      gadblTrueDnArrow[inx] = 0.0;
      
      intHigh = getHighFractal( inx, eintFractalBars );
      
      if ( intHigh == UP )          gadblTrueUpArrow[inx] = High[inx];
      else if ( intHigh == UP_F )   gadblFractalUpArrow[inx] = High[inx];
      
      intLow = getLowFractal( inx, eintFractalBars );
      
      if ( intLow == DOWN )          gadblTrueDnArrow[inx] = Low[inx];
      else if ( intLow == DOWN_F )   gadblFractalDnArrow[inx] = Low[inx];
   }
   
   return( 0 );
}

//+------------------------------------------------------------------+
//| getHighFractal                                                   |
//+------------------------------------------------------------------+
int getHighFractal( int inx, int intBars )
{
   int intRet = NONE;
   int intStart = 0;
   
   // Check if the current bar has highest high going back
   int intExt = iHighest( Symbol(), Period(), MODE_HIGH, intBars-1, inx+1 );
   
   if ( High[inx] > High[intExt] )
   {
      intRet = UP;
      
      // Check if the current bar has the highest high going forward
      intStart = inx - intBars + 1;
      
      if ( intStart >= 0 )
      {
         intExt = iHighest( Symbol(), Period(), MODE_HIGH, intBars-1, intStart );
         
         if ( High[inx] > High[intExt] )  intRet = UP_F;
      }
   }
   
   return( intRet );
}

//+------------------------------------------------------------------+
//| getLowFractal                                                    |
//+------------------------------------------------------------------+
int getLowFractal( int inx, int intBars )
{
   int intRet = NONE;
   int intStart = 0;
   
   // Check if the current bar has lowest low going back
   int intExt = iLowest( Symbol(), Period(), MODE_LOW, intBars-1, inx+1 );
   
   if ( Low[inx] < Low[intExt] )
   {
      intRet = DOWN;
      
      // Check if the current bar has the highest high going forward
      intStart = inx - intBars + 1;
      
      if ( intStart >= 0 )
      {
         intExt = iLowest( Symbol(), Period(), MODE_LOW, intBars-1, intStart );
         
         if ( Low[inx] < Low[intExt] )  intRet = DOWN_F;
      }
   }
   
   return( intRet );
}