MMA
Download scriptThe Morris MA is a sophisticated moving average indicator designed to provide a smoother, more responsive visualization of price trends in the Forex market. Unlike standard moving averages that simply calculate a mean of past prices, this script employs a dynamic "driving" and "damping" logic to react intelligently to market volatility.
Core Logic Overview
The indicator aims to balance two competing needs in trading: reacting quickly enough to capture price movements while remaining smooth enough to filter out insignificant market noise. It achieves this through three primary mechanisms:
1. Noise Evaluation The script first determines the "noise level" of the market by looking at the distance between the high and low prices of a specific bar. By establishing what constitutes a normal price fluctuation, the indicator can differentiate between meaningful trends and erratic, insignificant price spikes.
2. The Driving Function (Acceleration) Instead of treating every price change equally, the logic calculates an "error" value—the difference between the current price and the current trend line.
- Small moves result in very little influence on the indicator.
- Significant trends provide a stronger "drive," pulling the moving average toward the new price level.
- Sharp spikes are automatically dampened so they do not cause the indicator to jump unnaturally.
3. The Damping Function (Braking) To prevent the indicator from overshooting or reacting too aggressively when the price moves rapidly but then levels off, a damping system acts as a "brake." If the average is moving faster than the actual price action suggests it should, the damping logic slows down the progression to maintain stability.
Specialized Market Adjustments
- Gap Compensation: The script includes a specific safeguard for weekend gaps or large jumps in price. If there is a significant time gap between bars where the price "leaps" without continuous trading, the indicator identifies this jump and adjusts its calculations to ensure the trend line remains connected and accurate rather than creating an artificial distortion.
- Customizable Sensitivity: Users can fine-tune the experience via three main variables:
- Length: Controls the responsiveness (shorter lengths react faster).
- Damping: Adjusts the "braking" strength to eliminate overshooting.
- Max Gap: Defines the threshold for identifying and compensating for price jumps.
Summary for the User
In practical terms, this indicator behaves like a smart trend-follower. It ignores the "jitter" of the market but leans into significant moves, providing a cleaner line that helps traders identify the underlying direction of the currency pair without being distracted by minor fluctuations.
/*
*** Morris MA ***
Version 2 (29th May 2004)
** forex version **
use short duration bars e.g.
5min set length to give required speed of response
increase damping to eliminate overshooting
Lower length will require Higher damping
*/
//+##################################################################+
//| MMA.mq4 |
//| Copyright © 2003,2004 Tim Morris |
//| |
//| MQL4 © 2005, Nikolay Kositsin |
//| Khabarovsk |
//+##################################################################+
#property copyright ""
#property link ""
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- input parameters
extern int Length = 10;//inverse of driving coefficient
extern int damping = 5;//smoothing (percent)
extern int maxgap = 30;//maximum week gap ignored (pips)
extern int Shift = 0;
extern int CountBars = 300;//drawn per call - tune this to avoid
//---- buffers
double MMA_Buffer [];
double MEM[32];
//----
double p=0.0, dmp=0.0, drv=0.0, gap=0.0;
double n=0.0, k=0.0, d0=0.0, y0=0.0, y1=0.0, y2=0.0, mg=0.0, err=0.0;
//+==================================================================+
//| Custom indicator initialization function |
//+==================================================================+
int init()
{
string short_name;
//---- drawing settings
SetIndexStyle(0,DRAW_LINE);
SetIndexDrawBegin(0, Bars-CountBars);
//---- IndexShift
SetIndexShift(0,Shift);
//----
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
//---- name for DataWindow and indicator subwindow label
SetIndexLabel (0, "Moris_MA");
IndicatorShortName ("Moris_MA (Length="+Length+", damping="+damping+", maxgap="+maxgap+", Shift="+Shift+")");
//---- indicator buffers mapping
IndicatorBuffers(2);
SetIndexBuffer(0, MMA_Buffer);
SetIndexBuffer(1, MEM);
k =1.0/Length; d0 = damping/100.0; mg = maxgap*Point;
return(0);
}
//+==================================================================+
//| MMA |
//+==================================================================+
int start()
{
int counted_bars=IndicatorCounted();
//---- check for possible errors
if(counted_bars<0) return(-1);
int bar=Bars-counted_bars-1;
if (bar==Bars-1)
{
bar=bar-1;
y0=(High[bar]+Low[bar])/2;
MMA_Buffer[bar]=y0;
MEM[bar+0]=y0;
MEM[bar+1]=y0;
MEM[bar+2]=y0;
bar--;
}
while (bar>=0)
{
p=(High[bar]+Low[bar])/2.0;
//week} gap compensation------------------------------------------+
if (bar>0&& bar<Bars-1)
if (Time[bar]-Time[bar+1]>30000)
if ((High[bar]<Low[bar+1])||(Low[bar]>High[bar+1]))
{
gap=p-(High[bar+1]+Low[bar+1])/2.0;
if (MathAbs(gap)>mg){MEM[bar+1]+=gap; MEM[bar+2]+=gap;}
}
//----------------------------------------------------------------+
//*** calculate new average position ***
y1 = MEM[bar+1];
y2 = MEM[bar+2];
n = High[bar]-Low[bar];//consider H-L as noise level
if(n==0)n=Point/100;
err = (p-2.0*y1+y2)/n;
//error is difference between price && straight line
drv = MathMax(MathMin(k*err*err + k*MathAbs(err),0.5),0.0);
//driving function = polynomial of error/noise
//small moves have little effect,
//big moves have big effect,
//spikes have small effect
dmp = MathMax(MathMin(k*MathAbs(y1-y2)/n + d0,1.0),0.0);
//damping function = polynomial of gradient/noise
//if average is moving fast but price isn't - put the brakes on.
y0 = y1 + n*err*drv + (y1-y2)*(1.0-dmp);
//new average = straight line less damping plus driving
MEM[bar+0]=y0;
MMA_Buffer[bar]=y0;
bar--;
}
//---- done---
return(0);
}
Comments