//+------------------------------------------------------------------+
//|   #MAMA_v2.mq4
//+------------------------------------------------------------------+
#include <stdlib.mqh>
#property indicator_chart_window
#property indicator_buffers 2

extern int priceType = 4;
extern double FastLimit = 0.5;
extern double SlowLimit = 0.05;
extern color fastColor = Blue;
extern color slowColor = Crimson;
extern int width = 2;

double FABuffer[];
double MABuffer[];

double jI,jQ,DeltaPhase,alpha,ttime; 

double Price[]; 
double Smooth[]; 
double Detrender[]; 
double Q1[]; 
double I1[]; 
double I2[]; 
double Q2[];
double Re[]; 
double Im[]; 
double SmoothPeriod[];
double Period_[]; 
double Phase[];
double MAMA[]; 
double FAMA[];

int OldTime;

int init()
{
   SetIndexStyle(0,DRAW_LINE,0,width,fastColor);
   SetIndexBuffer(0,FABuffer);
   SetIndexLabel(0,"#FAMA");

   SetIndexBuffer(1,MABuffer);
   SetIndexStyle(1,DRAW_LINE,0,width,slowColor);
   SetIndexLabel(1,"#MAMA");

   SetIndexDrawBegin(0,50);
   SetIndexDrawBegin(1,50);
   
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));

   return(0);
}

int start()
{
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   int limit = Bars-counted_bars;

   if (Time[0] != OldTime) {ResizeArrays(); OldTime = Time[0];}
      
   for (int i=limit;i>=0;i--)
   {
      Price[i] = iMA(NULL,0,1,0,MODE_SMA,priceType,i);

      Smooth[i] = (4*Price[i] + 3*Price[i+1] + 2*Price[i+2] + Price[i+3]) / 10; 

      Detrender[i] = (0.0962*Smooth[i] + 0.5769*Smooth[i+2] - 0.5769*Smooth[i+4] - 
                     0.0962*Smooth[i+6])*(0.075*Period_[i+1] + 0.54); 

      // {Compute InPhase and Quadrature components} 
      Q1[i] = (0.0962*Detrender[i] + 0.5769*Detrender[i+2] - 0.5769*Detrender[i+4] - 
              0.0962*Detrender[i+6])*(0.075*Period_[i+1] + 0.54); 
      I1[i] = Detrender[i+3]; 

      // {Advance the phase of I1 and Q1 by 90 degrees} 
      jI = (0.0962*I1[i] + 0.5769*I1[i+2] - 0.5769*I1[i+4] - 0.0962*I1[i+6])*
          (0.075*Period_[i+1] + 0.54); 

      jQ = (0.0962*Q1[i] + 0.5769*Q1[i+3] - 0.5769*Q1[i+4] - 0.0962*Q1[i+6])*
          (0.075*Period_[i+1] + 0.54); 

      // {Phasor addition for 3 bar averaging)} 
      I2[i] = I1[i] - jQ; 
      Q2[i] = Q1[i] + jI; 

      // {Smooth the I and Q components before applying the discriminator} 
      I2[i] = 0.2*I2[i] + 0.8*I2[i+1]; 
      Q2[i] = 0.2*Q2[i] + 0.8*Q2[i+1]; 

      // {Homodyne Discriminator} 
      Re[i] = I2[i]*I2[i+1] + Q2[i]*Q2[i+1]; 
      Im[i] = I2[i]*Q2[i+1] - Q2[i]*I2[i+1]; 
      Re[i] = 0.2*Re[i] + 0.8*Re[i+1]; 
      Im[i] = 0.2*Im[i] + 0.8*Im[i+1]; 

      if (!CompareDoubles(Im[i],0) && !CompareDoubles(Re[i],0))
      {
         Period_[i] = 360 / (180/3.14159) * MathArctan(Im[i]/Re[i]);
      }
         
      if (Period_[i] > 1.5*Period_[i+1]) 
      {
         Period_[i] = 1.5*Period_[i+1]; 
      }
      
      if (Period_[i] < 0.67*Period_[i+1])
      {
         Period_[i] = 0.67*Period_[i+1]; 
      }
         
      if (Period_[i] < 6)
      { 
         Period_[i] = 6; 
      }

      if (Period_[i] > 50)
      {
         Period_[i] = 50; 
      }
      
      Period_[i] = 0.2*Period_[i] + 0.8*Period_[i+1]; 
      SmoothPeriod[i] = 0.33*Period_[i] + 0.67*SmoothPeriod[i+1]; 

      if (!CompareDoubles(I1[i],0))
      {
         Phase[i] = (MathArctan(Q1[i] / I1[i])); 
      }

      DeltaPhase = Phase[i+1] - Phase[i]; 

      if(DeltaPhase < 1)
      { 
         DeltaPhase = 1; 
      }
      
      alpha = FastLimit / DeltaPhase; 

      if(alpha < SlowLimit)
      {  
         alpha = SlowLimit; 
      }

      MAMA[i] = alpha*Price[i] + (1 - alpha)*MAMA[i+1]; 
      FAMA[i] = 0.5*alpha*MAMA[i] + (1 - 0.5*alpha)*FAMA[i+1]; 

      FABuffer[i] = MAMA[i];
      MABuffer[i] = FAMA[i];

   }
   return(0);
}

int ResizeArrays()
{
   ArraySetAsSeries(Price, true); ArrayResize(Price, Bars); ArraySetAsSeries(Price, false);
   ArraySetAsSeries(Smooth, true); ArrayResize(Smooth, Bars); ArraySetAsSeries(Smooth, false);
   ArraySetAsSeries(Detrender, true); ArrayResize(Detrender, Bars); ArraySetAsSeries(Detrender, false);
   ArraySetAsSeries(Q1, true); ArrayResize(Q1, Bars); ArraySetAsSeries(Q1, false);
   ArraySetAsSeries(I1, true); ArrayResize(I1, Bars); ArraySetAsSeries(I1, false);
   ArraySetAsSeries(I2, true); ArrayResize(I2, Bars); ArraySetAsSeries(I2, false);
   ArraySetAsSeries(Q2, true); ArrayResize(Q2, Bars); ArraySetAsSeries(Q2, false);
   ArraySetAsSeries(Re, true); ArrayResize(Re, Bars); ArraySetAsSeries(Re, false);
   ArraySetAsSeries(Im, true); ArrayResize(Im, Bars); ArraySetAsSeries(Im, false);
   ArraySetAsSeries(SmoothPeriod, true); ArrayResize(SmoothPeriod, Bars); ArraySetAsSeries(SmoothPeriod, false);
   ArraySetAsSeries(Period_, true); ArrayResize(Period_, Bars); ArraySetAsSeries(Period_, false);
   ArraySetAsSeries(Phase, true); ArrayResize(Phase, Bars); ArraySetAsSeries(Phase, false);
   ArraySetAsSeries(MAMA, true); ArrayResize(MAMA, Bars); ArraySetAsSeries(MAMA, false);
   ArraySetAsSeries(FAMA, true); ArrayResize(FAMA, Bars); ArraySetAsSeries(FAMA, false);
   
   return(0);
}
/*
   If CurrentBar > 5 then begin
         Smooth = (4*Price + 3*Price[1] + 2*Price[2] + Price[3]) / 10;
         Detrender = (.0962*Smooth + .5769*Smooth[2] - .5769*Smooth[4]         -
   .0962*Smooth[6])*(.075*Period[1] + .54);
         {Compute InPhase and Quadrature components}
         Q1 = (.0962*Detrender + .5769*Detrender[2]      -  .5769*Detrender[4] -
   .0962*Detrender[6])*(.075*Period[1] + .54);
         I1 = Detrender[3];
         {Advance the phase of I1 and Q1 by 90 degrees}
         jI     =     (.0962*I1     +     .5769*I1[2]     -     .5769*I1[4]    -
   .0962*I1[6])*(.075*Period[1] + .54);
         jQ     =     (.0962*Q1     +     .5769*Q1[2]     -     .5769*Q1[4]    -
   .0962*Q1[6])*(.075*Period[1] + .54);
         {Phasor addition for 3 bar averaging)}
         I2 = I1 - jQ;
         Q2 = Q1 + jI;
         {Smooth the I and Q components before applying the discriminator}
         I2 = .2*I2 + .8*I2[1];
         Q2 = .2*Q2 + .8*Q2[1];
         {Homodyne Discriminator}
         Re = I2*I2[1] + Q2*Q2[1];
         Im = I2*Q2[1] - Q2*I2[1];
         Re = .2*Re + .8*Re[1];
         Im = .2*Im + .8*Im[1];
         If Im <> 0 and Re <> 0 then Period = 360/ArcTangent(Im/Re);
         If Period > 1.5*Period[1] then Period = 1.5*Period[1];
         If Period < .67*Period[1] then Period = .67*Period[1];
         If Period < 6 then Period = 6;
         If Period > 50 then Period = 50;
         Period = .2*Period + .8*Period[1];
         SmoothPeriod = .33*Period + .67*SmoothPeriod[1];
         If I1 <> 0 then Phase = (ArcTangent(Q1 / I1));
         DeltaPhase = Phase[1] - Phase;
         If DeltaPhase < 1 then DeltaPhase = 1;
         alpha = FastLimit / DeltaPhase;
         If alpha < SlowLimit then alpha = SlowLimit;
         MAMA = alpha*Price + (1 - alpha)*MAMA[1];
         FAMA = .5*alpha*MAMA + (1 - .5*alpha)*FAMA[1];
         Plot1(MAMA, \u201cMAMA\u201d);
         Plot2(FAMA, \u201cFAMA\u201d);
*/         

