MAMA_v1MTFsig_alert
Download scriptOverview of MAMA_v1 Logic
This script is a sophisticated technical analysis tool designed to track market trends and provide visual signals for potential trading entries. It primarily utilizes the MAMA (MESA Adaptive Moving Average) and its companion, the FAMA (Fractal Adaptive Moving Average).
Unlike standard moving averages that apply a fixed speed to price data, this logic is "adaptive." This means it automatically adjusts its sensitivity based on the current market environment—speeding up when the market is trending to reduce lag, and slowing down when the market is volatile or consolidating to filter out "noise."
Core Functional Components
1. Dynamic Price Selection
The tool allows users to choose exactly which price data point it should monitor. While most traders use the standard "Close" price, this script provides 11 different options, including:
- Basic Metrics: High, Low, Open, and Close prices.
- Calculated Averages: Median (High+Low)/2, Typical (High+Low+Close)/3, and Weighted Close.
- Heiken Ashi Data: Options to pull specific data points from Heiken Ashi candles, which are often used to smooth out price action.
2. The Adaptive Engine
The internal logic performs several complex mathematical steps to determine the "speed" of the trend:
- Smoothing and Detrending: It first smooths the chosen price and then applies a "detrending" process. This helps the script isolate the core movement of the market from random fluctuations.
- Cycle Analysis: The script calculates the period and phase of the price movement using trigonometric calculations. By analyzing these cycles, it determines how fast the trend is changing.
- Adaptive Alpha Calculation: Based on the cycle analysis, the script calculates a dynamic "Alpha" value. This value dictates how much weight to give to the newest price information versus historical data.
3. MAMA and FAMA Lines
- MAMA: This is the primary adaptive moving average that follows the price closely while trying to maintain smoothness.
- FAMA: This is a secondary, even smoother line derived from the MAMA. It acts as a "slow" filter. When the MAMA moves away from the FAMA, it often indicates the strengthening of a trend.
4. Signal Generation and Alerts
The script includes an optional "Signal Mode" that automatically identifies trend shifts:
- Trend Detection: The logic monitors the relationship between the MAMA and FAMA. If the MAMA crosses over the FAMA in a specific direction, the system recognizes a change in trend (Bullish or Bearish).
- Visual Cues: When a trend shift is detected, the script places specific arrow icons on the chart to highlight the entry point.
- Notifications: Users can enable sound alerts and visual warnings that trigger specifically when these trend shifts occur, ensuring that traders do not have to watch the screen constantly to catch a move.
5. Multi-Timeframe Capabilities
A key feature of this script is its ability to handle different timeframes simultaneously. It can calculate data from higher timeframes (like Daily or Weekly) and project that information onto a smaller, lower timeframe chart (like 1-minute or 5-minute). This allows a trader to see the "big picture" trend while looking at very granular price movements.
//+------------------------------------------------------------------+
//| MAMA_v1.mq4 |
//| Copyright © 2009, TrendLaboratory |
//| http://finance.groups.yahoo.com/group/TrendLaboratory |
//| E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
//mod
// 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_chart_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 = 0; //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 = 0; //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_LINE);
SetIndexStyle(2,DRAW_ARROW);
SetIndexArrow(2,159);
SetIndexStyle(3,DRAW_ARROW);
SetIndexArrow(3,159);
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(5);
SetIndexBuffer(0,MAMA);
SetIndexBuffer(1,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] - 0.5*iATR(NULL,TimeFrame,10,mBars-y-1);
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] + 0.5*iATR(NULL,TimeFrame,10,mBars-y-1);
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];
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];
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