MAMA_v1_osc_MTF_alert
Download scriptThis script is a sophisticated technical analysis tool designed to help traders identify trend directions and potential entry points by calculating two dynamic moving averages: the MAMA (Mixed Adaptive Moving Average) and the FAMA (Fractal Adaptive Moving Average).
Core Logic Overview
Unlike standard moving averages that use a fixed period (like a 14-day or 50-day average), this script uses "adaptive" logic. This means the indicator automatically speeds up or slows down its responsiveness based on the current market volatility and price momentum.
The primary goal of this adaptation is to follow trends closely when they are strong and filter out "noise" or minor fluctuations when the market is ranging or choppy.
Key Components of the Calculation
1. Data Input Selection The script allows users to choose which specific price data points it should analyze. You can select standard metrics such as:
- Closing Price
- Opening Price
- High/Low prices
- Median and Typical prices
- Weighted averages
- Heiken Ashi price components (a specialized candlestick smoothing technique)
2. The Adaptive Engine The logic performs several complex mathematical steps to determine the current market state:
- Smoothing & Detrending: It first cleans the raw price data to remove immediate outliers.
- Cycle Analysis: It calculates the "period" of the current market cycle. By identifying how often a trend repeats, it determines if the market is in a fast-moving phase or a slow-moving one.
- Phase & Delta: It tracks the "Phase" (the position within a cycle) and the "Delta Phase" (how much that position has changed).
3. Dynamic Alpha Calculation The script uses these calculations to determine an Alpha value. This value acts as a throttle:
- If the market is changing rapidly, the Alpha adjusts to make the indicator more reactive.
- If the market is stable, the Alpha restricts movement to prevent "whipsaws" (false signals).
4. MAMA and FAMA Relationship
- MAMA: This is the primary adaptive average that reacts directly to the price trends derived from the alpha calculations.
- FAMA: This is a "smoothed" version of the MAMA. It follows the MAMA but with an extra layer of filtering, making it much slower and more stable.
Visual Signals and Alerts
The script translates these mathematical movements into visual cues on your chart:
- Trend Identification: By observing the distance and crossing points between the MAMA and FAMA lines, the indicator shows the prevailing trend.
- Buy/Sell Signals: When the MAMA crosses the FAMA in a specific direction, the script identifies a trend shift.
- Visual Markers: It plots specific arrows on the chart to highlight these "Up" and "Down" signal points.
- Alerts: The script can be configured to trigger sound alerts or pop-up messages on your screen whenever a new trend signal is detected, ensuring you don't have to watch the charts constantly.
Multi-Timeframe Capability
The logic is also designed to handle different timeframes. It can calculate data from a higher timeframe (e.g., looking at the Daily trend) and project those results onto a lower timeframe (e.g., a 15-minute chart), allowing for better context in your trading decisions.
//+------------------------------------------------------------------+
//| MAMA_v1.mq4 |
//| Copyright © 2009, TrendLaboratory |
//| http://finance.groups.yahoo.com/group/TrendLaboratory |
//| E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
//mod osc
// List of Prices:
// Price = 0 - Close
// Price = 1 - Open
// Price = 2 - High
// Price = 3 - Low
// Price = 4 - Median Price = (High+Low)/2
// Price = 5 - Typical Price = (High+Low+Close)/3
// Price = 6 - Weighted Close = (High+Low+Close*2)/4
// Price = 7 - Heiken Ashi Close
// Price = 8 - Heiken Ashi Open
// Price = 9 - Heiken Ashi High
// Price =10 - Heiken Ashi Low
#property copyright "Copyright © 2009, TrendLaboratory"
#property link "http://finance.groups.yahoo.com/group/TrendLaboratory"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Yellow
#property indicator_width1 1
#property indicator_color2 SkyBlue
#property indicator_width2 1
#property indicator_color3 SkyBlue
#property indicator_width3 2
#property indicator_color4 Tomato
#property indicator_width4 2
//----
extern int TimeFrame = 60; //Time Frame in min
extern int Price = 4; //Price Mode (0...10)
extern double FastLimit = 0.5; //Laguerre Period(or Order,max=10)
extern double SlowLimit = 0.05; //Adaptive Factor Length
extern int SignalMode = 1; //Switch of Signal mode(0-off,1-on)
extern int AlertMode = 0; //Sound Alert switch(0...2)
extern int WarningMode = 0; //Warning Mode (0-off,1-on)
extern string note_Price = "0C 1O 2H 3L 4Md 5Tp 6WghC";
extern string _________ = "Md(HL/2)4,Tp(HLC/3)5,Wgh(HLCC/4)6";
extern string HA_price_ = "7haC 8haO 9haH 10haL";
extern string _______ = "haC=(O+H+L+C)/4; haO=(O[i1]+C[i1])/2;haH=Max(H,haO,haC);haL=Min(L,hO,hC)";
extern string TimeFrames = "M1;5,15,30,60H1;240H4;1440D1;10080W1;43200MN";
//----
double MAMA[];
double FAMA[];
double UpSignal[];
double DnSignal[];
double sig[];
//----
double haClose[], haOpen[], haHigh[], haLow[];
int draw_begin, pBars, mcnt_bars, per;
string short_name1, short_name2;
datetime pTime;
bool UpTrendAlert=false, DnTrendAlert=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
SetIndexStyle(0,DRAW_LINE);
// SetIndexStyle(1,DRAW_NONE);
SetIndexStyle(2,DRAW_ARROW);
SetIndexArrow(2,158);
SetIndexStyle(3,DRAW_ARROW);
SetIndexArrow(3,158);
if(TimeFrame == 0 || TimeFrame < Period()) TimeFrame = Period();
per = 2/SlowLimit;
draw_begin=2*per*TimeFrame/Period();
//----
switch(TimeFrame)
{
case 1 : string TF = "M1"; break;
case 5 : TF = "M5"; break;
case 15 : TF = "M15"; break;
case 30 : TF = "M30"; break;
case 60 : TF = "H1"; break;
case 240 : TF ="H4"; break;
case 1440 : TF="D1"; break;
case 10080 : TF="W1"; break;
case 43200 : TF="MN"; break;
default : TF="CurrentTF";
}
short_name1 = "MAMA";
short_name2 = "FAMA";
IndicatorShortName(short_name1+"("+DoubleToStr(FastLimit,2)+","+DoubleToStr(SlowLimit,2)+")"+" "+TF);
SetIndexLabel(0,short_name1+"("+DoubleToStr(FastLimit,2)+","+DoubleToStr(SlowLimit,2)+")"+" "+TF);
SetIndexLabel(1,short_name2+"("+DoubleToStr(FastLimit,2)+","+DoubleToStr(SlowLimit,2)+")"+" "+TF);
SetIndexLabel(2,"UpSignal");
SetIndexLabel(3,"DnSignal");
SetIndexDrawBegin(0,draw_begin);
// SetIndexDrawBegin(1,draw_begin);
SetIndexDrawBegin(2,draw_begin);
SetIndexDrawBegin(3,draw_begin);
//----
IndicatorBuffers(6);
SetIndexBuffer(0,MAMA);
SetIndexBuffer(5,FAMA);
SetIndexBuffer(2,UpSignal);
SetIndexBuffer(3,DnSignal);
SetIndexBuffer(4,sig);
//----
return(0);
}
//+------------------------------------------------------------------+
//| MAMA_v1 |
//+------------------------------------------------------------------+
int start()
{
int limit, y, i, shift, cnt_bars=IndicatorCounted();
double price[], mMAMA[], mFAMA[], Smooth[], Detrender[], Q1[], I1[], JL[], JQ[], I2[], Q2[],
Re[], Im[], period[], Phase[], mUpsig[], mDnsig[], trend[];
if(TimeFrame!=Period()) int mBars = iBars(NULL,TimeFrame); else mBars = Bars;
if(mBars != pBars)
{
ArrayResize(price,mBars);
ArrayResize(mMAMA,mBars);
ArrayResize(mFAMA,mBars);
ArrayResize(Smooth,mBars);
ArrayResize(Detrender,mBars);
ArrayResize(Q1,mBars);
ArrayResize(I1,mBars);
ArrayResize(JL,mBars);
ArrayResize(JQ,mBars);
ArrayResize(I2,mBars);
ArrayResize(Q2,mBars);
ArrayResize(Re,mBars);
ArrayResize(Im,mBars);
ArrayResize(period,mBars);
ArrayResize(Phase,mBars);
if(Price > 6 && Price <= 10)
{
ArrayResize(haClose,mBars);
ArrayResize(haOpen,mBars);
ArrayResize(haHigh,mBars);
ArrayResize(haLow,mBars);
}
if(SignalMode>0)
{
ArrayResize(trend,mBars);
ArrayResize(mUpsig,mBars);
ArrayResize(mDnsig,mBars);
}
pBars = mBars;
}
if(cnt_bars<1)
{
for(i=Bars-1;i>0;i--)
{
MAMA[i]=EMPTY_VALUE;
FAMA[i]=EMPTY_VALUE;
UpSignal[i]=EMPTY_VALUE;
DnSignal[i]=EMPTY_VALUE;
}
mcnt_bars = 0;
}
//----
if(mcnt_bars > 0) mcnt_bars--;
for(y=mcnt_bars;y<mBars;y++)
{
if(Price <= 6) price[y] = iMA(NULL,TimeFrame,1,0,0,Price,mBars-y-1);
else
if(Price > 6 && Price <= 10) price[y] = HeikenAshi(TimeFrame,Price-7,mBars-y-1);
if(y >= 3) Smooth[y] = (4*price[y] + 3*price[y-1] + 2*price[y-2] + price[y-3])/10.0;
Detrender[y] = (0.0962*Smooth[y] + 0.5769*Smooth[y-2] - 0.5769*Smooth[y-4] - 0.0962*Smooth[y-6])*(0.075*period[y-1] + 0.54);
Q1[y] = (0.0962*Detrender[y] + 0.5769*Detrender[y-2] - 0.5769*Detrender[y-4] - 0.0962*Detrender[y-6])*(0.075*period[y-1] + 0.54);
I1[y] = Detrender[y-3];
JL[y] = (0.0962*I1[y] + 0.5769*I1[y-2] - 0.5769*I1[y-4] - 0.0962*I1[y-6])*(0.075*period[y-1] + 0.54);
JQ[y] = (0.0962*Q1[y] + 0.5769*Q1[y-2] - 0.5769*Q1[y-4] - 0.0962*Q1[y-6])*(0.075*period[y-1] + 0.54);
I2[y] = I1[y] - JQ[y];
Q2[y] = Q1[y] + JL[y];
I2[y] = 0.2*I2[y] + 0.8*I2[y-1];
Q2[y] = 0.2*Q2[y] + 0.8*Q2[y-1];
Re[y] = I2[y]*I2[y-1] + Q2[y]*Q2[y-1];
Im[y] = I2[y]*Q2[y-1] - Q2[y]*I2[y-1];
Re[y] = 0.2*Re[y] + 0.8*Re[y-1];
Im[y] = 0.2*Im[y] + 0.8*Im[y-1];
double rad2Deg = 45.0/MathArctan(1);
if(Im[y] != 0 && Re[y] != 0) period[y] = 360.0/MathArctan(Im[y]/Re[y])/rad2Deg;
if(period[y] > 1.5 *period[y-1]) period[y] = 1.5*period[y-1];
if(period[y] < 0.67*period[y-1]) period[y] = 0.67*period[y-1];
if(period[y] < 6) period[y] = 6;
if(period[y] > 50) period[y] = 50;
period[y] = 0.2*period[y] + 0.8*period[y-1];
if(I1[y] != 0) Phase[y] = MathArctan(Q1[y]/I1[y])*rad2Deg;
double DeltaPhase = Phase[y-1] - Phase[y];
if(DeltaPhase < 1) DeltaPhase = 1;
double Alpha = FastLimit / DeltaPhase;
if(Alpha < SlowLimit) Alpha = SlowLimit;
if(Alpha > FastLimit) Alpha = FastLimit;
mMAMA[y] = Alpha*price[y] + (1.0 - Alpha)*mMAMA[y-1];
mFAMA[y] = 0.5*Alpha*mMAMA[y] + (1.0 - 0.5*Alpha)*mFAMA[y-1];
if(SignalMode > 0)
{
trend[y] = trend[y-1];
if(mFAMA[y]-mMAMA[y] < 0 && trend[y-1]<=0) trend[y]= 1;
if(mFAMA[y]-mMAMA[y] > 0 && trend[y-1]>=0) trend[y]=-1;
if(trend[y] > 0)
{
if(trend[y-1] <= 0)
{
mUpsig[y] = mFAMA[y]-mMAMA[y];
if (WarningMode>0 && y==mBars-1) PlaySound("alert2.wav");
}
else
mUpsig[y]= EMPTY_VALUE;
mDnsig[y]= EMPTY_VALUE;
}
else
if (trend[y] < 0)
{
if(trend[y-1] >= 0)
{
mDnsig[y] =mFAMA[y]-mMAMA[y];
if (WarningMode>0 && y==mBars-1) PlaySound("alert2.wav");
}
else
mDnsig[y]= EMPTY_VALUE;
mUpsig[y]= EMPTY_VALUE;
}
}
if(TimeFrame == Period())
{
MAMA[mBars-y-1] = mMAMA[y]-mFAMA[y];
FAMA[mBars-y-1] = mFAMA[y];
if(SignalMode > 0)
{
UpSignal[mBars-y-1] = mUpsig[y];
DnSignal[mBars-y-1] = mDnsig[y];
}
}
mcnt_bars = mBars-1;
}
if(TimeFrame > Period())
{
if(cnt_bars>0) cnt_bars--;
limit = Bars-cnt_bars+TimeFrame/Period()-1;
for(shift=0,y=0;shift<limit;shift++)
{
if (Time[shift] < iTime(NULL,TimeFrame,y)) y++;
MAMA[shift] = mMAMA[mBars-y-1]-mFAMA[mBars-y-1];
FAMA[shift] = mFAMA[mBars-y-1];
if(SignalMode > 0)
{
UpSignal[shift] = mUpsig[mBars-y-1];
DnSignal[shift] = mDnsig[mBars-y-1];
sig[mBars-y-1] = trend[y];
}
}
}
//----------
string Message;
if (trend[mBars-2]<0 && trend[mBars-1]>0 && !UpTrendAlert && AlertMode == 1)
{
Message = " "+Symbol()+" TF M"+TimeFrame+" chart M"+Period()+": MAMA Signal for BUY";
if (isNewBar()) Alert (Message);
UpTrendAlert=true; DnTrendAlert=false;
}
else
if (trend[mBars-2]>0 && trend[mBars-1]<0 && !DnTrendAlert && AlertMode == 1)
{
Message = " "+Symbol()+" TF M"+TimeFrame+" chart M"+Period()+": MAMA Signal for SELL";
if (isNewBar()) Alert (Message);
DnTrendAlert=true; UpTrendAlert=false;
}
return(0);
}
double HeikenAshi(int tf,int price,int bar)
{
if(bar == iBars(NULL,TimeFrame)- 1)
{
haClose[bar] = iClose(NULL,tf,bar);
haOpen[bar] = iOpen(NULL,tf,bar);
haHigh[bar] = iHigh(NULL,tf,bar);
haLow[bar] = iLow(NULL,tf,bar);
}
else
{
haClose[bar] = (iOpen(NULL,tf,bar)+iHigh(NULL,tf,bar)+iLow(NULL,tf,bar)+iClose(NULL,tf,bar))/4;
haOpen[bar] = (haOpen[bar+1]+haClose[bar+1])/2;
haHigh[bar] = MathMax(iHigh(NULL,tf,bar),MathMax(haOpen[bar], haClose[bar]));
haLow[bar] = MathMin(iLow(NULL,tf,bar),MathMin(haOpen[bar], haClose[bar]));
}
switch(price)
{
case 0: return(haClose[bar]);break;
case 1: return(haOpen[bar]);break;
case 2: return(haHigh[bar]);break;
case 3: return(haLow[bar]);break;
}
}
bool isNewBar()
{
bool res=false;
if (iTime(NULL,TimeFrame,0)!=pTime)
{
res=true;
pTime=iTime(NULL,TimeFrame,0);
}
return(res);
}
Comments