MA_Angle_v4

Download script
MA_Angle_v4

This tool is designed to help traders visualize the momentum and "steepness" of a Moving Average (MA) by converting its movement into an angular measurement. Instead of just looking at the price line, this indicator helps you identify how aggressively the trend is moving or if it has flattened out.

How the Logic Works

The script follows a structured process to determine the current "tilt" of a selected moving average:

1. Selection and Customization First, the user selects the specific type of Moving Average they prefer (such as Simple, Exponential, Linear Weighted, or Linear Regression). You can also choose which price data the average should be based on—such as the closing price, the opening price, the high, or the low of a candle.

2. Measuring the Movement The indicator looks at two different points in time on the Moving Average:

  • A "Current" point (the immediate past).
  • A "Previous" point (a set distance further back in history).

By comparing these two points, the script calculates the change in value over that specific distance. This creates a slope.

3. Converting Slope to an Angle To make this data easier for humans to read, the logic converts that raw numerical change into a geometric angle (degrees). It uses mathematical trigonometry to ensure that:

  • A sharp move upward translates to a high positive angle.
  • A sharp move downward translates to a low negative angle.
  • A flat or sideways move results in an angle near zero.

4. Visualizing the Results The indicator displays these angles in a separate window as a histogram, color-coded to give you an instant visual cue of market sentiment:

  • Green: The angle is rising significantly (indicating strong upward momentum).
  • Red: The angle is falling significantly (indicating strong downward momentum).
  • Yellow: The angle is "near zero," meaning the moving average has flattened out. This often suggests a period of consolidation, indecision, or a potential trend reversal where the previous momentum has died down.

Key Summary for Traders

Essentially, this script acts as a "speedometer" for trends. While a standard Moving Average tells you the direction of the price, this tool tells you the intensity of that direction. It allows you to quickly identify when a trend is gaining strength or when it is losing steam and becoming "flat."

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
7 Views
1 Downloads
0 Favorites
MA_Angle_v4
//+------------------------------------------------------------------+
//|                                                     MA_Angle.mq4 |
//| Modified from code for EMA_Angle by jpkfox                       |
//|                                                                  |
//| You can use this indicator to measure when the MA angle is       |
//| "near zero". AngleTreshold determines when the angle for the     |
//| MA is "about zero": This is when the value is between            |
//| [-AngleTreshold, AngleTreshold] (or when the histogram is red).  |
//|   MAPeriod: MA period                                            |
//|   AngleTreshold: The angle value is "about zero" when it is      |
//|     between the values [-AngleTreshold, AngleTreshold].          |      
//|   StartMAShift: The starting point to calculate the              |   
//|     angle. This is a shift value to the left from the            |
//|     observation point. Should be StartMAShift > EndMAShift.      | 
//|   EndMAShift: The ending point to calculate the                  |
//|     angle. This is a shift value to the left from the            | 
//|     observation point. Should be StartMAShift > EndMAShift.      |
//|                                                                  |
//|   Modified by MrPip                                              |
//|       Red for down                                               |
//|       Yellow for near zero                                       |
//|       Green for up                                               |
//|  10/15/05  MrPip                                                 |
//|            Corrected problem with USDJPY and optimized code      |
//|  10/23/05  Added other JPY crosses                               |   
//|                                                                  |
//|   8/1/2006 Modified to use any MA including LSMA                 |                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+

#property  copyright "MrPip and jpkfox"
//---- indicator settings
#property  indicator_separate_window
#property  indicator_buffers 3
#property  indicator_color1  LimeGreen
#property  indicator_color2  Yellow
#property  indicator_color3 FireBrick
#property  indicator_width1 2
#property  indicator_width2 2
#property  indicator_width3 2

//---- indicator parameters
extern int MAPeriod=34;
extern string  m = "--Moving Average Types--";
extern string  m0 = " 0 = SMA";
extern string  m1 = " 1 = EMA";
extern string  m2 = " 2 = SMMA";
extern string  m3 = " 3 = LWMA";
extern string  m4 = " 4 = LSMA";
extern int MA_Type = 1; //0=SMA, 1=EMA, 2=SMMA, 3=LWMA, 4=LSMA
extern string  p = "--Applied Price Types--";
extern string  p0 = " 0 = close";
extern string  p1 = " 1 = open";
extern string  p2 = " 2 = high";
extern string  p3 = " 3 = low";
extern string  p4 = " 4 = median(high+low)/2";
extern string  p5 = " 5 = typical(high+low+close)/3";
extern string  p6 = " 6 = weighted(high+low+close+close)/4";
extern int MA_AppliedPrice = 0;//0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4
extern double AngleTreshold=8;
extern int PrevMAShift=1;
extern int CurMAShift=0;

int MA_Mode;
string strMAType;

//---- indicator buffers
double UpBuffer[];
double DownBuffer[];
double ZeroBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//---- 2 additional buffers are used for counting.
   IndicatorBuffers(3);
//---- drawing settings
   SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID);
   SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID);
   SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_SOLID);

   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+2);

//---- 3 indicator buffers mapping
   if(!SetIndexBuffer(0,UpBuffer) &&
      !SetIndexBuffer(1,DownBuffer) &&
      !SetIndexBuffer(2,ZeroBuffer))
      Print("cannot set indicator buffers!");
switch (MA_Type)
   {
      case 1: strMAType="EMA"; MA_Mode=MODE_EMA; break;
      case 2: strMAType="SMMA"; MA_Mode=MODE_SMMA; break;
      case 3: strMAType="LWMA"; MA_Mode=MODE_LWMA; break;
      case 4: strMAType="LSMA"; break;
      default: strMAType="SMA"; MA_Mode=MODE_SMA; break;
   }
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName("MA_" + strMAType+"_Angle("+MAPeriod+","+AngleTreshold+","+PrevMAShift+","+CurMAShift+")");
//---- initialization done
   return(0);
}

//+------------------------------------------------------------------+
//| LSMA with PriceMode                                              |
//| PrMode  0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2,    |
//| 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4  |
//+------------------------------------------------------------------+

double LSMA(int Rperiod, int prMode, int shift)
{
   int i, mshift;
   double sum, pr;
   int length;
   double lengthvar;
   double tmp;
   double wt;

   length = Rperiod;
 
   sum = 0;
   for(i = length; i >= 1  ; i--)
   {
     lengthvar = length + 1;
     lengthvar /= 3;
     tmp = 0;
     mshift = length-i+shift;
     switch (prMode)
     {
     case 0: pr = Close[mshift];break;
     case 1: pr = Open[mshift];break;
     case 2: pr = High[mshift];break;
     case 3: pr = Low[mshift];break;
     case 4: pr = (High[mshift] + Low[mshift])/2;break;
     case 5: pr = (High[mshift] + Low[mshift] + Close[mshift])/3;break;
     case 6: pr = (High[mshift] + Low[mshift] + 2 * Close[mshift])/4;break;
     }
     tmp = ( i - lengthvar)*pr;
     sum+=tmp;
    }
    wt = MathFloor(sum*6/(length*(length+1))/Point)*Point;
    
    return(wt);
}

//+------------------------------------------------------------------+
//| The angle for MA                                                |
//+------------------------------------------------------------------+
int start()
{
   double fCurMA, fPrevMA;
   double fAngle, mFactor, dFactor;
   int nLimit, i;
   int nCountedBars;
   double angle;
   int ShiftDif;
   string Sym;
 
   if(CurMAShift >= PrevMAShift)
   {
      Print("Error: CurMAShift >= PrevMAShift");
      PrevMAShift = 6;
      CurMAShift = 0;      
   }  
         
   nCountedBars = IndicatorCounted();
//---- check for possible errors
   if(nCountedBars<0) 
      return(-1);
//---- last counted bar will be recounted
   if(nCountedBars>0) 
      nCountedBars--;
   nLimit = Bars-nCountedBars;
//   dFactor = 2*3.14159/180.0;
   dFactor = 3.14159/180.0;
//   mFactor = 100000.0;
   mFactor = 1000.0;
   Sym = StringSubstr(Symbol(),3,3);
//   if (Sym == "JPY") mFactor = 1000.0;
   if (Sym == "JPY") mFactor = 10.0;
   ShiftDif = PrevMAShift-CurMAShift;
//   mFactor /= ShiftDif; 
//---- main loop
   for(i=0; i<nLimit; i++)
   {
      if (MA_Type == 4)
      {
        fCurMA=LSMA(MAPeriod,MA_AppliedPrice, i+CurMAShift);
        fPrevMA=LSMA(MAPeriod,MA_AppliedPrice, i+PrevMAShift);
      }
      else
      {
        fCurMA=iMA(NULL,0,MAPeriod,0,MA_Mode,MA_AppliedPrice,i+CurMAShift);
        fPrevMA=iMA(NULL,0,MAPeriod,0,MA_Mode,MA_AppliedPrice,i+PrevMAShift);
      }
//      fAngle = mFactor * (fCurMA - fPrevMA)/2.0;
//    calculate tan(angle) = opposite / adjacent
      fAngle = (fCurMA - fPrevMA)/ShiftDif;
      // 10000.0 : Multiply by 10000 so that the fAngle is not too small
      // for the indicator Window.
      // take ArcTan of value to get the angle in radians and convert to degrees
      fAngle = mFactor * MathArctan(fAngle)/dFactor;

      DownBuffer[i] = 0.0;
      UpBuffer[i] = 0.0;
      ZeroBuffer[i] = 0.0;
      
      if(fAngle > AngleTreshold)
      {
         UpBuffer[i] = fAngle;
      }
      else if (fAngle < -AngleTreshold)
      {
         DownBuffer[i] = fAngle;
      }
      else ZeroBuffer[i] = fAngle;
   }

   return(0);
  }
//+------------------------------------------------------------------+

Comments