Author:
Snake

The "Snake" indicator is a sophisticated technical analysis tool designed to visualize price dynamics by calculating a dynamic "path" or "spine" and surrounding it with a calculated buffer zone. Instead of simply showing a moving average, it analyzes the relationship between recent price extremes and a smoothed central trend to determine market volatility and sentiment.

Core Logic & Mechanics

The Primary Axis (The Spine) The logic begins by establishing a central reference point, referred to in the script as the "Axis." This axis is generated using a weighted moving average. Rather than giving equal importance to all previous prices, the script applies a specific weighting system based on a defined range (the "Snake Range"). It looks at price data points and assigns weights to them to create a smooth, responsive line that follows the general direction of the market. Users can choose which specific price data to use for this calculation—such as the opening price, closing price, the high/low extremes, or a mathematical average of those values.

Dynamic Range Calculation Once the central axis is established, the script analyzes the historical price action over a broader "Filter Period." It identifies the highest and lowest points reached during this timeframe. By comparing these extremes to the current position of the central axis, the script calculates the volatility of the market.

The Boundary Channels The indicator then projects a boundary (an upper and lower border) around the central axis. These borders are not static; they expand or contract based on the volatility identified in the previous step.

  • If the market is highly volatile (large distance between high and low), the boundaries widen.
  • If the market is stable, the boundaries tighten.

Volatility and Sentiment Indicators Beyond just drawing lines on the chart, the script performs internal calculations to derive several key metrics:

  • Width: This measures the total distance between the upper and lower boundaries, representing the current "breathing room" of the price.
  • Martingale/Trend Value: The script calculates a specific mathematical offset from the axis to determine the core trend strength.
  • Mood: This is perhaps the most unique feature of the logic. It calculates the relative position of the central trend within the current volatility boundaries. By determining where the "spine" sits between the top and bottom borders, it produces a value that represents the prevailing market "mood"—essentially identifying whether the price is leaning toward the upper limit, the lower limit, or staying neutral in the center.

Summary of Behavior

In practical terms, this script acts as a sophisticated "envelope" system. It identifies the heart of the price movement (the Axis), determines the current "swing" of the market based on recent history (the Filter), and then maps out a visual channel. The resulting visual output allows a user to see not just where the price is going, but how much energy/volatility is behind that movement and whether the current trend is biased toward the top or bottom of its typical range.

Indicators Used
Moving average indicator
8 Views
0 Downloads
0 Favorites
Snake
//+------------+-----------------------------------------------------+
//| v.19.04.07 |                                           Snake.mq4 |
//+------------+                                   "ÔÈËÜÒÐÓÉ ÁÀÇÀÐ!" |
//|            |              Bookkeeper, 2006, yuzefovich@gmail.com |
//+------------------------------------------------------------------+
#property copyright ""
#property link      "http://www.forexter.land.ru/indicators.htm"
//----
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1  Blue
#property indicator_color2  Blue
#property indicator_color3  Maroon
#property indicator_color4  Maroon
#property indicator_color5  Black
#property indicator_color6  Black
//----
extern int    SnakeRange   =3; 
extern int    FilterPeriod =21; 
extern double MartFiltr    =2;
extern int    PRICE_Const  =1; // 0 - Close
                               // 1 - Open
                               // 2 - High
                               // 3 - Low
                               // 4 - (H+L)/2
                               // 5 - (H+L+C)/3
                               // 6 - (H+L+2*C)/4
extern bool   HardCalc     =false;
//----
double        BorderTop[];
double        BorderBot[];
double        Mart[];
double        Axis[];
double        Mood[];  // äëÿ iCustom
double        Width[]; // äëÿ iCustom
//----
//----
void deinit()
{
  return;
}
//----
int init()
{
int    draw_begin;
   draw_begin=FilterPeriod+SnakeRange+2;
   IndicatorBuffers  (6);
   SetIndexBuffer    (0,BorderTop);
   SetIndexBuffer    (1,BorderBot); 
   SetIndexBuffer    (2,Mart); 
   SetIndexBuffer    (3,Axis); 
   SetIndexBuffer    (4,Mood); 
   SetIndexBuffer    (5,Width); 
   SetIndexStyle     (0,DRAW_LINE);
   SetIndexStyle     (1,DRAW_LINE);
   SetIndexStyle     (2,DRAW_LINE, EMPTY, 2); 
   SetIndexStyle     (3,DRAW_LINE,STYLE_DOT);
   SetIndexStyle     (4,DRAW_NONE);
   SetIndexStyle     (5,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);
   return(0);
}
//----
int start()
{
int counted_bars=IndicatorCounted();
int limit,i;
   if(counted_bars<0)  return(-1);
   if(Bars<=(FilterPeriod+SnakeRange+2)) return(-1);
   if(SnakeRange<3) SnakeRange=3;
   if(counted_bars>0)  counted_bars--;
   limit=Bars-counted_bars;
   for(i=limit;i>=0;i--) MainCalculation(i);
   return(0);
}
//---------------------------------------------------------------------
void MainCalculation(int Pos)
{
   if((Bars-Pos)>(SnakeRange+1)) MartAxis(Pos); 
   else Axis[Pos]=0;
   if((Bars-Pos)>(FilterPeriod+SnakeRange+2)) 
   {
      if(HardCalc==true) SmoothOverMart2(Pos);
      else SmoothOverMart(Pos);
   } 
   else 
   {
      BorderTop[Pos]=0;
      BorderBot[Pos]=0;
      Mart[Pos]=0;
      Mood[Pos]=0;
      Width[Pos]=0;
   }
   return;
}
//---------------------------------------------------------------------
void MartAxis(int Pos)
{  
int    SnakeWeight, i, w, ww, Shift;
double SnakeSum;
   switch(PRICE_Const) {
   case  0: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_CLOSE,Pos);
      break;
   case  1: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_OPEN,Pos);
      break;
   case  2: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_HIGH,Pos);
      break;
   case  3: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_LOW,Pos);
      break;
   case  4: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_MEDIAN,Pos);
      break;
   case  5: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_TYPICAL,Pos);
      break;
   case  6: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_WEIGHTED,Pos);
      break;
   default: Axis[Pos]=iMA(NULL,0,SnakeRange+1,0,MODE_LWMA,PRICE_WEIGHTED,Pos);
      break; }
   for(Shift=Pos+SnakeRange+2;Shift>Pos;Shift--)
   {
      SnakeSum=0.0;
      SnakeWeight=0;
      i=0;
      w=Shift+SnakeRange;
      ww=Shift-SnakeRange;
      if(ww<Pos) ww=Pos;
      while(w>=Shift)
      {
         i++;
         SnakeSum=SnakeSum+i*SnakePrice(w);
         SnakeWeight=SnakeWeight+i;
         w--;
      }
      while(w>=ww)
      {
         i--;
         SnakeSum=SnakeSum+i*SnakePrice(w);
         SnakeWeight=SnakeWeight+i;
         w--;
      }
      Axis[Shift]=SnakeSum/SnakeWeight;
   }
   return;
}
//----
double SnakePrice(int Shift)
{
   switch(PRICE_Const) {
   case  0:
      return(Close[Shift]);
   case  1:
      return(Open[Shift]);
   case  2:
      return(High[Shift]);
   case  3:
      return(Low[Shift]);
   case  4:
      return((High[Shift]+Low[Shift])/2);
   case  5:
      return((Close[Shift]+High[Shift]+Low[Shift])/3);
   case  6:
      return((2*Close[Shift]+High[Shift]+Low[Shift])/4);
   default:
      return((2*Close[Shift]+High[Shift]+Low[Shift])/4); }
}
//---------------------------------------------------------------------
void SmoothOverMart(int Pos)
{ 
int    Shift;
double a, t, b;
   for(Shift=Pos+SnakeRange+2;Shift>=Pos;Shift--)
   {
      t=Axis[ArrayMaximum(Axis,FilterPeriod,Shift)];
      b=Axis[ArrayMinimum(Axis,FilterPeriod,Shift)];
      a=Axis[Shift];
      BorderTop[Shift]=(2*(1+MartFiltr)*a+(t-b))/2/(1+MartFiltr);
      BorderBot[Shift]=(2*(1+MartFiltr)*a-(t-b))/2/(1+MartFiltr);
      Mart[Shift]=(2*(2+MartFiltr)*a-(t+b))/2/(1+MartFiltr);
      Width[Shift]=BorderTop[Shift]-BorderBot[Shift];
      Mood[Shift]=2.0*(Mart[Shift]-BorderBot[Shift])/
                   (BorderTop[Shift]-BorderBot[Shift])-1.0;
   }
   return;
}
//---------------------------------------------------------------------
void SmoothOverMart2(int Shift)
{ 
double a, t, b;
      t=Axis[ArrayMaximum(Axis,FilterPeriod,Shift)];
      b=Axis[ArrayMinimum(Axis,FilterPeriod,Shift)];
      a=Axis[Shift];
      BorderTop[Shift]=(2*(1+MartFiltr)*a+(t-b))/2/(1+MartFiltr);
      BorderBot[Shift]=(2*(1+MartFiltr)*a-(t-b))/2/(1+MartFiltr);
      Mart[Shift]=(2*(2+MartFiltr)*a-(t+b))/2/(1+MartFiltr);
      Width[Shift]=BorderTop[Shift]-BorderBot[Shift];
      Mood[Shift]=2.0*(Mart[Shift]-BorderBot[Shift])/
                   (BorderTop[Shift]-BorderBot[Shift])-1.0;
   return;
}
//---------------------------------------------------------------------

Comments