ATM_XpMA

The XP Moving Average is a versatile technical analysis tool designed to help traders identify price trends and potential entry or exit points by smoothing out market "noise." Rather than relying on a single standard moving average, this script provides a comprehensive suite of mathematical models and intelligent signaling logic.

Core Functionality

Versatile Moving Average Options The script allows users to choose from a wide variety of calculation methods. These range from standard industry favorites like Simple (SMA) and Exponential (EMA) to more advanced, high-responsiveness algorithms including Hull, Jurik, and Triple Exponential Moving Averages. This variety ensures that the tool can be tailored to different trading styles, whether you prefer a smooth, lagging indicator or one that reacts quickly to price fluctuations.

Dynamic Price Integration Users have the flexibility to apply these averages to various price points. Instead of just looking at where a candle closes, the logic can be configured to calculate based on the high, low, opening price, or a "typical" median price, allowing for more nuanced data analysis depending on the specific market conditions.

Advanced Logic & Signal Generation

Smoothing and Offsetting The script includes a "Vertical Shift" feature, which allows traders to manually move the indicator line up or down on the chart. Additionally, it features an automated shifting logic that adjusts based on the timeframe being viewed; for example, on longer timeframes (like Daily or Monthly), the script applies a larger offset to provide more visual clarity.

Trend Detection and Signal Arrows Beyond just drawing a line, the tool performs active logic to identify trend shifts:

  • Comparison Logic: The script calculates a short-term average of the moving average itself over a specific "Step Period."
  • Entry Signals: It compares the current value against this short-term average. If the main indicator crosses above or below this threshold, it triggers a signal.
  • Visual Cues: When these conditions are met, the script automatically places arrows on the chart (Up for potential buys, Down for potential sells) to alert the trader of a trend change.

Notifications and User Experience

To ensure traders don't miss critical movements, the script includes a multi-layered notification system:

  • On-Screen Alerts: Instant pop-up notifications appear directly on the trading platform when an Up or Down signal is confirmed.
  • Email Alerts: For traders who are away from their desks, the script can be configured to send automated emails whenever a new trend signal is detected.
  • Visual Management: The tool includes automated "cleanup" logic that manages chart objects (like labels and arrows) to ensure the workspace remains organized and uncluttered.

In summary, this script acts as an all-in-one trend analysis engine. It combines high-level mathematical smoothing with automated signal detection, providing a clear visual roadmap of market direction while offering various alert methods to keep the trader informed in real-time.

Indicators Used
Moving average indicatorMoving average indicator
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screenIt sends emails
7 Views
0 Downloads
0 Favorites
ATM_XpMA
//Version: 9
//Updated: December 22, 2006. Modifyed by Accrete on January 2nd 2007
//and renamed ATM_xpMAvs   "vs" stands for "Vertical Shift"
//+------------------------------------------------------------------+
//|                       XP Moving Average                          | 
//|                          xpMA.mq4                                |
//|                    Developed by Coders Guru                      |
//|                     http://www.xpworx.com                        |
//|                                                                  |
//| Many thanks to Coders Guru for his MT4 Tutorials and his helpful |
//| assistance. Accrete added "vertical shift" option and matched    |
//| arrow and line buffer colors set by user. more doodles at :      |
//| www.twotrilliondollarsdaily.com and www.accrete.com   Enjoy !!   |
//+------------------------------------------------------------------+
#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   int      TimeFrame               = 0;
extern   int      MA_Period               = 21;
extern   int      MA_Type                 = MODE_SMA;
extern   int      MA_Applied              = PRICE_CLOSE;
extern   double   T3MA_VolumeFactor       = 0.8;
extern   double   JMA_Phase               = 0;
extern   int      Step_Period             = 4;
extern   int      Vertical_Shift          = 0;// added by accrete

extern   bool     DebugMode               = false;

bool     Alert_On                = false;
bool     Arrows_On               = false;
int      UpArrowCode             = 241;
int      DownArrowCode           = 242;
color    UpArrowColor            = indicator_color3;//was Red
color    DownArrowColor          = indicator_color2;//was Blue
int      UpArrowSize             = 3;
int      DownArrowSize           = 3;
bool     Email_Alert             = false;
string   pro  = "xpMA";//was xpMA_v9
string   ver  = "";


double UpBuffer[];
double DownBuffer[];
double Buffer3[];
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,Buffer3);
   
   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 = 7;   break; 
        case    15: nShift = 10;   break; 
        case    30: nShift = 15;  break; 
        case    60: nShift = 20;  break; 
        case   240: nShift = 30;  break; 
        case  1440: nShift = 80;  break; 
        case 10080: nShift = 150; break; 
        case 43200: nShift = 250; break;               
      }
 
   return(0);
}

int deinit()
{
   DeleteStamp();
   DeleteAllObjects();
   return(0);
}



void start()
{
   
   StampVersion(pro,ver,5,20);
   
   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;
                  }
                  for(i=0; i<limit; i++)
                  {
                     matriple[i] = iMAOnArray(tempbuffer,0,MA_Period,0,MODE_EMA,i)+Vertical_Shift*Point;
                  }
                  for(i=0; i<limit; i++)
                  {
                     buffer[i] = iMAOnArray(matriple,0,MA_Period,0,MODE_EMA,i)+Vertical_Shift*Point;
                  }
            }
            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;
                  }
                  for(i=0; i<limit; i++)
                  {
                     buffer[i] = iMAOnArray(tempbuffer,0,MA_Period,0,MODE_EMA,i)+Vertical_Shift*Point;
                  }
            }
            break;
      
      case 6:
            {
                  for(i=0; i<limit; i++)
                  {
                     buffer[i] = iCustom(NULL,TimeFrame,"T3MA",MA_Period,T3MA_VolumeFactor,0,i)+Vertical_Shift*Point;
                  }
            }
            break;
      case 7:
            {
                  for(i=0; i<limit; i++)
                  {
                     buffer[i] = iCustom(NULL,TimeFrame,"JMA",MA_Period,JMA_Phase,0,i)+Vertical_Shift*Point;
                  }
            }
            break;
      
      case 8:
            {
                  for(i=0; i<limit; i++)
                  {
                     buffer[i] = iCustom(NULL,TimeFrame,"HMA",MA_Period,0,i)+Vertical_Shift*Point;
                  }
            }
            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;
                  }
            }
            break;

      case 10:
            {
                  for(i=0; i<limit; i++)
                  {
                     buffer[i] = iCustom(NULL,TimeFrame,"SATL",0,i)+Vertical_Shift*Point;
                  }
            }
            break;
            
   }

   for(int shift=0; shift<limit; shift++)
   {
       UpBuffer[shift] = buffer[shift];
       DownBuffer[shift] = buffer[shift];
       Buffer3[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 && Buffer3[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 && Buffer3[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 && Buffer3[1] != UpBuffer[0])
         AlertOnce(Symbol()+ ":" + PeriodToText() + "  -  Up Signal",1);
      if(DownBuffer[1] == EMPTY_VALUE &&  DownBuffer[0] != EMPTY_VALUE && Buffer3[1] != DownBuffer[0])   
         AlertOnce(Symbol()+ ":" + PeriodToText() + "  -  Down Signal",2);
   }
   
   if(Email_Alert)
   {                  
      if(UpBuffer[1] == EMPTY_VALUE &&  UpBuffer[0] != EMPTY_VALUE && Buffer3[1] != UpBuffer[0])
         SendMailOnce("xpMA Signal",Symbol()+ ":" + PeriodToText() + "  -  Up Signal",1);
      if(DownBuffer[1] == EMPTY_VALUE &&  DownBuffer[0] != EMPTY_VALUE && Buffer3[1] != DownBuffer[0])   
         SendMailOnce("xpMA Signal",Symbol()+ ":" + PeriodToText() + "  -  Down Signal",2);
   }

   
   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",Aqua);
         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",Aqua);
         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