BatMA_v1
Download scriptThis script is designed as a versatile technical analysis tool for the MetaTrader trading platform. Its primary purpose is to calculate and display various types of "Moving Averages" on a price chart. Moving averages are essential tools used by traders to smooth out price fluctuations, making it easier to identify the underlying trend of an asset over time.
Core Functionality
The script allows users to choose between five different mathematical models to calculate these averages. Depending on your selection, the tool will interpret historical price data differently to produce a specific visual line on your chart.
The Five Calculation Methods
The logic is structured to support the following calculation types:
- Simple Moving Average (SMA): This is the most straightforward method. It takes the average price of a set period (e.g., the last 13 bars) and plots it. Every data point in that period carries equal weight in the final calculation.
- Exponential Moving Average (EMA): Unlike the simple version, this method places more importance on recent price data. This allows the line to react more quickly to sudden market changes while still maintaining a smooth trend.
- Smoothed Moving Average (SMMA): This method provides an even greater level of smoothing than the SMA. It is designed to filter out "noise" or minor price spikes more aggressively, making it useful for identifying long-term trends.
- Linear Weighted Moving Average (LWMA): In this model, the most recent prices are given the highest weight, and the weights decrease linearly as you go further back in time. This creates a middle ground between the Simple and Exponential methods.
- Butterworth Moving Average (BatEMA): This is a more complex mathematical calculation designed to provide a specific type of smoothing effect. It uses a unique weighting formula to balance responsiveness with stability.
User Customization
The script includes several "External Parameters" that allow you to tailor the behavior of the indicator without needing to modify the underlying logic:
- Period: You can define the "look-back" window (e.g., how many candles/bars of data the average should consider).
- Shift: This allows you to move the resulting line forward or backward on the chart visually, which is helpful for aligning it with other technical indicators.
- Method: A simple toggle that lets you switch instantly between the five different calculation styles mentioned above.
Operational Logic
When the script runs, it automatically identifies the current market data and begins a "loop" through the history of the chart. It calculates the values for each point in time based on your chosen method and stores them in a buffer. This buffer is then rendered as a continuous line on your screen, updating in real-time as new price data arrives.
//+------------------------------------------------------------------+
//| Custom Moving Average.mq4 |
//| Copyright © 2004, MetaQuotes Software Corp. |
//| Copyright © 2008, YUBA |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp.,Copyright © 2008, YUBA"
#property link "http://www.metaquotes.net/"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- indicator parameters
extern int MA_Period=13;
extern int MA_Shift=0;
extern int MA_Method=1;
//---- indicator buffers
double ExtMapBuffer[], pr;
//----
int ExtCountedBars=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
int draw_begin;
string short_name;
//---- drawing settings
SetIndexStyle(0,DRAW_LINE);
SetIndexShift(0,MA_Shift);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
if(MA_Period<2) MA_Period=13;
draw_begin=MA_Period-1;
//---- indicator short name
switch(MA_Method)
{
case 1 : short_name="EMA("; draw_begin=0; break;
case 2 : short_name="SMMA("; break;
case 3 : short_name="LWMA("; break;
case 4 : short_name="BatEMA("; break;
default :
MA_Method=1;
short_name="EMA(";
}
IndicatorShortName(short_name+MA_Period+")");
SetIndexDrawBegin(0,draw_begin);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer);
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
if(Bars<=MA_Period) return(0);
ExtCountedBars=IndicatorCounted();
//---- check for possible errors
if (ExtCountedBars<0) return(-1);
//---- last counted bar will be recounted
if (ExtCountedBars>0) ExtCountedBars--;
//----
switch(MA_Method)
{
case 0 : sma(); break;
case 1 : ema(); break;
case 2 : smma(); break;
case 3 : lwma(); break;
case 4 : pr=MathSqrt(2.0/(1.0+MA_Period));
BatMa(pr);
}
//---- done
return(0);
}
//+------------------------------------------------------------------+
//| Simple Moving Average |
//+------------------------------------------------------------------+
void sma()
{
double sum=0;
int i,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=Close[pos];
//---- main calculation loop
while(pos>=0)
{
sum+=Close[pos];
ExtMapBuffer[pos]=sum/MA_Period;
sum-=Close[pos+MA_Period-1];
pos--;
}
//---- zero initial bars
if(ExtCountedBars<1)
for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
}
//+------------------------------------------------------------------+
//| Exponential Moving Average |
//+------------------------------------------------------------------+
void ema()
{
double pr=2.0/(MA_Period+1),Y;
int pos=Bars-2;
if(ExtCountedBars>2) pos=Bars-ExtCountedBars-1;
//---- main calculation loop
while(pos>=0)
{
if(pos==Bars-2) ExtMapBuffer[pos+1]=Close[pos+1];
ExtMapBuffer[pos]=Close[pos]*pr+ExtMapBuffer[pos+1]*(1-pr);
pos--;
}
}
//+------------------------------------------------------------------+
//| Smoothed Moving Average |
//+------------------------------------------------------------------+
void smma()
{
double sum=0;
int i,k,pos=Bars-ExtCountedBars+1;
//---- main calculation loop
pos=Bars-MA_Period;
if(pos>Bars-ExtCountedBars) pos=Bars-ExtCountedBars;
while(pos>=0)
{
if(pos==Bars-MA_Period)
{
//---- initial accumulation
for(i=0,k=pos;i<MA_Period;i++,k++)
{
sum+=Close[k];
//---- zero initial bars
ExtMapBuffer[k]=0;
}
}
else sum=ExtMapBuffer[pos+1]*(MA_Period-1)+Close[pos];
ExtMapBuffer[pos]=sum/MA_Period;
pos--;
}
}
//+------------------------------------------------------------------+
//| Linear Weighted Moving Average |
//+------------------------------------------------------------------+
void lwma()
{
double sum=0.0,lsum=0.0;
double price;
int i,weight=0,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<=MA_Period;i++,pos--)
{
price=Close[pos];
sum+=price*i;
lsum+=price;
weight+=i;
}
//---- main calculation loop
pos++;
i=pos+MA_Period;
while(pos>=0)
{
ExtMapBuffer[pos]=sum/weight;
if(pos==0) break;
pos--;
i--;
price=Close[pos];
sum=sum-lsum+price*MA_Period;
lsum-=Close[i];
lsum+=price;
}
//---- zero initial bars
if(ExtCountedBars<1)
for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
}
//+------------------------------------------------------------------+
//| Batterwort Moving Average |
//+------------------------------------------------------------------+
void BatMa(double Kf)
{
double p=2.0/(MA_Period+1);
double p1,p2,p3;
int pos=Bars-2;
p1=Kf*Kf;
p2=2.0*(1-Kf);
p3=(1-Kf)*(1-Kf);
if(ExtCountedBars>2) pos=Bars-ExtCountedBars-1;
//---- main calculation loop
while(pos>=0)
{
if(pos==Bars-2) ExtMapBuffer[pos+1]=Close[pos+1];
ExtMapBuffer[pos]=p1*Close[pos]+p2*ExtMapBuffer[pos+1]-p3*ExtMapBuffer[pos+2];
pos--;
}
}
//+------------------------------------------------------------------+
Comments