ATM_xpMAv10bVS_25LWMAmedian
Download scriptOverview of the XP Moving Average Logic
The XP Moving Average is a sophisticated technical analysis tool designed to help traders identify trend directions and potential entry points by smoothing out market price fluctuations. Unlike a standard moving average that simply follows the price, this script employs a multi-layered logic system to filter "market noise" and provide clearer visual cues.
Core Functionality
1. Customizable Smoothing Engines
The script is built with a wide variety of mathematical models to calculate averages. Depending on your preference, it can utilize several different smoothing techniques, including:
- Standard Models: Simple, Exponential, Smoothed, and Linear Weighted averages.
- Advanced Models: Triple Exponential (TEMA), Double Exponential (DEMA), Hull Moving Average (HMA), Jurik Moving Average (JMA), and more. Each of these models reacts differently to price speed; some are designed to be extremely responsive to sudden moves, while others are optimized for stability in slow-moving markets.
2. Dynamic Vertical Shifting
A unique feature of this script is the Vertical Shift logic. It allows the user to offset the indicator vertically on the chart. This is particularly useful when plotting multiple moving averages simultaneously, as it prevents the lines from overlapping, making it easier to see the relationship between different trend types.
3. Trend Detection and Signal Generation
The core "intelligence" of the script lies in how it determines buy and sell signals:
- Comparative Analysis: The script calculates a short-term average (based on a user-defined "Step Period") and compares the current moving average value against this shorter window.
- Signal Identification:
- An Up Signal is generated when the primary moving average crosses above its short-term average.
- A Down Signal is generated when it crosses below.
- Visual Cues: When these conditions are met, the script automatically places arrows on the chart to highlight the specific moment a trend shift occurs.
4. Automated Alerts and Notifications
To ensure traders don't have to watch the screen constantly, the script includes an extensive notification system:
- On-Screen Alerts: Pop-up notifications appear immediately when an Up or Down signal is confirmed.
- Email Notifications: The script can send automated emails directly to the user's inbox when trend changes are detected.
- Price Cross Alerts: It monitors for "Price Breaks," alerting the user specifically when the current market price crosses over the moving average line.
- Range Monitoring: Users can define a specific "Price Range." The script will notify the trader the moment the market enters this designated zone, which is highly effective for identifying consolidation phases or breakout zones.
Summary of User Experience
For a non-technical user, this tool functions as an automated trend analyst. It takes raw price data, processes it through complex mathematical filters of your choosing, and then simplifies that data into three clear outputs: visual lines (showing the trend), arrows (marking entries), and notifications (alerting you to action in real-time).
//Version: 10
//Updated: February 13, 2007
//+------------------------------------------------------------------+
//| XP Moving Average |
//| xpMA.mq4 |
//| Developed by Coders Guru |
//| http://www.xpworx.com |
//+------------------------------------------------------------------+
#property link "http://www.xpworx.com"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Yellow
#property indicator_color2 Red
#property indicator_color3 Blue
#define MODE_DEMA 4
#define MODE_TEMA 5
#define MODE_T3MA 6
#define MODE_JMA 7
#define MODE_HMA 8
#define MODE_DECEMA 9
#define MODE_SALT 10
/* Moving average types constants:
------------------------------------
MODE_SMA 0 Simple moving average,
MODE_EMA 1 Exponential moving average,
MODE_SMMA 2 Smoothed moving average,
MODE_LWMA 3 Linear weighted moving average.
MODE_DEMA 4 Double Exponential Moving Average.
MODE_TEMA 5 Triple Exponential Moving Average.
MODE_T3MA 6 T3 Moving Average.
MODE_JMA 7 Jurik Moving Average.
MODE_HMA 8 Hull Moving Average.
MODE_DECEMA 9 DECEMA Moving Average.
MODE_SALT 10 SALT Indicator.
------------------------------------*/
/* Applied price constants:
-------------------------------
PRICE_CLOSE 0 Close price.
PRICE_OPEN 1 Open price.
PRICE_HIGH 2 High price.
PRICE_LOW 3 Low price.
PRICE_MEDIAN 4 Median price, (high+low)/2.
PRICE_TYPICAL 5 Typical price, (high+low+close)/3.
PRICE_WEIGHTED 6 Weighted close price, (high+low+close+close)/4.
--------------------------------- */
extern string xpMA_by_CodersGuru = "Vertical Shift mods by Accrete";// added by accrete
int TimeFrame = 0;
int MA_Period = 25;
int MA_Type = MODE_LWMA;
int MA_Applied = PRICE_MEDIAN;
extern string Vertical_Shift_Settings = "Place 2 MAs, one +, one - VS";// added by accrete
extern int Vertical_Shift = 50;// added by accrete
string MA_Settings = "For T3 and JMA only";// added by accrete
double T3MA_VolumeFactor = 0.8;
double JMA_Phase = 0;
int Step_Period = 4;
bool DebugMode = false;
extern string Alert_ = "Settings";// added by accrete
extern bool Alert_On = true;
bool Arrows_On = false;
int UpArrowCode = 241;
int DownArrowCode = 242;
color UpArrowColor = indicator_color3;// added by accrete
color DownArrowColor = indicator_color2;// added by accrete
int UpArrowSize = 3;
int DownArrowSize = 3;
extern bool Email_Alert = false;
extern bool AlertOnPriceBreak = true;
extern bool AlertOnPriceRange = true;
extern double PriceRangeUpper = 5.0;
extern double PriceRangeLower = 5.0;
// string pro = "ATM_xpMAv10bVS_25LWMAmedian";
string pro = "Open-Close Trending Model xpMA25LWMA-VS Channel";
string ver = "";
double UpBuffer[];
double DownBuffer[];
double MainBuffer[];
double buffer[];
double tempbuffer[];
double matriple[];
double signal[];
int nShift;
int init()
{
DeleteStamp();
ver = GenVer();
DeleteAllObjects();
IndicatorBuffers(7);
SetIndexStyle(2,DRAW_LINE,STYLE_DOT,2);
SetIndexBuffer(2,UpBuffer);
SetIndexStyle(1,DRAW_LINE,STYLE_DOT,2);
SetIndexBuffer(1,DownBuffer);
SetIndexStyle(0,DRAW_LINE,STYLE_DOT,2);
SetIndexBuffer(0,MainBuffer);
SetIndexBuffer(3,signal);
SetIndexBuffer(4,buffer);
SetIndexBuffer(5,tempbuffer);
SetIndexBuffer(6,matriple);
SetIndexLabel(0,"XP Moving Average");
SetIndexLabel(1,"DownBuffer");
SetIndexLabel(2,"UpBuffer");
SetIndexLabel(3,"Signal");
switch(Period())
{
case 1: nShift = 5; break;
case 5: nShift = 10; break;
case 15: nShift = 15; break;
case 30: nShift = 15; break;
case 60: nShift = 30; break;
case 240: nShift = 30; break;
case 1440: nShift = 90; break;
case 10080: nShift = 180; break;
case 43200: nShift = 240; break;
}
return(0);
}
int deinit()
{
DeleteStamp();
DeleteAllObjects();
return(0);
}
void start()
{
StampVersion(pro,ver,5,15);
int limit;
int i = 0;
int counted_bars=IndicatorCounted();
if(counted_bars<0) return(-1);
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
switch (MA_Type)
{
case 0:
case 1:
case 2:
case 3:
{
for(i=0; i<limit; i++)
{
buffer[i] = iMA(NULL,TimeFrame,MA_Period,0,MA_Type,MA_Applied,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 4:
{
for(i=0; i<limit; i++)
{
tempbuffer[i] = iMA(NULL,TimeFrame,MA_Period,0,MODE_EMA,MA_Applied,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
for(i=0; i<limit; i++)
{
matriple[i] = iMAOnArray(tempbuffer,0,MA_Period,0,MODE_EMA,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
for(i=0; i<limit; i++)
{
buffer[i] = iMAOnArray(matriple,0,MA_Period,0,MODE_EMA,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 5:
{
for(i=0; i<limit; i++)
{
tempbuffer[i] = iMA(NULL,TimeFrame,MA_Period,0,MODE_EMA,MA_Applied,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
for(i=0; i<limit; i++)
{
buffer[i] = iMAOnArray(tempbuffer,0,MA_Period,0,MODE_EMA,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 6:
{
for(i=0; i<limit; i++)
{
buffer[i] = iCustom(NULL,TimeFrame,"T3MA",MA_Period,T3MA_VolumeFactor,0,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 7:
{
for(i=0; i<limit; i++)
{
buffer[i] = iCustom(NULL,TimeFrame,"JMA",MA_Period,JMA_Phase,0,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 8:
{
for(i=0; i<limit; i++)
{
buffer[i] = iCustom(NULL,TimeFrame,"HMA",MA_Period,0,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 9:
{
for(i=0; i<limit; i++)
{
buffer[i] = iCustom(NULL,TimeFrame,"DECEMA_v1",MA_Period,MA_Applied,0,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
case 10:
{
for(i=0; i<limit; i++)
{
buffer[i] = iCustom(NULL,TimeFrame,"SATL",0,i)+Vertical_Shift*Point;// Vertical_Shift*Point added by accrete
}
}
break;
}
for(int shift=0; shift<limit; shift++)
{
UpBuffer[shift] = buffer[shift];
DownBuffer[shift] = buffer[shift];
MainBuffer[shift] = buffer[shift];
}
/*for(shift=0; shift<limit; shift++)
{
if (buffer[shift]<buffer[shift+1])
{
UpBuffer[shift] = EMPTY_VALUE;
}
else if (buffer[shift]>buffer[shift+1] )
{
DownBuffer[shift] = EMPTY_VALUE;
}
else
{
UpBuffer[shift] = CLR_NONE;
DownBuffer[shift] = CLR_NONE;
}
}*/
for(shift=0; shift<limit; shift++)
{
double dMA = 0;
for(int k = shift+1; k <= shift+Step_Period; k++){
dMA += buffer[k];
}
dMA = dMA / Step_Period;
if (buffer[shift] < dMA)
{
UpBuffer[shift] = EMPTY_VALUE;
}
else if (buffer[shift]>dMA)
{
DownBuffer[shift] = EMPTY_VALUE;
}
else
{
UpBuffer[shift] = EMPTY_VALUE;
DownBuffer[shift] = EMPTY_VALUE;
}
}
for(shift=0; shift<limit; shift++)
{
signal[shift]=0;
if(UpBuffer[shift+1] == EMPTY_VALUE && UpBuffer[shift] != EMPTY_VALUE && MainBuffer[shift+1] != UpBuffer[shift] )
{
if(Arrows_On && shift !=0) DrawObject(1,shift, buffer[shift] - nShift*Point);
if(Arrows_On && shift ==0) DrawOnce(1,shift, buffer[shift] - nShift*Point,1);
signal[shift] = 1;
}
if(DownBuffer[shift+1] == EMPTY_VALUE && DownBuffer[shift] != EMPTY_VALUE && MainBuffer[shift+1] != DownBuffer[shift])
{
if(Arrows_On && shift !=0) DrawObject(2,shift, buffer[shift] + nShift*Point);
if(Arrows_On && shift ==0) DrawOnce(2,shift, buffer[shift] + nShift*Point,2);
signal[shift] = -1;
}
}
if(Alert_On)
{
if(UpBuffer[1] == EMPTY_VALUE && UpBuffer[0] != EMPTY_VALUE && MainBuffer[1] != UpBuffer[0])
AlertOnce(Symbol()+ ":" + PeriodToText() + " - Up Signal",1);
if(DownBuffer[1] == EMPTY_VALUE && DownBuffer[0] != EMPTY_VALUE && MainBuffer[1] != DownBuffer[0])
AlertOnce(Symbol()+ ":" + PeriodToText() + " - Down Signal",2);
}
if(Email_Alert)
{
if(UpBuffer[1] == EMPTY_VALUE && UpBuffer[0] != EMPTY_VALUE && MainBuffer[1] != UpBuffer[0])
SendMailOnce("xpMA Signal",Symbol()+ ":" + PeriodToText() + " - Up Signal",1);
if(DownBuffer[1] == EMPTY_VALUE && DownBuffer[0] != EMPTY_VALUE && MainBuffer[1] != DownBuffer[0])
SendMailOnce("xpMA Signal",Symbol()+ ":" + PeriodToText() + " - Down Signal",2);
}
if(AlertOnPriceBreak)
{
if(MainBuffer[0] > Close[0] && MainBuffer[1] < Close[1])
AlertOnce(Symbol()+ ":" + PeriodToText() + " - Cross up occured!",3);
if(MainBuffer[0] < Close[0] && MainBuffer[1] > Close[1])
AlertOnce(Symbol()+ ":" + PeriodToText() + " - Cross down occured!",4);
}
if(AlertOnPriceRange && PriceRangeLower>0 && PriceRangeUpper>0)
{
RefreshRates();
if(MainBuffer[0] >= PriceRangeLower && MainBuffer[1] <= PriceRangeUpper)
AlertOnce(Symbol()+ ":" + PeriodToText() + " - The price entered the range(" + DoubleToStr(PriceRangeLower,MarketInfo(Symbol(),MODE_DIGITS)) + ":" + DoubleToStr(PriceRangeUpper,MarketInfo(Symbol(),MODE_DIGITS))+ ").",5);
}
if(DebugMode)
{
TakeScreenShot(40);
}
return(0);
}
bool DrawOnce(int direction, int bar , double price, int ref)
{
static int LastDraw_1 = 0;
static int LastDraw_2 = 0;
static int LastDraw_3 = 0;
static int LastDraw_4 = 0;
switch(ref)
{
case 1:
if( LastDraw_1 == 0 || LastDraw_1 < Bars )
{
DrawObject(direction, bar , price);
LastDraw_1 = Bars;
return (1);
}
break;
case 2:
if( LastDraw_2 == 0 || LastDraw_2 < Bars )
{
DrawObject(direction, bar , price);
LastDraw_2 = Bars;
return (1);
}
break;
case 3:
if( LastDraw_3 == 0 || LastDraw_3 < Bars )
{
DrawObject(direction, bar , price);
LastDraw_3 = Bars;
return (1);
}
break;
case 4:
if( LastDraw_4 == 0 || LastDraw_4 < Bars )
{
DrawObject(direction, bar , price);
LastDraw_4 = Bars;
return (1);
}
break;
}
}
void DrawObject(int direction, int bar , double price)
{
static int count = 0;
count++;
string Obj = "";
if (direction==1) //up arrow
{
Obj = "xpMA_up_" + DoubleToStr(count,0);
ObjectCreate(Obj,OBJ_ARROW,0,Time[bar],price);
ObjectSet(Obj,OBJPROP_COLOR,UpArrowColor);
ObjectSet(Obj,OBJPROP_ARROWCODE,UpArrowCode);
ObjectSet(Obj,OBJPROP_WIDTH,DownArrowSize);
}
if (direction==2) //down arrow
{
Obj = "xpMA_down_" + DoubleToStr(count,0);
ObjectCreate(Obj,OBJ_ARROW,0,Time[bar],price);
ObjectSet(Obj,OBJPROP_COLOR,DownArrowColor);
ObjectSet(Obj,OBJPROP_ARROWCODE,DownArrowCode);
ObjectSet(Obj,OBJPROP_WIDTH,DownArrowSize);
}
ObjectsRedraw();
}
void DeleteAllObjects()
{
int objs = ObjectsTotal();
string name;
for(int cnt=ObjectsTotal()-1;cnt>=0;cnt--)
{
name=ObjectName(cnt);
if (StringFind(name,"xpMA",0)>-1) ObjectDelete(name);
ObjectsRedraw();
}
}
bool AlertOnce(string alert_msg, int ref)
{
static int LastAlert_1 = 0;
static int LastAlert_2 = 0;
static int LastAlert_3 = 0;
static int LastAlert_4 = 0;
switch(ref)
{
case 1:
if( LastAlert_1 == 0 || LastAlert_1 < Bars )
{
Alert(alert_msg);
LastAlert_1 = Bars;
return (1);
}
break;
case 2:
if( LastAlert_2 == 0 || LastAlert_2 < Bars )
{
Alert(alert_msg);
LastAlert_2 = Bars;
return (1);
}
break;
case 3:
if( LastAlert_3 == 0 || LastAlert_3 < Bars )
{
Alert(alert_msg);
LastAlert_3 = Bars;
return (1);
}
break;
case 4:
if( LastAlert_4 == 0 || LastAlert_4 < Bars )
{
Alert(alert_msg);
LastAlert_4 = Bars;
return (1);
}
break;
}
}
bool SendMailOnce(string subject, string mail_msg, int ref)
{
static int LastMail_1 = 0;
static int LastMail_2 = 0;
static int LastMail_3 = 0;
static int LastMail_4 = 0;
switch(ref)
{
case 1:
if( LastMail_1 == 0 || LastMail_1 < Bars )
{
SendMail(subject,mail_msg);
LastMail_1 = Bars;
return (1);
}
break;
case 2:
if( LastMail_2 == 0 || LastMail_2 < Bars )
{
SendMail(subject,mail_msg);
LastMail_2 = Bars;
return (1);
}
break;
case 3:
if( LastMail_3 == 0 || LastMail_3 < Bars )
{
SendMail(subject,mail_msg);
LastMail_3 = Bars;
return (1);
}
break;
case 4:
if( LastMail_4 == 0 || LastMail_4 < Bars )
{
SendMail(subject,mail_msg);
LastMail_4 = Bars;
return (1);
}
break;
}
}
void TakeScreenShot(int exit_on = -1)
{
int count = 1;
if(!GlobalVariableCheck("ssc"))
{
GlobalVariableSet("ssc",1);
count = 1;
}
else
{
count = GlobalVariableGet("ssc") + 1;
GlobalVariableSet("ssc",count);
}
if ( exit_on > 0 && count > exit_on ) return(0);
string filename = "xpMA\\" + "xpMA_" + Symbol() + "_" + DoubleToStr(count,0) + ".jpg";
ScreenShot(filename,320,480);
}
string PeriodToText()
{
switch (Period())
{
case 1:
return("M1");
break;
case 5:
return("M5");
break;
case 15:
return("M15");
break;
case 30:
return("M30");
break;
case 60:
return("H1");
break;
case 240:
return("H4");
break;
case 1440:
return("D1");
break;
case 10080:
return("W1");
break;
case 43200:
return("MN1");
break;
}
}
void StampVersion(string pro , string ver , int x , int y)
{
string Obj="Stamp_" + pro;
int objs = ObjectsTotal();
string name;
for(int cnt=0;cnt<ObjectsTotal();cnt++)
{
name=ObjectName(cnt);
if (StringFind(name,Obj,0)>-1)
{
ObjectSet(Obj,OBJPROP_XDISTANCE,x);
ObjectSet(Obj,OBJPROP_YDISTANCE,y);
ObjectsRedraw();
}
else
{
ObjectCreate(Obj,OBJ_LABEL,0,0,0);
ObjectSetText(Obj,pro + " " + ver,8,"arial",Lime);
ObjectSet(Obj,OBJPROP_XDISTANCE,x);
ObjectSet(Obj,OBJPROP_YDISTANCE,y);
ObjectsRedraw();
}
}
if (ObjectsTotal() == 0)
{
ObjectCreate(Obj,OBJ_LABEL,0,0,0);
ObjectSetText(Obj,pro + " " + ver,8,"arial",Lime);
ObjectSet(Obj,OBJPROP_XDISTANCE,x);
ObjectSet(Obj,OBJPROP_YDISTANCE,y);
ObjectsRedraw();
}
return(0);
}
void DeleteStamp()
{
int objs = ObjectsTotal();
string name;
for(int cnt=ObjectsTotal()-1;cnt>=0;cnt--)
{
name=ObjectName(cnt);
if (StringFind(name,"Stamp",0)>-1) ObjectDelete(name);
ObjectsRedraw();
}
}
string GenVer()
{
/*
string t1;
if(MA_Type==0) t1="SMA";
if(MA_Type==1) t1="EMA";
if(MA_Type==2) t1="SMMA";
if(MA_Type==3) t1="LWMA";
if(MA_Type==4) t1="DEMA";
if(MA_Type==5) t1="TEMA";
if(MA_Type==6) t1="T3MA";
if(MA_Type==7) t1="JMA";
if(MA_Type==8) t1="HMA";
if(MA_Type==9) t1="DECEMA";
if(MA_Type==10) t1="SALT";
return (t1+"("+MA_Period+")");
*/
}
Comments