This script is a specialized technical indicator designed to analyze price action by identifying cyclical patterns and underlying periodicities in the market. Rather than simply looking at raw price movements, it utilizes a complex mathematical approach involving "detrending" and "phasor addition" to isolate recurring waves from general market noise.
Core Logic Overview
The logic operates through several sequential processing stages:
1. Data Smoothing and Detrending The script begins by calculating a baseline "Price" for every bar, derived from the high and low values. It then applies a weighted smoothing process to this data to reduce immediate volatility. From there, it performs "Detrending," which is a mathematical method used to strip away long-term trends (the general direction of the market) to reveal the underlying cycles or oscillations that remain.
2. Component Decomposition (In-Phase and Quadrature) Once the trend is removed, the script breaks down the remaining data into two distinct components:
- In-Phase: Representing the primary movement of the cycle.
- Quadrature: Representing the movement at a 90-degree phase shift relative to the primary movement.
By splitting the data this way, the script can analyze the "rotation" of the market cycle more accurately, similar to how complex waves are analyzed in physics or signal processing.
3. Phasor Addition and Averaging The script combines these components using a technique called "Phasor Addition." This allows it to average out movements over a three-bar window. It ensures that the resulting data isn't just reacting to a single price tick but is instead reflecting a broader, more stable cyclical movement.
4. Periodicity Detection and Filtering The final stage of the logic calculates the "Period"—the length of time it takes for a specific cycle to complete. To ensure the indicator remains reliable and doesn't produce erratic results, it applies several safety filters:
- It smooths the detected period over time to prevent sudden jumps.
- It enforces boundaries (minimum and maximum limits) so that the detected cycles stay within a logically consistent range for trading.
Summary of Purpose
The goal of this logic is to provide a cleaner view of market "heartbeats." By filtering out the noise, removing the dominant trend, and calculating the recurring period of price oscillations, it helps identify the underlying rhythmic behavior of the asset being traded.
//+------------------------------------------------------------------+
//| MAMA_Slave.mq4 |
//| Copyright © 2007, MetaQuotes Software Corp. |
//| http://www.metaquotes.ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link "http://www.metaquotes.ru/"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
//---- input parameters
extern double FastLimit=0.5;
extern double SlowLimit=0.05;
//---- buffers
double jI[];
double jQ[];
double I2[];
double Q1[];
double Q2[];
double PeriodD[];
double Re[];
double Im[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
IndicatorBuffers(8);
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,I2);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,Q2);
SetIndexBuffer(2,Re);
SetIndexBuffer(3,Im);
SetIndexBuffer(4,jQ);
SetIndexBuffer(5,jI);
SetIndexBuffer(6,Q1);
SetIndexBuffer(7,PeriodD);
SetIndexEmptyValue(0,0);
SetIndexEmptyValue(1,0);
SetIndexEmptyValue(2,0);
SetIndexEmptyValue(3,0);
SetIndexEmptyValue(4,0);
SetIndexEmptyValue(5,0);
SetIndexEmptyValue(6,0);
SetIndexEmptyValue(7,0);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| âû÷èñëèòü ìåäèàíó äëÿ áàðà ñ èíäåêñîì index |
//+------------------------------------------------------------------+
double Price(int index)
{
double res;
//----
res=(High[index]+Low[index])/2.0;
//----
return(res);
}
//+------------------------------------------------------------------+
//| âû÷èñëèòü Smooth äëÿ áàðà ñ èíäåêñîì i |
//+------------------------------------------------------------------+
double Smooth(int i)
{
double res;
//----
res=(4*Price(i)+3*Price(i+1)+2*Price(i+2)+Price(i+3))/10.0;
//----
return(res);
}
//+------------------------------------------------------------------+
//| âûñèëèòü Detrender æäÿ äàííîãî áàðà ñ çàäàííûì |
//+------------------------------------------------------------------+
double Detrender(int i, double PeriodDD[])
{
double res;
//----
res=(0.0962*Smooth(i)+0.5769*Smooth(i+2)-0.5769*Smooth(i+4)-0.0962*Smooth(i+6))*(0.075*PeriodDD[i+1]+0.54);
//----
return(res);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int i,limit,limit2,limit3,limit4,counted_bars=IndicatorCounted();
double tempI2,tempQ2,tempRe,tempIm;
//----
if (counted_bars>0)
{
limit=Bars-counted_bars;
limit2=limit;
limit3=limit;
limit4=limit3;
}
if (counted_bars==0)
{
limit=Bars-4;
limit2=limit-7;
limit3=limit2-7;
limit4=limit3-10;
}
/*
for (i=limit;i>=0;i--)
{
Smooth[i]=(4*Price(i)+3*Price(i+1)+2*Price(i+2)+Price(i+3))/10.0;
}
for (i=limit2;i>=0;i--)
{
Detrender[i]=(0.0962*Smooth[i]+0.5769*Smooth[i+2]-0.5769*Smooth[i+4]-0.0962*Smooth[i+6])*(0.075*PeriodD[i+1]+0.54);
}
*/
//{Compute InPhase and Quadrature components}
for (i=limit3;i>=0;i--)
{
Q1[i]=(0.0962*Detrender(i,PeriodD)+0.5769*Detrender(i+2,PeriodD)-0.5769*Detrender(i+4,PeriodD)-0.0962*Detrender(i+6,PeriodD))*(0.075*PeriodD[i+1]+0.54);
//I1[i]=Detrender[i+3];
}
//{Compute InPhase and Quadrature components}
//{Advance the phase of I1 and Q1 by 90 degrees}
for (i=limit4;i>=0;i--)
{
//jI[i]=(0.0962*I1[i]+0.5769*I1[i+2]-0.5769*I1[i+4]-0.0962*I1[i+6])*(0.075*PeriodD[i+1]+0.54);
jI[i]=(0.0962*Detrender(i+3,PeriodD)+0.5769*Detrender(i+5,PeriodD)-0.5769*Detrender(i+7,PeriodD)-0.0962*Detrender(i+9,PeriodD))*(0.075*PeriodD[i+1]+0.54);
jQ[i]=(0.0962*Q1[i]+0.5769*Q1[i+2]-0.5769*Q1[i+4]-0.0962*Q1[i+6])*(0.075*PeriodD[i+1]+0.54);
}
//{Advance the phase of I1 and Q1 by 90 degrees}
// {Phasor addition for 3 bar averaging)}
for (i=limit4;i>=0;i--)
{
//I2[i]=I1[i]-jQ[i];
//I2[i]=Detrender[i+3]-jQ[i];
//Q2[i]=Q1[i]+jI[i];
tempI2=Detrender(i+3,PeriodD)-jQ[i];
tempQ2=Q1[i]+jI[i];
// {Smooth the I and Q components before applying the discriminator}
I2[i]=0.2*tempI2+0.8*I2[i+1];
Q2[i]=0.2*tempQ2+0.8*Q2[i+1];
tempRe=I2[i]*I2[i+1]+Q2[i]*Q2[i+1];
tempIm=I2[i]*Q2[i+1]+Q2[i]*I2[i+1];
Re[i]=0.2*tempRe+0.8*Re[i+1];
Im[i]=0.2*tempIm+0.8*Im[i+1];
if (Im[i]!=0 && Re[i]!=0) PeriodD[i]=2*3.1415/MathArctan(Im[i]/Re[i]);
if (PeriodD[i]>1.5*PeriodD[i+1]) PeriodD[i]=1.5*PeriodD[i+1];
if (PeriodD[i]<0.67*PeriodD[i+1]) PeriodD[i]=0.67*PeriodD[i+1];
if (PeriodD[i]<6) PeriodD[i]=6;
if (PeriodD[i]>50) PeriodD[i]=50;
PeriodD[i]=0.2*PeriodD[i]+0.8*PeriodD[i+1];
}
// {Phasor addition for 3 bar averaging)}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments