SnakeBorders

Download script
Author:
SnakeBorders

This technical indicator is designed to provide traders with a visual representation of market corridors and price boundaries. It focuses on identifying "envelopes" or channels based on historical price action, helping to define potential zones of support and resistance.

Core Logic and Mechanism

1. The "Snake" Signal Base The foundation of this script is a custom calculation referred to as the "Snake." This is a smoothed price value derived from a combination of High, Low, and Close prices. Unlike a standard moving average that gives equal weight to all data points, the Snake uses a weighted approach to create a smoother, more reactive baseline of where the market is currently trending.

2. Dynamic Corridor Calculation The indicator creates two distinct corridors (or "Borders") based on different time horizons:

  • Primary Border (Max Period): This looks at a larger window of data to establish the broad boundaries of the market. It identifies the highest and lowest points the "Snake" has reached over a long duration and places a boundary around the current price.
  • Secondary Border (Min Period): This is a more localized corridor that monitors shorter-term fluctuations. It provides a tighter view of the immediate trading range.

3. Weighted Boundary Smoothing To prevent the borders from jumping erratically, the script uses a weighted formula to plot them. Instead of just showing the extreme high and low points, it blends those extremes with the current "Snake" price. This results in smooth, flowing lines that represent the "walls" of the current market movement.

4. Visual Representations Depending on user preferences, these boundaries can be displayed in two different visual formats:

  • Lines: Continuous flow showing the steady progression of the corridors.
  • Histograms: Vertical bars that provide a more distinct view of the corridor's range at specific points in time.

5. Real-Time Tracking and Data Output The script includes a dynamic reporting system on the chart. It automatically calculates the distance between the upper and lower boundaries (the "Walk") and displays this information as a text comment. This allows a visitor to see exactly how wide the current market corridor is in real-time, providing an immediate sense of volatility—a wider "walk" suggests high volatility, while a narrower one suggests consolidation.

Summary for the User

In simple terms, this script acts as a volatility map. It identifies the boundaries of where the price is currently "living." By looking at both long-term and short-term borders simultaneously, it helps you see if the price is trending within a stable channel, breaking out of its historical limits, or compressing into a tight range before a potential move.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
4 Views
0 Downloads
0 Favorites
SnakeBorders
//+------------------------------------------------------------------+
//|                                                      Borders.mq4 |
//|                                      "ÈÍÄÈÊÀÒÎÐÛ ÄËß ÑÀÌÎÎÁÌÀÍÀ" |
//|                           Bookkeeper, 2006, yuzefovich@gmail.com |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1  Olive
#property indicator_color2  Olive
#property indicator_color3  Olive
#property indicator_color4  Olive
#property indicator_color5  PowderBlue
#property indicator_color6  PowderBlue
#property indicator_color7  Yellow
//----
extern int  MaxPeriod          =60; 
extern int  MinPeriod          =24; 
extern bool Show_MaxPeriod     =true; // Ðèñîâàòü êîðèäîð ïî ñâå÷êàì
                                      // ñ ïåðèîäîì MaxPeriod
extern bool Show_HistMaxPeriod =true; // Ðèñîâàòü êîðèäîð ïî ñâå÷êàì
                                      // ñ ïåðèîäîì MaxPeriod
                                      // â âèäå ãèñòîãðàììû
extern bool Show_HistMinPeriod =true; // Ðèñîâàòü êîðèäîð ïî ñâå÷êàì
                                      // ñ ïåðèîäîì MinPeriod
                                      // â âèäå ãèñòîãðàììû
extern bool Show_Signal        =true; // Ðèñîâàòü ñèãíàëüíóþ
//----
double    TopBorder1[];
double    ind_buffer1[];
double    BottomBorder1[];
double    ind_buffer2[];
double    TopBorder2[];
double    BottomBorder2[];
double    Signal[];
//----
double Snake_Sum, Snake_Weight, Snake_Sum_Minus, Snake_Sum_Plus;
double indperiod,val1,val2;
string CommentStr;
//----
int init()
{
int    draw_begin;
   draw_begin=2*MaxPeriod+10;
   IndicatorBuffers(7);
   SetIndexBuffer(0,TopBorder1);
   SetIndexBuffer(1,ind_buffer1);
   SetIndexBuffer(2,BottomBorder1);
   SetIndexBuffer(3,ind_buffer2);
   SetIndexBuffer(4,TopBorder2);
   SetIndexBuffer(5,BottomBorder2);
   SetIndexBuffer(6,Signal);
   if(Show_MaxPeriod==true)
   { 
      if(Show_HistMaxPeriod==true)
      { 
         SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,2); 
         SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,2);
         SetIndexStyle(2,DRAW_HISTOGRAM,EMPTY,2);
         SetIndexStyle(3,DRAW_HISTOGRAM,EMPTY,2);
      }
      else 
      { 
         SetIndexStyle(0,DRAW_LINE,EMPTY,2); 
         SetIndexStyle(1,DRAW_NONE);
         SetIndexStyle(2,DRAW_LINE,EMPTY,2);
         SetIndexStyle(3,DRAW_NONE);
      }
   }
   else 
   { 
      SetIndexStyle(0,DRAW_NONE); 
      SetIndexStyle(1,DRAW_NONE);
      SetIndexStyle(2,DRAW_NONE);
      SetIndexStyle(3,DRAW_NONE);
   }
   if(Show_HistMinPeriod==true)
   { 
      SetIndexStyle(4,DRAW_HISTOGRAM);
      SetIndexStyle(5,DRAW_HISTOGRAM);
   }
   else 
   { 
      SetIndexStyle(4,DRAW_LINE);
      SetIndexStyle(5,DRAW_LINE);
   }
   if(Show_Signal==true) SetIndexStyle(6,DRAW_LINE);
   else                  SetIndexStyle(6,DRAW_NONE);
   SetIndexDrawBegin(0,draw_begin);
   SetIndexDrawBegin(1,draw_begin);
   SetIndexDrawBegin(2,draw_begin);
   SetIndexDrawBegin(3,draw_begin);
   SetIndexDrawBegin(4,draw_begin);
   SetIndexDrawBegin(5,draw_begin);
   SetIndexDrawBegin(6,draw_begin);
   indperiod=1.0*MinPeriod*Period();
   if(indperiod<60)
   {
      CommentStr=DoubleToStr(indperiod,0);
      CommentStr=" M"+CommentStr;
   }
   else
   {
      indperiod=indperiod/60;
      if(indperiod>=24)
      {
         val1=MathAbs(MathRound(indperiod/24)-indperiod/24);
         if(val1<0.01)
         {
            CommentStr=DoubleToStr(indperiod/24,0);
            CommentStr=" D"+CommentStr;
         }
          else
         {
            CommentStr=DoubleToStr(indperiod/24,1);
            CommentStr=" D"+CommentStr;
         }
      }
      else
      {
         val1=MathAbs(MathRound(indperiod)-indperiod);
         if(val1<0.01)
         {
            CommentStr=DoubleToStr(indperiod,0);
            CommentStr=" H"+CommentStr;
         }
          else
         {
            CommentStr=DoubleToStr(indperiod,1);
            CommentStr=" H"+CommentStr;
         }
      }
   }
   CommentStr="SnakeInBorders"+CommentStr;
   if(Show_MaxPeriod==true)
   {
   indperiod=1.0*MaxPeriod*Period();
   if(indperiod<60)
      CommentStr=CommentStr+" in M"+DoubleToStr(indperiod,0);
   else
   {
      indperiod=indperiod/60;
      if(indperiod>=24)
      {
         val1=MathAbs(MathRound(indperiod/24)-indperiod/24);
         if(val1<0.01)
            CommentStr=CommentStr+" in D"+DoubleToStr(indperiod/24,0);
          else
            CommentStr=CommentStr+" in D"+DoubleToStr(indperiod/24,1);
      }
      else
      {
         val1=MathAbs(MathRound(indperiod)-indperiod);
         if(val1<0.01)
            CommentStr=CommentStr+" in H"+DoubleToStr(indperiod,0);
          else
            CommentStr=CommentStr+" in H"+DoubleToStr(indperiod,1);
      }
   }
   }
   return(0);
}
//----
void deinit()
{
  Comment("");
}
//----
int start()
{
int FirstPos, ExtCountedBars=0,i;
   if(Bars<=150) return(0);
   if(MinPeriod<21) return(0);
   if(MaxPeriod<=MinPeriod) return(0);
   ExtCountedBars=IndicatorCounted();
   if (ExtCountedBars<0) return(-1);
   if (ExtCountedBars>0) ExtCountedBars--;
   FirstPos=Bars-ExtCountedBars-1;
   if(FirstPos>Bars-MaxPeriod-7)
   {
      FirstPos=Bars-MaxPeriod-7;
      Signal[FirstPos+MaxPeriod]=SnakeFirstCalc(FirstPos+MaxPeriod);
      for(i=FirstPos+MaxPeriod-1;i>FirstPos;i--) SnakeNextCalc(i);
   }
   Snake(FirstPos);
   return(0);
}
//----
void Snake(int Pos)
{
int i;
   if(Pos<6) Pos=6;
   Signal[Pos]=SnakeFirstCalc(Pos);
   Drawing(Pos);
   Pos--;
   while(Pos>=5)
   {
      Signal[Pos]=SnakeNextCalc(Pos);
      Drawing(Pos);
      Pos--;
   }
   while(Pos>0)
   {
      Signal[Pos]=SnakeFirstCalc(Pos);
      Drawing(Pos);
      Pos--;
   }
   if(Pos==0) 
   {
      Signal[Pos]=iMA(NULL,0,6,0,MODE_LWMA,PRICE_TYPICAL,0);
      Drawing(Pos);
   }
   return;
}
//----
double SnakePrice(int Shift)
{
   return((2*Close[Shift]+High[Shift]+Low[Shift])/4);
}
//----
double SnakeFirstCalc(int Shift)
{
int i, j, w;
   Snake_Sum=0.0;
   if(Shift<5)
   {
      Snake_Weight=0.0;
      i=0;
      w=Shift+5;
      while(w>=Shift)
      {
         i++;
         Snake_Sum=Snake_Sum+i*SnakePrice(w);
         Snake_Weight=Snake_Weight+i;
         w--;
      }
      while(w>=0)
      {
         i--;
         Snake_Sum=Snake_Sum+i*SnakePrice(w);
         Snake_Weight=Snake_Weight+i;
         w--;
      }
   }
   else
   {
      Snake_Sum_Minus=0.0;
      Snake_Sum_Plus=0.0;
      for(j=Shift-5,i=Shift+5,w=1; w<=5; j++,i--,w++)
      {
         Snake_Sum=Snake_Sum+w*(SnakePrice(i)+SnakePrice(j));
         Snake_Sum_Minus=Snake_Sum_Minus+SnakePrice(i);
         Snake_Sum_Plus=Snake_Sum_Plus+SnakePrice(j);
      }
      Snake_Sum=Snake_Sum+6*SnakePrice(Shift);
      Snake_Sum_Minus=Snake_Sum_Minus+SnakePrice(Shift);
      Snake_Weight=36;
   }
   return(Snake_Sum/Snake_Weight);
}
//----
double SnakeNextCalc(int Shift)
{
   Snake_Sum_Plus=Snake_Sum_Plus+SnakePrice(Shift-5);
   Snake_Sum=Snake_Sum-Snake_Sum_Minus+Snake_Sum_Plus;
   Snake_Sum_Minus=Snake_Sum_Minus-SnakePrice(Shift+6)+SnakePrice(Shift);
   Snake_Sum_Plus=Snake_Sum_Plus-SnakePrice(Shift);
   return(Snake_Sum/Snake_Weight);
}
//----
void Drawing(int Shift)
{
int i;
   TopBorder1[Shift]=
   (5*Signal[ArrayMaximum(Signal,MaxPeriod,Shift)]+4*Signal[Shift])/9;
   BottomBorder1[Shift]=
   (5*Signal[ArrayMinimum(Signal,MaxPeriod,Shift)]+4*Signal[Shift])/9;
   TopBorder2[Shift]=
   (5*Signal[ArrayMaximum(Signal,MinPeriod,Shift)]+4*Signal[Shift])/9;
   ind_buffer1[Shift]=TopBorder2[Shift];
   BottomBorder2[Shift]=
   (5*Signal[ArrayMinimum(Signal,MinPeriod,Shift)]+4*Signal[Shift])/9;
   ind_buffer2[Shift]=BottomBorder2[Shift];
   if(Shift==0) ind_comment();
   return;
}
//----
void ind_comment()
{
string shortname,str;
int    i;
   shortname=CommentStr;
   str=DoubleToStr((TopBorder2[11]-BottomBorder2[11])/Point,0);
   shortname=shortname+" :   Walk .."+str+"ï";
   for(i=10;i>=0;i--) 
   {
      str=DoubleToStr((TopBorder2[i]-BottomBorder2[i])/Point,0);
      shortname=shortname+".."+str+"ï";
   }
   Comment(shortname);
   return;
}
//----

Comments