//
// SS2009_B v1.01 - updated by eni in 2015 ( better performance and compatible to latest MT4 releases )
//

#define IND_VERSION "v1.01"

//
// properties
//

#property strict

#property indicator_separate_window
#property indicator_buffers 3

#property indicator_color1  clrBlack
#property indicator_color2  clrBlue
#property indicator_color3  clrRed

#property indicator_width1  0
#property indicator_width2  2
#property indicator_width3  2

#property indicator_style1  0
#property indicator_style2  0
#property indicator_style3  0

//
// input section
//

input int lookback = 15;    // Super Signals Period ( lookback )

//
// global variables section
//

double ValueBuff[];
double UpperBuff[];
double LowerBuff[];

//
// init indicator
//

int init()
  {
    IndicatorDigits    ( Digits + 1 );
    IndicatorShortName ( "SS2009_B " + IND_VERSION );
    IndicatorBuffers   ( 3 );
      
    SetIndexStyle      ( 0, DRAW_NONE      );
    SetIndexStyle      ( 1, DRAW_HISTOGRAM );
    SetIndexStyle      ( 2, DRAW_HISTOGRAM );
    
    SetIndexBuffer     ( 0, ValueBuff      );
    SetIndexBuffer     ( 1, UpperBuff      );
    SetIndexBuffer     ( 2, LowerBuff      );
    
    SetIndexEmptyValue ( 0, EMPTY_VALUE    );
    SetIndexEmptyValue ( 1, EMPTY_VALUE    );
    SetIndexEmptyValue ( 2, EMPTY_VALUE    );
     
    SetIndexLabel      ( 1, NULL);
    SetIndexLabel      ( 2, NULL);
    
    return(0);
  }
  
//
// deinit indicator
//

int deinit()
  {
    return(0);
  }
  
//
// indicator loop
//

int start()
  {
    double prev_val   = 0.0; 
    double curr_val   = 0.0;
    double max_low    = 0.0;
    double max_high   = 0.0;
    double med_val    = 0.0;
    double db1        = 0.0;
    double db2        = 0.0;
    double db3        = 0.0;
    
    bool   High_Value = true;
   
    int i, limit, counted_bars, lookback_counter;
   
    if ( Bars <= lookback + 1 ) return(0);
   
    counted_bars = IndicatorCounted();
    if ( counted_bars < 0 ) return(-1);
    if ( counted_bars > 0 ) counted_bars--;
    limit = Bars - counted_bars;
   
    lookback_counter = lookback;
    if ( limit > lookback_counter ) lookback_counter = limit;
   
    for ( i = 0 ; i < lookback_counter ; i++ )
        {
          max_high = High[ iHighest ( NULL, 0, MODE_HIGH, lookback, i ) ];
          max_low  = Low [ iLowest  ( NULL, 0, MODE_LOW , lookback, i ) ];
          
          med_val  = ( High[i] + Low[i] ) / 2.0;
          
          if ( max_high - max_low == 0.0 )
             {
               db1 = 0.67 * db2 + ( -0.33 );
             }
          else
             {
               db1 = 0.66 * ( ( med_val - max_low ) / ( max_high - max_low ) - 0.5 ) + 0.67 * db2;
             }
             
          db1 = MathMin ( MathMax ( db1, -0.999 ), 0.999 );
          
          if ( 1 - db1 == 0.0 )
             {
               ValueBuff[i] = db3 / 2.0 + 0.5;
             }
          else
             {
               ValueBuff[i] = MathLog ( ( db1 + 1.0 ) / ( 1 - db1 ) ) / 2.0 + db3 / 2.0;
             }
             
          db2 = db1;
          db3 = ValueBuff[i];
          
        }
   
    High_Value = true;
   
    for ( i = lookback_counter; i >= 0 ; i-- )
        {
          if ( i > Bars - 2 ) continue;   // no array out of range looking back ( i + 1 );
      
          curr_val = ValueBuff[i];
          prev_val = ValueBuff[i + 1];
          
          if ( ( curr_val < 0.0 && prev_val > 0.0 ) || curr_val < 0.0 ) High_Value = false;
          if ( ( curr_val > 0.0 && prev_val < 0.0 ) || curr_val > 0.0 ) High_Value = true;
          
          if ( !High_Value )
             {
               LowerBuff[i] = curr_val;
               UpperBuff[i] = 0.0;
             }
          else
             {
               UpperBuff[i] = curr_val;
               LowerBuff[i] = 0.0;
             }
        }  
           
    return(0);
  }
  
//
// end indicator code
//