This technical tool is designed to provide traders with a visual representation of price trends by calculating different types of Moving Averages (MA) and extending the most recent data point into a forward-looking "ray."
Core Functionality
The primary purpose of this script is to smooth out market price fluctuations to identify the underlying direction of an asset. It offers four distinct methods for calculating these averages, allowing users to choose the specific mathematical smoothing that best suits their trading style:
- Simple Moving Average (SMA): Calculates a basic average of prices over a set period, giving equal importance to every data point.
- Exponential Moving Average (EMA): Places a greater emphasis on more recent price action, allowing the indicator to react faster to sudden market shifts.
- Smoothed Moving Average (SMMA): A variation that provides a slower, more refined trend line by incorporating previous averages into the current calculation.
- Linear Weighted Moving Average (LWMA): Assigns a weighted value to prices, where the most recent data points have the highest influence on the resulting average.
The "Ray" Projection Logic
A unique feature of this specific script is its ability to project a "ray" onto the chart. While standard moving averages only show historical data (the past), this logic takes the very last calculated value and draws a horizontal line extending into the future space of the chart.
This provides a visual reference point for the current price level, helping traders see exactly where the current trend average stands as new candles form in real-time.
User Customization
The logic is built to be flexible through several adjustable parameters:
- Period: Determines how many past bars of data are used to calculate the average (a higher number creates a smoother, slower line; a lower number creates a more reactive, jagged line).
- Shift: Allows the user to move the entire visual line forward or backward on the chart.
- Visual Styling: Users can customize the color and thickness of the trend line and the projection ray to ensure they are clearly visible against the background of their specific trading charts.
//+------------------------------------------------------------------+
//| Moving Average+Ray.mq4 |
//| Copyright © 2004, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp."
#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=0;
extern color color_ray=Red;
extern int width_ray=1;
//---- indicator buffers
double ExtMapBuffer[];
//----
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;
default :
MA_Method=0;
short_name="SMA(";
}
IndicatorShortName(short_name+MA_Period+")");
SetIndexDrawBegin(0,draw_begin);
//---- indicator buffers mapping
CreateRay();
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
ObjectDelete("MA_Ray");
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();
}
//---- done
if (ObjectFind("MA_Ray")==-1) CreateRay();
ObjectSet("MA_Ray",OBJPROP_TIME1,Time[1]);
ObjectSet("MA_Ray",OBJPROP_PRICE1,ExtMapBuffer[1]);
ObjectSet("MA_Ray",OBJPROP_TIME2,Time[0]);
ObjectSet("MA_Ray",OBJPROP_PRICE2,ExtMapBuffer[0]);
return(0);
}
//+------------------------------------------------------------------+
//| Create Ray |
//+------------------------------------------------------------------+
void CreateRay()
{
SetIndexBuffer(0,ExtMapBuffer);
ObjectCreate("MA_Ray",OBJ_TREND,0,0,0,0,0);
ObjectSet("MA_Ray",OBJPROP_RAY,true);
ObjectSet("MA_Ray",OBJPROP_COLOR,color_ray);
ObjectSet("MA_Ray",OBJPROP_WIDTH,width_ray);
}
//+------------------------------------------------------------------+
//| 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);
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;
}
//+------------------------------------------------------------------+
Comments