Ehler's MAMA Buy and Sell Signals Indicator for ThinkorSwim

BenTen

Administrative
Staff
VIP
Lifetime
This is the MAMA and FAMA indicator by John Ehlers. Testing on SPY and few other stocks and it is highly accurate on the certain timeframes and works best with SPY.

It will show MAMA: BEAR as an indication to sell and MAMA: BULL to indicate Bullish move. It was originally made to trade /ES.

The indicator performs worst in times of CHOP. So I would use a choppy indicator to indicate choppiness in the market and avoid taking any trades during that time.

Good Stuff: Overall if you trade(On sell trades) SPY on 2D 5M chart with will end up making roughly ~ $200. Lets not forget its simulation and not real trades

qb8f8eo.png


thinkScript Code

Rich (BB code):
# Here is Ehler's MAMA:
# hint: <b>Ehler's Mesa Adaptive Moving Average</b> using Ray's clean version
# of the homodyne discriminator.
#

# MIT License
# Copyright (c) <2010> <Radford Juang>
#
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
#

script WMA_Smooth {
    input price = hl2;
    plot smooth = (4 * price
+ 3 * price[1]
+ 2 * price[2]
+ price[3]) / 10;
}

script Phase_Accumulation {
# This is Ehler's Phase Accumulation code. It has a full cycle delay.
# However, it computes the correction factor to a very high degree.
#
    input price = hl2;

    rec Smooth;
    rec Detrender;
    rec Period;
    rec Q1;
    rec I1;
    rec I1p;
    rec Q1p;
    rec Phase1;
    rec Phase;
    rec DeltaPhase;
    rec DeltaPhase1;
    rec InstPeriod1;
    rec InstPeriod;
    def CorrectionFactor;

    if barNumber() <= 5
    then {
        Period = 0;
        Smooth = 0;
        Detrender = 0;
        CorrectionFactor = 0;
        Q1 = 0;
        I1 = 0;
        Q1p = 0;
        I1p = 0;
        Phase = 0;
        Phase1 = 0;
        DeltaPhase1 = 0;
        DeltaPhase = 0;
        InstPeriod = 0;
        InstPeriod1 = 0;
    } else {
        CorrectionFactor = 0.075 * Period[1] + 0.54;

# Smooth and detrend my smoothed signal:
        Smooth = WMA_Smooth(price);
        Detrender = ( 0.0962 * Smooth
+ 0.5769 * Smooth[2]
- 0.5769 * Smooth[4]
- 0.0962 * Smooth[6] ) * CorrectionFactor;

# Compute Quadrature and Phase of Detrended signal:
        Q1p = ( 0.0962 * Detrender
+ 0.5769 * Detrender[2]
- 0.5769 * Detrender[4]
- 0.0962 * Detrender[6] ) * CorrectionFactor;
        I1p = Detrender[3];

# Smooth out Quadrature and Phase:
        I1 = 0.15 * I1p + 0.85 * I1p[1];
        Q1 = 0.15 * Q1p + 0.85 * Q1p[1];

# Determine Phase
        if I1 != 0
        then {
# Normally, ATAN gives results from -pi/2 to pi/2.
# We need to map this to circular coordinates 0 to 2pi

            if Q1 >= 0 and I1 > 0
            then { # Quarant 1
                Phase1 = ATan(AbsValue(Q1 / I1));
            } else if Q1 >= 0 and I1 < 0
            then { # Quadrant 2
                Phase1 = Double.Pi - ATan(AbsValue(Q1 / I1));
            } else if Q1 < 0 and I1 < 0
            then { # Quadrant 3
                Phase1 = Double.Pi + ATan(AbsValue(Q1 / I1));
            } else { # Quadrant 4
                Phase1 = 2 * Double.Pi - ATan(AbsValue(Q1 / I1));
            }
        } else if Q1 > 0
        then { # I1 == 0, Q1 is positive
            Phase1 = Double.Pi / 2;
        } else if Q1 < 0
        then { # I1 == 0, Q1 is negative
            Phase1 = 3 * Double.Pi / 2;
        } else { # I1 and Q1 == 0
            Phase1 = 0;
        }

# Convert phase to degrees
        Phase = Phase1 * 180 / Double.Pi;

        if Phase[1] < 90 and Phase > 270
        then {
# This occurs when there is a big jump from 360-0
            DeltaPhase1 = 360 + Phase[1] - Phase;
        } else {
            DeltaPhase1 = Phase[1] - Phase;
        }

# Limit our delta phases between 7 and 60
        if DeltaPhase1 < 7
        then {
            DeltaPhase = 7;
        } else if DeltaPhase1 > 60
        then {
            DeltaPhase = 60;
        } else {
            DeltaPhase = DeltaPhase1;
        }

# Determine Instantaneous period:
        InstPeriod1 =
-1 * (fold i = 0 to 40 with v=0 do
if v < 0 then
v
else if v > 360 then
-i
else
v + GetValue(DeltaPhase, i, 41)
);

        if InstPeriod1 <= 0
        then {
            InstPeriod = InstPeriod[1];
        } else {
            InstPeriod = InstPeriod1;
        }

        Period = 0.25 * InstPeriod + 0.75 * Period[1];
    }
    plot DC = Period;
}

script Ehler_MAMA {
    input price = hl2;
    input FastLimit = 0.5;
    input SlowLimit = 0.05;


    rec Period;
    rec Period_raw;
    rec Period_cap;
    rec Period_lim;

    rec Smooth;
    rec Detrender;
    rec I1;
    rec Q1;
    rec jI;
    rec jQ;
    rec I2;
    rec Q2;
    rec I2_raw;
    rec Q2_raw;

    rec Phase;
    rec DeltaPhase;
    rec DeltaPhase_raw;
    rec alpha;
    rec alpha_raw;

    rec Re;
    rec Im;
    rec Re_raw;
    rec Im_raw;

    rec SmoothPeriod;
    rec vmama;
    rec vfama;

    def CorrectionFactor = Phase_Accumulation(price).CorrectionFactor;

    if barNumber() <= 5
    then {
        Smooth = 0;
        Detrender = 0;

        Period = 0;
        Period_raw = 0;
        Period_cap = 0;
        Period_lim = 0;
        I1 = 0;
        Q1 = 0;
        I2 = 0;
        Q2 = 0;
        jI = 0;
        jQ = 0;
        I2_raw = 0;
        Q2_raw = 0;
        Re = 0;
        Im = 0;
        Re_raw = 0;
        Im_raw = 0;
        SmoothPeriod = 0;
        Phase = 0;
        DeltaPhase = 0;
        DeltaPhase_raw = 0;
        alpha = 0;
        alpha_raw = 0;
        vmama = 0;
        vfama = 0;
    } else {
# Smooth and detrend my smoothed signal:
        Smooth = WMA_Smooth(price);
        Detrender = ( 0.0962 * Smooth
+ 0.5769 * Smooth[2]
- 0.5769 * Smooth[4]
- 0.0962 * Smooth[6] ) * CorrectionFactor;

        Q1 = ( 0.0962 * Detrender
+ 0.5769 * Detrender[2]
- 0.5769 * Detrender[4]
- 0.0962 * Detrender[6] ) * CorrectionFactor;
        I1 = Detrender[3];

        jI = ( 0.0962 * I1
+ 0.5769 * I1[2]
- 0.5769 * I1[4]
- 0.0962 * I1[6] ) * CorrectionFactor;

        jQ = ( 0.0962 * Q1
+ 0.5769 * Q1[2]
- 0.5769 * Q1[4]
- 0.0962 * Q1[6] ) * CorrectionFactor;

# This is the complex conjugate
        I2_raw = I1 - jQ;
        Q2_raw = Q1 + jI;

        I2 = 0.2 * I2_raw + 0.8 * I2_raw[1];
        Q2 = 0.2 * Q2_raw + 0.8 * Q2_raw[1];

        Re_raw = I2 * I2[1] + Q2 * Q2[1];
        Im_raw = I2 * Q2[1] - Q2 * I2[1];

        Re = 0.2 * Re_raw + 0.8 * Re_raw[1];
        Im = 0.2 * Im_raw + 0.8 * Im_raw[1];

# Compute the phase
        if Re != 0 and Im != 0
        then {
            Period_raw = 2 * Double.Pi / ATan(Im / Re);
        } else {
            Period_raw = 0;
        }

        if Period_raw > 1.5 * Period_raw[1]
        then {
            Period_cap = 1.5 * Period_raw[1];
        } else if Period_raw < 0.67 * Period_raw[1] {
            Period_cap = 0.67 * Period_raw[1];
        } else {
            Period_cap = Period_raw;
        }

        if Period_cap < 6
        then {
            Period_lim = 6;
        } else if Period_cap > 50
        then {
            Period_lim = 50;
        } else {
            Period_lim = Period_cap;
        }

        Period = 0.2 * Period_lim + 0.8 * Period_lim[1];
        SmoothPeriod = 0.33 * Period + 0.67 * SmoothPeriod[1];

        if I1 != 0
        then {
            Phase = ATan(Q1 / I1);
        } else if Q1 > 0
        then { # Quadrant 1:
            Phase = Double.Pi / 2;
        } else if Q1 < 0
        then { # Quadrant 4:
            Phase = -Double.Pi / 2;
        } else { # Both numerator and denominator are 0.
            Phase = 0;
        }

        DeltaPhase_raw = Phase[1] - Phase;
        if DeltaPhase_raw < 1
        then {
            DeltaPhase = 1;
        } else {
            DeltaPhase = DeltaPhase_raw;
        }

        alpha_raw = FastLimit / DeltaPhase;
        if alpha_raw < SlowLimit
        then {
            alpha = SlowLimit;
        } else {
            alpha = alpha_raw;
        }
        vmama = alpha * price + (1 - alpha) * vmama[1];
        vfama = 0.5 * alpha * vmama + (1 - 0.5 * alpha) * vfama[1];
    }

    plot MAMA = vmama;
    plot FAMA = vfama;
}

declare upper;
input price = hl2;
input FastLimit = 0.5;
input SlowLimit = 0.05;

plot MAMA = Ehler_MAMA(price, FastLimit, SlowLimit).MAMA;
plot FAMA = Ehler_MAMA(price, FastLimit, SlowLimit).FAMA;

plot Crossing = Crosses((MAMA < FAMA), yes);
Crossing.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

plot Crossing1 = Crosses((MAMA > FAMA), yes);
Crossing1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

AddLabel(yes, Concat("MAMA: ", Concat("",
if MAMA > FAMA then "Bull" else "Bear")),

if MAMA > FAMA then Color.GREEN else Color.RED);

Shareable Link

https://tos.mx/1BjtpK

mxjCEJ4.png


https://tos.mx/nw7xS1

@jerrydinvestor contributed to this post.
 
Last edited:

DB01

New member
Did anyone come up with a TOS scan for stocks that have an alert signal (buy or sell) from this indy? I'm just looking for stocks where the FAMA has crossed the MAMA in either direction. When I try and build it custom in the TOS scanner custom filter, I get a "Too complex exception" and that the scan is too complex for reliable real time data. All Im asking for is a 2 lines cross, not that complex. Any help?
 

tomsk

Well-known member
VIP
Did anyone come up with a TOS scan for stocks that have an alert signal (buy or sell) from this indy? I'm just looking for stocks where the FAMA has crossed the MAMA in either direction. When I try and build it custom in the TOS scanner custom filter, I get a "Too complex exception" and that the scan is too complex for reliable real time data. All Im asking for is a 2 lines cross, not that complex. Any help?


My assumption is that you're referring to Ben's posted study in post#1 of this thread. Tere are two basic plots therein - FAMA and MAMA. This works very well on a chart study. However because the manner in which the underlying study is derived and written, it is too complex to be used on the scanner. That is why you see the message that the scan is too complex for real time data. That said, there is a workaround alternative.

Stepping back for a moment you'll note that this study parallels a very fast moving average and appears to resemble two fast moving averages. The suggestion that @horserider gave above is a good one. It not only gives you a similar look and feel to the FAMA/MAMA study, but is very simple that it can be scanned with no problems. Hence do try the suggestion made in post # 16
 
Last edited by a moderator:

ranjodhsingh

New member
I didn't put TTM, but someone else could add.

Code:
# Name: MTF Mama
# source:  http://tos.mx/J8iZ0JA
# Author: mcdon030
# added switch as for some reason it's stabilizes MTFs

# OC order http://tos.mx/SHQhQ19

script mama {
    input price = close;
    rec Smooth;
    rec Detrender;
    rec Period;
    rec Q1;
    rec I1;
    rec I1p;
    rec Q1p;
    rec Phase1;
    rec Phase;
    rec DeltaPhase;
    rec DeltaPhase1;
    rec InstPeriod1;
    rec InstPeriod;
    def CorrectionFactor;
    if BarNumber() <= 5
    then {
        Period = 0;
        Smooth = 0;
        Detrender = 0;
        CorrectionFactor = 0;
        Q1 = 0;
        I1 = 0;
        Q1p = 0;
        I1p = 0;
        Phase = 0;
        Phase1 = 0;
        DeltaPhase1 = 0;
        DeltaPhase = 0;
        InstPeriod = 0;
        InstPeriod1 = 0;
    } else {
        CorrectionFactor = 0.075 * Period[1] + 0.54;
        Smooth =   (4 * price + 3 * price[1] + 2 * price[2] + price[3]) / 10;
        Detrender = ( 0.0962 * Smooth + 0.5769 * Smooth[2] - 0.5769 * Smooth[4] - 0.0962 * Smooth[6] ) * CorrectionFactor;
        Q1p = ( 0.0962 * Detrender + 0.5769 * Detrender[2] - 0.5769 * Detrender[4] - 0.0962 * Detrender[6] ) * CorrectionFactor;
        I1p = Detrender[3];
        I1 = 0.15 * I1p + 0.85 * I1p[1];
        Q1 = 0.15 * Q1p + 0.85 * Q1p[1];
        if I1 != 0
        then {
            if Q1 >= 0 and I1 > 0
            then {
                Phase1 = ATan(AbsValue(Q1 / I1));
            } else if Q1 >= 0 and I1 < 0
            then {
                Phase1 = Double.Pi - ATan(AbsValue(Q1 / I1));
            } else if Q1 < 0 and I1 < 0
            then {
                Phase1 = Double.Pi + ATan(AbsValue(Q1 / I1));
            } else {
                Phase1 = 2 * Double.Pi - ATan(AbsValue(Q1 / I1));
            }
        } else if Q1 > 0
        then {
            Phase1 = Double.Pi / 2;
        } else if Q1 < 0
        then {
            Phase1 = 3 * Double.Pi / 2;
        } else {
            Phase1 = 0;
        }
        Phase = Phase1 * 180 / Double.Pi;
        if Phase[1] < 90 and Phase > 270
        then {
            DeltaPhase1 = 360 + Phase[1] - Phase;
        } else {
            DeltaPhase1 = Phase[1] - Phase;
        }
        if DeltaPhase1 < 7
        then {
            DeltaPhase = 7;
        } else if DeltaPhase1 > 60
        then {
            DeltaPhase = 60;
        } else {
            DeltaPhase = DeltaPhase1;
        }
        InstPeriod1 = -1 * (fold i = 0 to 40 with v=0 do if v < 0 then v else if v > 360 then
        -i else v + GetValue(DeltaPhase, i, 41));
        if InstPeriod1 <= 0
        then {
            InstPeriod = InstPeriod[1];
        } else {
            InstPeriod = InstPeriod1;
        }
        Period = 0.25 * InstPeriod + 0.75 * Period[1];
    }
    def DC = Period;
    input FastLimit = 0.5;
    input SlowLimit = 0.05;
    rec Periodx;
    rec Periodx_raw;
    rec Periodx_cap;
    rec Periodx_lim;
    rec smoothx;
    rec Detrenderx;
    rec I1x;
    rec Q1x;
    rec j1x;
    rec jQx;
    rec I2x;
    rec Q2x;
    rec I2x_raw;
    rec Q2x_raw;
    rec Phasex;
    rec DeltaPhasex;
    rec DeltaPhasex_raw;
    rec alphax;
    rec alphax_raw;
    rec Re;
    rec Im;
    rec Re_raw;
    rec Im_raw;
    rec smoothxPeriodx;
    rec vmama;
    rec vfama;
    if BarNumber() <= 5
    then {
        smoothx = 0;
        Detrenderx = 0;
        Periodx = 0;
        Periodx_raw = 0;
        Periodx_cap = 0;
        Periodx_lim = 0;
        I1x = 0;
        Q1x = 0;
        I2x = 0;
        Q2x = 0;
        j1x = 0;
        jQx = 0;
        I2x_raw = 0;
        Q2x_raw = 0;
        Re = 0;
        Im = 0;
        Re_raw = 0;
        Im_raw = 0;
        smoothxPeriodx = 0;
        Phasex = 0;
        DeltaPhasex = 0;
        DeltaPhasex_raw = 0;
        alphax = 0;
        alphax_raw = 0;
        vmama = 0;
        vfama = 0;
    } else {
        smoothx = (4 * price + 3 * price[1] + 2 * price[2] + price[3]) / 10;
        Detrenderx = ( 0.0962 * smoothx + 0.5769 * smoothx[2] - 0.5769 * smoothx[4] - 0.0962 * smoothx[6] ) * CorrectionFactor;
        Q1x = ( 0.0962 * Detrenderx + 0.5769 * Detrenderx[2] - 0.5769 * Detrenderx[4] - 0.0962 * Detrenderx[6] ) * CorrectionFactor;
        I1x = Detrenderx[3];
        j1x = ( 0.0962 * I1x + 0.5769 * I1x[2] - 0.5769 * I1x[4] - 0.0962 * I1x[6] ) * CorrectionFactor;
        jQx = ( 0.0962 * Q1x + 0.5769 * Q1x[2] - 0.5769 * Q1x[4] - 0.0962 * Q1x[6] ) * CorrectionFactor;
        I2x_raw = I1x - jQx;
        Q2x_raw = Q1x + j1x;
        I2x = 0.2 * I2x_raw + 0.8 * I2x_raw[1];
        Q2x = 0.2 * Q2x_raw + 0.8 * Q2x_raw[1];
        Re_raw = I2x * I2x[1] + Q2x * Q2x[1];
        Im_raw = I2x * Q2x[1] - Q2x * I2x[1];
        Re = 0.2 * Re_raw + 0.8 * Re_raw[1];
        Im = 0.2 * Im_raw + 0.8 * Im_raw[1];
        if Re != 0 and Im != 0
        then {
            Periodx_raw = 2 * Double.Pi / ATan(Im / Re);
        } else {
            Periodx_raw = 0;
        }
        if Periodx_raw > 1.5 * Periodx_raw[1]
        then {
            Periodx_cap = 1.5 * Periodx_raw[1];
        } else if Periodx_raw < 0.67 * Periodx_raw[1] {
            Periodx_cap = 0.67 * Periodx_raw[1];
        } else {
            Periodx_cap = Periodx_raw;
        }
        if Periodx_cap < 6
        then {
            Periodx_lim = 6;
        } else if Periodx_cap > 50
        then {
            Periodx_lim = 50;
        } else {
            Periodx_lim = Periodx_cap;
        }
        Periodx = 0.2 * Periodx_lim + 0.8 * Periodx_lim[1];
        smoothxPeriodx = 0.33 * Periodx + 0.67 * smoothxPeriodx[1];
        if I1x != 0
        then {
            Phasex = ATan(Q1x / I1x);
        } else if Q1x > 0
        then {
            Phasex = Double.Pi / 2;
        } else if Q1x < 0
        then {
            Phasex = -Double.Pi / 2;
        } else {
            Phasex = 0;
        }
        DeltaPhasex_raw = Phasex[1] - Phasex;
        if DeltaPhasex_raw < 1
        then {
            DeltaPhasex = 1;
        } else {
            DeltaPhasex = DeltaPhasex_raw;
        }
        alphax_raw = FastLimit / DeltaPhasex;
        if alphax_raw < SlowLimit
        then {
            alphax = SlowLimit;
        } else {
            alphax = alphax_raw;
        }
        vmama = alphax * price + (1 - alphax) * vmama[1];
        vfama = 0.5 * alphax * vmama + (1 - 0.5 * alphax) * vfama[1];
    }
    plot mama = vmama;
    plot fama = vfama;
}


input aggOne = AggregationPeriod.HOUR;
input AggTwo = AggregationPeriod.FIFTEEN_MIN;
input price = close;
input FastLimit = 0.5;
input SlowLimit = 0.05;
def c = close;
def nan = double.nan;

def mamaone;
def famaone;
def mamatwo;
def famatwo;
def mamathree;
def famathree;
input isMTF = {naMTF, default MTF};
switch (isMTF){
Case naMTF:
 mamaone = Mama(price = price, FastLimit = FastLimit, SlowLimit = SlowLimit).fama;
famaone = Mama(price = price, FastLimit = FastLimit, SlowLimit = SlowLimit).fama;
mamatwo = Mama(price = close(period = aggOne )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).mama;
famatwo = Mama(price = close(period = aggOne )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).fama;
mamathree = Mama(price = close(period = AggTwo )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).mama;
famathree = Mama(price = close(period = AggTwo )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).fama;

Case MTF:
 mamaone = Mama(price=close,FastLimit=FastLimit,SlowLimit=SlowLimit).mama;
famaone = Mama(price = close, FastLimit = FastLimit, SlowLimit = SlowLimit).fama;
mamatwo = Mama(price = close(period = aggOne )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).mama;
famatwo = Mama(price = close(period = aggOne )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).fama;
mamathree = Mama(price = close(period = AggTwo )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).mama;
famathree = Mama(price = close(period = AggTwo )[1], FastLimit = FastLimit, SlowLimit = SlowLimit).fama;
}


def stateOne = if mamaone > famaone then 100 else -100;
def statetwo = if mamatwo > famatwo then 100 else -100;
def statethree = if mamathree > famathree then 100 else -100;

plot isMama = if !IsNaN(c) then 1 else nan;
isMama.AssignValueColor(
if stateOne == 100  then Color.GREEN
else Color.RED);
isMama.HideTitle();
isMama.SetLineWeight(5);
isMama.SetPaintingStrategy(PaintingStrategy.SQUARES);

plot MamaMTF1 = if !IsNaN(c) then 1.001 else nan;
MamaMTF1.AssignValueColor(
if statetwo == 100  then Color.GREEN
else Color.RED);
MamaMTF1.HideTitle();
MamaMTF1.SetLineWeight(5);
MamaMTF1.SetPaintingStrategy(PaintingStrategy.SQUARES);
plot MamaMTF2 = if !IsNaN(c) then 1.002 else nan;
MamaMTF2.AssignValueColor(
if statethree == 100  then Color.GREEN
else Color.RED);
MamaMTF2.HideTitle();
MamaMTF2.SetLineWeight(5);
MamaMTF2.SetPaintingStrategy(PaintingStrategy.SQUARES);
do you have shareable link
script is not working for me . Tried on all time frames
can you provide the same
 
Last edited by a moderator:

MerryDay

Administrative
Staff member
Staff
VIP
Lifetime
Last edited:

MerryDay

Administrative
Staff member
Staff
VIP
Lifetime
could someone explain why does this looks different than John ehler's MAMA? His version looks like two ratchet lines while this TOS version are two smooth lines

Here is the original code using easy language
https://www.mesasoftware.com/papers/MAMA.pdf
The ratcheting in Ehler's study is due to the phase cycles. The the script in the 1st post in this thread eliminated the phase math, Making it smoother and triggers earlier which many members prefer.

I found a version here: https://sharpvisiontraders.com/down...mdownloads/mama-fama-adaptive-moving-average/
that seems to be more true to Ehler's process.
FYI: Ehlers recommends this indicator be used on a daily timeframe
2SqRWEy.png

While this version is free. Sharp Vision Traders ask that you to create a free account on their site to download their zip file.
We can not post their script here.

Unsure of how to import a .ts file into the ToS app:
https://tinyurl.com/4xb5zzbn
 
Last edited:

METAL

Active member
Hey guys,
Is there a way to create a watchlist for this study: I cannot locate where I got it. Sorry.
I would like to create a custom watchlist that shows when the Mama and Fama crosses within 1 bar.Is it possible or is this script too difficult to do that with?

Code:
# hint: <b>Ehler's Mesa Adaptive Moving Average</b> using Ray's clean version
# of the homodyne discriminator.
#

# MIT License
# Copyright (c) <2010> <Radford Juang>
#
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
#

script WMA_Smooth {
    input price = hl2;
    plot smooth = (4 * price
+ 3 * price[1]
+ 2 * price[2]
+ price[3]) / 10;
}

script Phase_Accumulation {
# This is Ehler's Phase Accumulation code. It has a full cycle delay.
# However, it computes the correction factor to a very high degree.
#
    input price = hl2;

    rec Smooth;
    rec Detrender;
    rec Period;
    rec Q1;
    rec I1;
    rec I1p;
    rec Q1p;
    rec Phase1;
    rec Phase;
    rec DeltaPhase;
    rec DeltaPhase1;
    rec InstPeriod1;
    rec InstPeriod;
    def CorrectionFactor;

    if BarNumber() <= 5
    then {
        Period = 0;
        Smooth = 0;
        Detrender = 0;
        CorrectionFactor = 0;
        Q1 = 0;
        I1 = 0;
        Q1p = 0;
        I1p = 0;
        Phase = 0;
        Phase1 = 0;
        DeltaPhase1 = 0;
        DeltaPhase = 0;
        InstPeriod = 0;
        InstPeriod1 = 0;
    } else {
        CorrectionFactor = 0.075 * Period[1] + 0.54;

# Smooth and detrend my smoothed signal:
        Smooth = WMA_Smooth(price);
        Detrender = ( 0.0962 * Smooth
+ 0.5769 * Smooth[2]
- 0.5769 * Smooth[4]
- 0.0962 * Smooth[6] ) * CorrectionFactor;

# Compute Quadrature and Phase of Detrended signal:
        Q1p = ( 0.0962 * Detrender
+ 0.5769 * Detrender[2]
- 0.5769 * Detrender[4]
- 0.0962 * Detrender[6] ) * CorrectionFactor;
        I1p = Detrender[3];

# Smooth out Quadrature and Phase:
        I1 = 0.15 * I1p + 0.85 * I1p[1];
        Q1 = 0.15 * Q1p + 0.85 * Q1p[1];

# Determine Phase
        if I1 != 0
        then {
# Normally, ATAN gives results from -pi/2 to pi/2.
# We need to map this to circular coordinates 0 to 2pi

            if Q1 >= 0 and I1 > 0
            then { # Quarant 1
                Phase1 = ATan(AbsValue(Q1 / I1));
            } else if Q1 >= 0 and I1 < 0
            then { # Quadrant 2
                Phase1 = Double.Pi - ATan(AbsValue(Q1 / I1));
            } else if Q1 < 0 and I1 < 0
            then { # Quadrant 3
                Phase1 = Double.Pi + ATan(AbsValue(Q1 / I1));
            } else { # Quadrant 4
                Phase1 = 2 * Double.Pi - ATan(AbsValue(Q1 / I1));
            }
        } else if Q1 > 0
        then { # I1 == 0, Q1 is positive
            Phase1 = Double.Pi / 2;
        } else if Q1 < 0
        then { # I1 == 0, Q1 is negative
            Phase1 = 3 * Double.Pi / 2;
        } else { # I1 and Q1 == 0
            Phase1 = 0;
        }

# Convert phase to degrees
        Phase = Phase1 * 180 / Double.Pi;

        if Phase[1] < 90 and Phase > 270
        then {
# This occurs when there is a big jump from 360-0
            DeltaPhase1 = 360 + Phase[1] - Phase;
        } else {
            DeltaPhase1 = Phase[1] - Phase;
        }

# Limit our delta phases between 7 and 60
        if DeltaPhase1 < 7
        then {
            DeltaPhase = 7;
        } else if DeltaPhase1 > 60
        then {
            DeltaPhase = 60;
        } else {
            DeltaPhase = DeltaPhase1;
        }

# Determine Instantaneous period:
        InstPeriod1 =
-1 * (fold i = 0 to 40 with v=0 do
if v < 0 then
v
else if v > 360 then
-i
else
v + GetValue(DeltaPhase, i, 41)
);

        if InstPeriod1 <= 0
        then {
            InstPeriod = InstPeriod[1];
        } else {
            InstPeriod = InstPeriod1;
        }

        Period = 0.25 * InstPeriod + 0.75 * Period[1];
    }
    plot DC = Period;
}

script Ehler_MAMA {
    input price = hl2;
    input FastLimit = 0.5;
    input SlowLimit = 0.05;


    rec Period;
    rec Period_raw;
    rec Period_cap;
    rec Period_lim;

    rec Smooth;
    rec Detrender;
    rec I1;
    rec Q1;
    rec jI;
    rec jQ;
    rec I2;
    rec Q2;
    rec I2_raw;
    rec Q2_raw;

    rec Phase;
    rec DeltaPhase;
    rec DeltaPhase_raw;
    rec alpha;
    rec alpha_raw;

    rec Re;
    rec Im;
    rec Re_raw;
    rec Im_raw;

    rec SmoothPeriod;
    rec vmama;
    rec vfama;

    def CorrectionFactor = Phase_Accumulation(price).CorrectionFactor;

    if BarNumber() <= 5
    then {
        Smooth = 0;
        Detrender = 0;

        Period = 0;
        Period_raw = 0;
        Period_cap = 0;
        Period_lim = 0;
        I1 = 0;
        Q1 = 0;
        I2 = 0;
        Q2 = 0;
        jI = 0;
        jQ = 0;
        I2_raw = 0;
        Q2_raw = 0;
        Re = 0;
        Im = 0;
        Re_raw = 0;
        Im_raw = 0;
        SmoothPeriod = 0;
        Phase = 0;
        DeltaPhase = 0;
        DeltaPhase_raw = 0;
        alpha = 0;
        alpha_raw = 0;
        vmama = 0;
        vfama = 0;
    } else {
# Smooth and detrend my smoothed signal:
        Smooth = WMA_Smooth(price);
        Detrender = ( 0.0962 * Smooth
+ 0.5769 * Smooth[2]
- 0.5769 * Smooth[4]
- 0.0962 * Smooth[6] ) * CorrectionFactor;

        Q1 = ( 0.0962 * Detrender
+ 0.5769 * Detrender[2]
- 0.5769 * Detrender[4]
- 0.0962 * Detrender[6] ) * CorrectionFactor;
        I1 = Detrender[3];

        jI = ( 0.0962 * I1
+ 0.5769 * I1[2]
- 0.5769 * I1[4]
- 0.0962 * I1[6] ) * CorrectionFactor;

        jQ = ( 0.0962 * Q1
+ 0.5769 * Q1[2]
- 0.5769 * Q1[4]
- 0.0962 * Q1[6] ) * CorrectionFactor;

# This is the complex conjugate
        I2_raw = I1 - jQ;
        Q2_raw = Q1 + jI;

        I2 = 0.2 * I2_raw + 0.8 * I2_raw[1];
        Q2 = 0.2 * Q2_raw + 0.8 * Q2_raw[1];

        Re_raw = I2 * I2[1] + Q2 * Q2[1];
        Im_raw = I2 * Q2[1] - Q2 * I2[1];

        Re = 0.2 * Re_raw + 0.8 * Re_raw[1];
        Im = 0.2 * Im_raw + 0.8 * Im_raw[1];

# Compute the phase
        if Re != 0 and Im != 0
        then {
            Period_raw = 2 * Double.Pi / ATan(Im / Re);
        } else {
            Period_raw = 0;
        }

        if Period_raw > 1.5 * Period_raw[1]
        then {
            Period_cap = 1.5 * Period_raw[1];
        } else if Period_raw < 0.67 * Period_raw[1] {
            Period_cap = 0.67 * Period_raw[1];
        } else {
            Period_cap = Period_raw;
        }

        if Period_cap < 6
        then {
            Period_lim = 6;
        } else if Period_cap > 50
        then {
            Period_lim = 50;
        } else {
            Period_lim = Period_cap;
        }

        Period = 0.2 * Period_lim + 0.8 * Period_lim[1];
        SmoothPeriod = 0.33 * Period + 0.67 * SmoothPeriod[1];

        if I1 != 0
        then {
            Phase = ATan(Q1 / I1);
        } else if Q1 > 0
        then { # Quadrant 1:
            Phase = Double.Pi / 2;
        } else if Q1 < 0
        then { # Quadrant 4:
            Phase = -Double.Pi / 2;
        } else { # Both numerator and denominator are 0.
            Phase = 0;
        }

        DeltaPhase_raw = Phase[1] - Phase;
        if DeltaPhase_raw < 1
        then {
            DeltaPhase = 1;
        } else {
            DeltaPhase = DeltaPhase_raw;
        }

        alpha_raw = FastLimit / DeltaPhase;
        if alpha_raw < SlowLimit
        then {
            alpha = SlowLimit;
        } else {
            alpha = alpha_raw;
        }
        vmama = alpha * price + (1 - alpha) * vmama[1];
        vfama = 0.5 * alpha * vmama + (1 - 0.5 * alpha) * vfama[1];
    }

    plot MAMA = vmama;
    plot FAMA = vfama;
}

declare upper;
input price = hl2;
input FastLimit = 0.5;
input SlowLimit = 0.05;

plot MAMA = Ehler_MAMA(price, FastLimit, SlowLimit).MAMA;
plot FAMA = Ehler_MAMA(price, FastLimit, SlowLimit).FAMA;

plot Crossing = Crosses((MAMA < FAMA), yes);
Crossing.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

plot Crossing1 = Crosses((MAMA > FAMA), yes);
Crossing1.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

AddLabel(yes, Concat("MAMA: ", Concat("",
if MAMA > FAMA then "Bull" else "Bear")),

if MAMA > FAMA then Color.GREEN else Color.RED);
alert( MAMA Crosses Above FAMA, "Bull", Alert.BAR, Sound.Bell );
alert( MAMA Crosses Below FAMA, "Bear", Alert.BAR, Sound.Bell );
 

MerryDay

Administrative
Staff member
Staff
VIP
Lifetime
Hey guys,
Is there a way to create a watchlist for this study: I cannot locate where I got it. Sorry.
I would like to create a custom watchlist that shows when the Mama and Fama crosses within 1 bar.Is it possible or is this script too difficult to do that with?
This script is too complex for scans, watchlists, chart alerts, and conditional orders.
Start reading from here
https://usethinkscript.com/threads/...nals-indicator-for-thinkorswim.34/#post-14653
for scripting, something that might provide you with similar results.

Here is how to search the forum for your indicators:
https://usethinkscript.com/threads/search-the-forum.12626/
 

bigboss

Member
Okay. thanks. That is what I thought.
Here is a version of MAMA that is a direct port of Ehler's original paper, and it should scan. The output of this version matches the MAMA indicator built into NT8. The SharpVisionTraders version is not an accurate port, nor are most on TradingView.


Code:
# Ehler's MAMA – THE MOTHER OF ADAPTIVE MOVING AVERAGES
# https://www.mesasoftware.com/papers/MAMA.pdf
#
# by bigboss
# v20230121

input price = hl2;
input fastLimit = 0.5;
input slowLimit = 0.05;
input showCloud = yes;
input paintBars = no;

def Period;
def smooth = (4 * price + 3 * price[1] + 2 * price[2] + price[3]) / 10.0;
def detrender = (.0962 * smooth + .5769 * smooth[2] - .5769 * smooth[4]- .0962 * smooth[6])*(.075 * Period[1] + .54);

# Compute InPhase and Quadrature components
def Q1 = (.0962 * detrender + .5769 * detrender[2] - .5769 * detrender[4]- .0962 * detrender[6])*(.075 * Period[1] + .54);
def I1 = detrender[3];

# Advance the phase of I1 and Q1 by 90 degrees}
def jI = (.0962 * I1 + .5769 * I1[2] - .5769 * I1[4]- .0962 * I1[6]) * (.075 * Period[1] + .54);
def jQ = (.0962 * Q1 + .5769 * Q1[2] - .5769 * Q1[4]- .0962 * Q1[6]) * (.075 * Period[1] + .54);

# Phasor Addition for 3 bar averaging
# Smooth the I and Q components before applying the discriminator}
def I2 = .2 * (I1 - jQ) + .8 * I2[1];
def Q2 = .2 * (Q1 + jI) + .8 * Q2[1];

# Homodyne Discriminator
def Re = .2 * (I2 * I2[1] + Q2 * Q2[1]) + .8 * Re[1];
def Im = .2 * (I2 * Q2[1] - Q2 * I2[1]) + .8 * Im[1];

def p1 = if(Im <> 0 and Re <> 0, (2 * Double.Pi) / atan(Im / Re), Period[1]);
def p2 = if(p1 > 1.5 * Period[1], 1.5 * Period[1], p1);
def p3 = if(p2 < .67 * Period[1], .67 * Period[1], p2);
def p4 = if(p3 < 6, 6, p3);
def p5 = if(p4 > 50, 50, p4);
Period = .2 * p5 + .8 * Period[1];

def SmoothPeriod = .33 * Period + .67 * SmoothPeriod[1];
def Phase =  if(I1 <> 0, (180 / Double.Pi) * atan(Q1 / I1),Phase[1]);
def DeltaPhase = if((Phase[1] - Phase) < 1, 1, (Phase[1] - Phase));
def alpha = if(fastLimit / DeltaPhase < slowLimit, slowLimit, fastLimit / DeltaPhase);
def _mama = CompoundValue(5,alpha * price + (1 - alpha) * _mama[1],price);
def _fama = CompoundValue(5,.5 * alpha * _mama + (1 - .5 * alpha) * _fama[1],close);

plot MAMA = _mama;
plot FAMA = _fama;

MAMA.SetDefaultColor(Color.Green);
FAMA.SetDefaultColor(Color.Red);

AddCloud(if(showCloud,MAMA,Double.NaN),if(showCloud,FAMA,Double.NaN),Color.LIGHT_GREEN,Color.LIGHT_RED);

AssignPriceColor(if !paintbars then Color.CURRENT else if mama > fama then color.green else color.red);
 

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Top