SnakeSMA
Download scriptThis indicator, known as "SnakeSMA," is designed to provide a smoother and more responsive moving average on your trading charts. Unlike standard moving averages that treat all past data points with equal importance or follow simple linear progression, this script employs a unique "Snake" logic to calculate price trends.
How the Logic Works
The core philosophy of this indicator is centered around a weighted distribution of prices. Instead of simply averaging a block of candles, it creates a balanced calculation by weighting prices based on their proximity to a central point (the current candle).
1. The "Snake" Weighting System Imagine a weight distributed like a physical scale. The indicator looks at a specific range of historical data defined by your settings. It gives more significance to prices closer to the current time and less significance to those further away. This creates a "weighted" average that reacts more fluidly to new market information while maintaining a smooth line on the chart.
2. Mathematical Balancing The indicator performs a sophisticated balancing act:
- It calculates a sum of prices multiplied by their relative distance from the center.
- It ensures that the values on the "left" side of the calculation are balanced against the "right" side.
- By calculating these weights dynamically, the line can curve and adapt to market volatility more naturally than a standard straight-line average.
3. Adaptive Calculation Modes While the primary logic revolves around this unique weighting, the script also allows for flexibility in how it handles price types:
- Moving Average Types: You can choose between different standard calculation modes (like Simple, Exponential, or Weighted) to influence how the underlying data is processed.
- Price Sources: You can decide which specific price point the "Snake" should track, such as the closing price, opening price, or a combination of high and low prices.
Summary for Traders
In practical terms, this script aims to reduce the "lag" typically associated with moving averages without making the line so jumpy that it becomes difficult to read. It attempts to find a middle ground where the indicator follows the trend closely enough to be useful for entries and exits, but remains smooth enough to filter out minor market noise.
//+------------------------------------------------------------------+
//| SnakeSMA.mq4 |
//| "ÈÍÄÈÊÀÒÎÐÛ ÄËß ÑÀÌÎÎÁÌÀÍÀ" |
//| Bookkeeper, 2006, yuzefovich@gmail.com |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
//----
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Yellow
//----
extern int Snake_HalfCycle=5; // Snake_HalfCycle = 4...10 or other
extern int MAMode = 0; // 0-SMA, 1-EMA 2-SMMA 3-LWMA
extern int Price = 0; // 0-Close, 1-Open... 6-Typical
//----
double Snake_Buffer[];
double Snake_Sum, Snake_Weight, Snake_Sum_Minus, Snake_Sum_Plus;
int Snake_FullCycle;
//----
int init()
{
int draw_begin;
Snake_FullCycle=Snake_HalfCycle*2+1;
draw_begin=Snake_FullCycle+1;
SetIndexDrawBegin(0,draw_begin);
SetIndexBuffer(0,Snake_Buffer);
SetIndexStyle(0,DRAW_LINE);
return(0);
}
//----
int start()
{
int FirstPos, ExtCountedBars=0;
if(Bars<=150) return(0);
if(Snake_HalfCycle<3) Snake_HalfCycle=3;
ExtCountedBars=IndicatorCounted();
if (ExtCountedBars<0) return(-1);
if (ExtCountedBars>0) ExtCountedBars--;
FirstPos=Bars-ExtCountedBars-1;
if(FirstPos>Bars-Snake_HalfCycle-1) FirstPos=Bars-Snake_HalfCycle-1;
Snake(FirstPos);
return(0);
}
//----
void Snake(int Pos)
{
int i;
if(Pos<=Snake_HalfCycle+1) Pos=Snake_HalfCycle+2;
Snake_Buffer[Pos]=SnakeFirstCalc(Pos);
Pos--;
while(Pos>=Snake_HalfCycle)
{
Snake_Buffer[Pos]=SnakeNextCalc(Pos);
Pos--;
}
while(Pos>0)
{
Snake_Buffer[Pos]=SnakeFirstCalc(Pos);
Pos--;
}
if(Pos==0)
Snake_Buffer[0]=iMA(NULL,0,Snake_HalfCycle,0,MAMode,Price,0);
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;
Snake_Weight=0.0;
if(Shift<Snake_HalfCycle)
{
i=0;
w=Shift+Snake_HalfCycle;
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-Snake_HalfCycle,i=Shift+Snake_HalfCycle,w=1;
w<= Snake_HalfCycle;
j++,i--,w++)
{
Snake_Sum=Snake_Sum+w*(SnakePrice(i)+SnakePrice(j));
Snake_Weight=Snake_Weight+2*w;
Snake_Sum_Minus=Snake_Sum_Minus+SnakePrice(i);
Snake_Sum_Plus=Snake_Sum_Plus+SnakePrice(j);
}
Snake_Sum=Snake_Sum+( Snake_HalfCycle+1)*SnakePrice(Shift);
Snake_Weight=Snake_Weight+ Snake_HalfCycle+1;
Snake_Sum_Minus=Snake_Sum_Minus+SnakePrice(Shift);
}
return(Snake_Sum/ Snake_Weight);
}
//----
double SnakeNextCalc(int Shift)
{
Snake_Sum_Plus=Snake_Sum_Plus+SnakePrice(Shift-Snake_HalfCycle);
Snake_Sum=Snake_Sum-Snake_Sum_Minus+Snake_Sum_Plus;
Snake_Sum_Minus=Snake_Sum_Minus-SnakePrice(Shift+Snake_HalfCycle+1)+SnakePrice(Shift);
Snake_Sum_Plus=Snake_Sum_Plus-SnakePrice(Shift);
return(Snake_Sum/Snake_Weight);
}
//----
Comments