bouncestrengthindicator

Download script
Author: 2015, fxborg
bouncestrengthindicator

This indicator is designed to measure and visualize the strength of price "bounces" off support and resistance levels. It helps traders identify how much pressure is being exerted by buyers and sellers at specific price points by analyzing historical price action over a defined period.

Core Logic Overview

The script operates by examining price movement within a rolling window (the "Range Period"). Instead of just looking at the current price, it evaluates how candles behave relative to the highest highs and lowest lows found during that timeframe.

1. Range Identification

The indicator first establishes the boundaries of the current market segment. It identifies:

  • The Highest High reached within the look-back period.
  • The Lowest Low reached within the look-back period.
  • The Total Spread, which is the distance between that high and low.

2. Bounce Strength Calculation

The logic then calculates two distinct types of "Bounce Strength":

  • Floor Bounce Strength (Positive Pressure): The script looks for instances where price moves upward. It specifically identifies bars that aren't primarily "downward" candles and checks how close the low of those bars got to the period's bottom boundary. It calculates a ratio of how much space was covered from the bottom, weighing this by trading volume (if enabled). This tells you how effectively the market is "pushing off" the floor.
  • Ceiling Bounce Strength (Negative Pressure): Conversely, the script identifies bars that aren't primarily "upward" candles and checks how close the high of those bars got to the period's top boundary. It calculates the ratio of space covered from the ceiling, again weighted by volume. This shows the strength of the "rejection" at the top.

3. Volume Integration

A key feature of this logic is the ability to use Tick Volume. When enabled, the indicator doesn't just count how many times a price moved; it weights the bounce strength based on the actual activity occurring. A high-volume bounce is treated as significantly "stronger" than a low-volume move, providing a more accurate picture of market conviction.

4. Visualization and Smoothing

The indicator provides three primary visual outputs:

  • Floor Bounce Histogram: Represents the positive pressure from the bottom.
  • Ceiling Bounce Histogram: Represents the negative pressure from the top.
  • Bounce Strength Index (Main Line): This is a smoothed average of both floor and ceiling pressures. By applying a "Slowing" and "Average Period," the script filters out minor market noise to produce a cleaner line that shows the prevailing trend of momentum—whether the market is currently favoring the "floor" or the "ceiling."

Summary for Traders

Essentially, this tool transforms raw price data into a momentum profile. By looking at the histograms, you can see if the market is actively hitting and reacting to boundaries. The main index then provides a smoothed look at whether that reaction is leaning more toward a bullish (floor-driven) or bearish (ceiling-driven) bias.

Miscellaneous
Implements a curve of type %1
15 Views
0 Downloads
0 Favorites
bouncestrengthindicator
ÿþ//+------------------------------------------------------------------+

//|                                                          BSI.mq4 |

//|                                          Copyright 2015, fxborg. |

//|                                  http://blog.livedoor.jp/fxborg/ |

//+------------------------------------------------------------------+

#property copyright   "2015, fxborg"

#property link        "http://blog.livedoor.jp/fxborg/"

#property description "Bounce Strength Indicator"

#property strict

//---

#property indicator_separate_window

#property indicator_buffers    3

#property indicator_color1     Blue

#property indicator_color2     Red

#property indicator_color3     Black

#property indicator_level1     10.0

#property indicator_level2     0.0

#property indicator_level3     -10.0

#property indicator_levelcolor clrSilver

#property indicator_levelstyle STYLE_DOT

//--- input parameters

input int InpRangePeriod=20; //  Range Period

input int InpSlowing=3;     // Slowing

input int InpAvgPeriod=3;   //  Avg Period

input bool InpUsingVolumeWeight=true;   // Using TickVolume

//--- buffers

double ExtMainBuffer[];

double ExtPosBuffer[];

double ExtNegBuffer[];

//---- for calc 

double ExtHighesBuffer[];

double ExtLowesBuffer[];

double ExtVolBuffer[];

//---

int draw_begin1=0;

int draw_begin2=0;

//+------------------------------------------------------------------+

//| Custom indicator initialization function                         |

//+------------------------------------------------------------------+

int OnInit(void)

  {

   string short_name;

//--- 2 additional buffers are used for counting.

   IndicatorBuffers(6);

   SetIndexBuffer(3,ExtHighesBuffer);

   SetIndexBuffer(4,ExtLowesBuffer);

   SetIndexBuffer(5,ExtVolBuffer);

//--- indicator lines

   SetIndexLabel(0,"Floor Bounce Strength");

   SetIndexStyle(0,DRAW_HISTOGRAM);

   SetIndexBuffer(0,ExtPosBuffer);

   SetIndexLabel(1,"Ceiling Bounce Strength");

   SetIndexStyle(1,DRAW_HISTOGRAM);

   SetIndexBuffer(1,ExtNegBuffer);

   SetIndexLabel(2,"Bounce Strength Index");

   SetIndexStyle(2,DRAW_LINE);

   SetIndexBuffer(2,ExtMainBuffer);

//--- name for DataWindow and indicator subwindow label

//---

   draw_begin1=InpRangePeriod+InpSlowing;

   draw_begin2=draw_begin1+InpAvgPeriod;

   SetIndexDrawBegin(0,draw_begin1);

   SetIndexDrawBegin(1,draw_begin1);

   SetIndexDrawBegin(2,draw_begin2);

   short_name="Bane Strength Index("+IntegerToString(InpRangePeriod)+","+IntegerToString(InpSlowing)+","+IntegerToString(InpAvgPeriod)+")";

   if(InpUsingVolumeWeight)

      short_name+=" using Volumes";

   IndicatorShortName(short_name);

//--- initialization done

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| BSI caluclate                                                    |

//+------------------------------------------------------------------+

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 i,k,pos;

//--- check for bars count

   if(rates_total<=InpRangePeriod+InpAvgPeriod+InpSlowing)

      return(0);

//--- counting from 0 to rates_total

   ArraySetAsSeries(ExtMainBuffer,false);

   ArraySetAsSeries(ExtPosBuffer,false);

   ArraySetAsSeries(ExtNegBuffer,false);

   ArraySetAsSeries(ExtHighesBuffer,false);

   ArraySetAsSeries(ExtLowesBuffer,false);

   ArraySetAsSeries(ExtVolBuffer,false);

   ArraySetAsSeries(low,false);

   ArraySetAsSeries(high,false);

   ArraySetAsSeries(close,false);

   ArraySetAsSeries(tick_volume,false);

//---

   pos=InpRangePeriod-1;

//---  

   if(pos+1<prev_calculated)

      pos=prev_calculated-2;

   else

     {

      for(i=0; i<pos; i++)

        {

         ExtLowesBuffer[i]=0.0;

         ExtHighesBuffer[i]=0.0;

         ExtVolBuffer[i]=0.0;

        }

     }

//--- calculate HighesBuffer[] and ExtHighesBuffer[]

   for(i=pos; i<rates_total && !IsStopped(); i++)

     {

      //--- calculate range spread

      double dmin=1000000.0;

      double dmax=-1000000.0;

      long volmax=0;

      for(k=i-InpRangePeriod+1; k<=i; k++)

        {

         if(dmin>low[k])

            dmin=low[k];

         if(dmax<high[k])

            dmax=high[k];

         if(volmax<tick_volume[k])

            volmax=tick_volume[k];

        }

      ExtLowesBuffer[i]=dmin;

      ExtHighesBuffer[i]=dmax;

      //---

      if(InpUsingVolumeWeight)

         ExtVolBuffer[i]=(double)volmax;

     }

//--- line

   pos=InpRangePeriod-1+InpSlowing-1;

   if(pos+1<prev_calculated)

      pos=prev_calculated-2;

   else

     {

      for(i=0; i<pos; i++)

        {

         ExtMainBuffer[i]=0.0;

         ExtPosBuffer[i]=0.0;

         ExtNegBuffer[i]=0.0;

        }

     }

//--- main cycle

   for(i=pos; i<rates_total && !IsStopped(); i++)

     {

      double sumpos=0.0;

      double sumneg=0.0;

      double sumhigh=0.0;

      double sumpvol = 0.0;

      double sumnvol = 0.0;

      for(k=(i-InpSlowing+1); k<=i; k++)

        {

         //---

         double vol=1.0;

         if(InpUsingVolumeWeight && ExtVolBuffer[k]>0)

           {

            vol=tick_volume[k]/ExtVolBuffer[k];

           }

         //--- Range position ratio

         double ratio=0;

         //--- Range spread

         double range=ExtHighesBuffer[k]-ExtLowesBuffer[k];

         //--- Bar Spread

         double sp=(high[k]-low[k]);

         //--- Not DownBar

         if(!(close[k-1]-sp*0.2>close[k]))

           {

            //--- low equal range low

            if(low[k]==ExtLowesBuffer[k])

               ratio=1;

            else // upper - low / range spread

            ratio=(ExtHighesBuffer[k]-low[k])/range;

            sumpos+=(close[k]-low[k])*ratio *vol;

           }

         //--- Not UpBar

         if(!(close[k-1]+sp*0.2<close[k]))

           {

            //--- high equal range high 

            if(high[k]==ExtHighesBuffer[k])

               ratio=1;

            else // high - lower / range spread

            ratio=(high[k]-ExtLowesBuffer[k])/range;

            sumneg+=(high[k]-close[k])*ratio*vol*-1;

           }

         //---

         sumhigh+=range;

        }

      //---

      if(sumhigh==0.0)

        {

         ExtPosBuffer[i]=EMPTY_VALUE;

         ExtNegBuffer[i]=EMPTY_VALUE;

        }

      else

        {

         ExtPosBuffer[i]=sumpos/sumhigh*100;

         ExtNegBuffer[i]=sumneg/sumhigh*100;

        }

     }

//--- avg

   pos=InpAvgPeriod-1;

   if(pos+1<prev_calculated)

      pos=prev_calculated-2;

   else

     {

      for(i=0; i<pos; i++)

        {

         ExtMainBuffer[i]=0.0;

        }

     }

//---

   for(i=pos; i<rates_total && !IsStopped(); i++)

     {

      double sumPos=0.0;

      double sumNeg=0.0;

      double sum=0.0;

      for(k=0; k<InpAvgPeriod; k++)

        {

         sum+=ExtPosBuffer[i-k]-(-1*ExtNegBuffer[i-k]);

        }

      //---

      ExtMainBuffer[i]=sum/InpAvgPeriod;

     }

//--- OnCalculate done. Return new prev_calculated.

   return(rates_total);

  }

//+------------------------------------------------------------------+

Comments