Impulse MACD [LazyBear] by LazyBear


If you are added actual QUESTION you might have, it would be possible to give you any answer.

Please follow this advice: How to ask a good question

1 Like

Sorry I thought I had posted some code: I was trying to convert some Pinescript code to AFL and the indicator in Amibroker is different. I was wondering whether anyone can spot the error in my converted code. It would be much appreciated.

///@link https://www.tradingview.com/chart/pwIDdtdH/

src = (H+L+C)/3;
lengthMA = 34;
lengthSignal = 9;
function zlema(src,length )
{
    ema1 = ema(src, length);
    ema2 = ema(ema1, length);
    d    = ema1-ema2;
    zelma = ema1+d;
  return zelma;
}

len = 34;
smma = 0;
function SmoothedMovingAverage(src, len) 
{
   smma = IIf(IsNaN(Ref(smma,-1)), MA(src,len), (Ref(smma,-1) * (len - 1) + src) / len);
    return smma;
}
//Plot(smma(src,len),"smma",colorBlue,styleLine);

hi=SmoothedMovingAverage(high, lengthMA);
lo=SmoothedMovingAverage(low, lengthMA);
mi=zlema(src, lengthMA); 

md = IIf((mi>hi),(mi-hi),IIf((mi<lo),(mi - lo),0));
md = IIf(mi > hi, mi - hi, IIf(mi < lo, mi - lo, 0));

sb = MA(md, lengthSignal);
sh=md-sb;
mdc = IIf(src>mi,IIf(src>hi,2,1),IIf(src<lo,-2,-1));
plot(0, "MidLine",colordarkGrey,styleline);
plot(md, "ImpulseMACD",colorblue, stylehistogram);
plot(sh, "ImpulseHisto",colorred, stylehistogram);
plot(sb, "ImpulseMACDCDSignal",colorDarkRed, styleline);

////////////////////////////////////////////////////////////////
// Define Input Variables
LengthMA = Param("Length of MA", 34, 2, 500, 1);
LengthSignal = Param("Length of Signal", 9, 2, 500, 1);

// Define Functions
   smma = 0;
   len = 34;
function SmoothedMovingAverage(src, len) 
{
   smma = IIf(IsNaN(Ref(smma,-1)), MA(src,len), (Ref(smma,-1) * (len - 1) + src) / len);
    return smma;
}

function ZeroLagExponentialMovingAverage(src, length) 
{
    ema1 = EMA(src, length);
    ema2 = EMA(ema1, length);
    d = ema1 - ema2;
    return ema1 + d;
}

// Calculate Values
Source = (H + L + C) / 3;
HI = SmoothedMovingAverage(H, LengthMA);
LO = SmoothedMovingAverage(L, LengthMA);
MI = ZeroLagExponentialMovingAverage(Source, LengthMA);

MD = IIf(MI > HI, MI - HI, IIf(MI < LO, MI - LO, 0));
SB = MA(MD, LengthSignal);
SH = MD - SB;

MDC = IIf(Source > MI, IIf(Source > HI, colorGreen, colorLime), IIf(Source < LO, colorRed, colorOrange));

// Plotting
Plot(0, "MidLine", colorGrey40, styleLine);
Plot(MD, "Impulse MACD", MDC, styleHistogram);
Plot(SH, "Impulse Histo", colorBlue, styleHistogram);
Plot(SB, "Impulse MACD Signal", colorCustom1);

// Enable Bar Color
EnableBarColor = ParamToggle("Enable Bar Colors", "No|Yes", 0);
if (EnableBarColor) {
    BarColor = MDC;
}


This is the link to the Pinescript code
https://www.tradingview.com/script/qt6xLfLi-Impulse-MACD-LazyBear/

//study("Impulse MACD [LazyBear]", shorttitle="IMACD_LB", overlay=false)

lengthMA = 34;//input(34)
lengthSignal = 9;

src = (H+ L + C) / 3;
hi = MA(High, lengthMA);
lo = MA(low, lengthMA);
ema1 = ema(src, lengthMA);
ema2 = ema(ema1, lengthMA);
d = ema1 - ema2;
mi = ema1 + d;

md = IIf( mi > hi, mi - hi, IIf(mi < lo, mi - lo, 0));
sb = MA(md, lengthSignal);
sh = md - sb;

mdc = IIf(src > mi, IIf( src > hi, colorLime, colorGreen), IIf(src < lo, colorRed, colorOrange));
plot(md, "ImpulseMACD", mdc, stylehistogram);
plot(sh, "ImpulseHisto", colorblue, stylehistogram);
plot(sb, "ImpulseMACDCDSignal", colorBrown, styleThick);
PlotGrid(0);

5 Likes

@moccha, welcome to this Community.

Here below a version that seem more similar to the original (using the custom "calc_smma" function instead of a simple MA as done by @awilson):

// study("Impulse MACD [LazyBear]", shorttitle="IMACD_LB", overlay=false)

function calc_smma( src, len )
{
    sma = MA( src, len );
    smma = Null;

    for( i = 1; i < BarCount; i++ )
    {
        if( IsNull( smma[i - 1] ) )
            smma[i] =  sma[i];
        else {
            smma[i]  = ( smma[i - 1] * ( len - 1 ) + src[i] ) / len;
		}
    }

    return smma;
}

function calc_zlema( src, len )
{
    ema1 = EMA( src, len );
    ema2 = EMA( ema1, len );
    d = ema1 - ema2;
    return ema1 + d;
}

// User params
lengthEMA = Param( "MACD EMA Periods", 34, 10, 1 );
lengthSignal = Param( "MACD Signal Periods", 9, 5, 25, 1 );

showMACDHistogram = ParamToggle( "Show MACD Histogram", "No|Yes", 1);
MACDHistogramColor0 = ParamColor( "MACD Histogram - Color 0", colorLime);
MACDHistogramColor1 = ParamColor( "MACD Histogram - Color 1", colorGreen);
MACDHistogramColor2 = ParamColor( "MACD Histogram - Color 2", colorLightOrange);
MACDHistogramColor3 = ParamColor( "MACD Histogram - Color 3", colorRed);
HistogramBarsWidth = Param("% Width of Histogram bars", 30, 1, 50, 1);

showImpulseHistogram = ParamToggle( "Show Impulse Histogram", "No|Yes", 1);
impulseHistogramColor = ParamColor("Impulse Histogram Color", colorBlue);

showMACDSignal = ParamToggle( "Show MACD Signal", "No|Yes", 1);
MACDSignalColor = ParamColor( "MACD Signal Color", colorBrown);
showMidLine = ParamToggle( "Show Mid Line", "No|Yes", 1);
colorMidLine = ParamColor( "Color Mid Line", colorGrey40);

src = Avg; // same as (High+Low+Close)/3 
hi = calc_smma( High, lengthEMA );
lo = calc_smma( Low, lengthEMA );
mi = calc_zlema( src, lengthEMA );

md = IIf( mi > hi, mi - hi, IIf( mi < lo, mi - lo, 0 ) );

sb = MA( md, lengthSignal );
sh = md - sb;

GraphXSpace = 5;
mdc = IIf( src > mi, IIf( src > hi, MACDHistogramColor0, MACDHistogramColor1 ), IIf( src < lo, MACDHistogramColor3, MACDHistogramColor2 ) );
if (showMACDHistogram)
	Plot( md, "Impulse MACD", mdc, styleHistogram, Null, Null, 0, 0, -HistogramBarsWidth );
if (showImpulseHistogram)
	Plot( sh, "Impulse Histogram", impulseHistogramColor, styleHistogram, Null, Null, 0, 1, -HistogramBarsWidth ); // paint above MADC Histogram
if (showMACDSignal)
	Plot( sb, "MACD Signal", MACDSignalColor, styleThick, Null, Null, 0, 2);  // paint above both Histograms
if (showMidline AND (showMACDHistogram OR showImpulseHistogram OR showMACDSignal))
	Plot( 0 , "", colorMidLine, styleDashed | styleNoTitle);

I also added parameters to customize appearance.

Just out of curiosity, if you find a formula that uses this indicator to improve the conditions/signals for entering or exiting positions, please let us know!

3 Likes

If you would not just copy and paste you would realize that upper slow version is just single AMA line

lengthEMA = Param( "MACD EMA Periods", 34, 10, 1 );

hi = AMA(H, 1/lengthEMA);

lo = AMA(L, 1/lengthEMA);
3 Likes

One main problem is the calc_smma() or SmoothMovingAverage() as you call it, can be written in various ways like with a loop or using IIR() with factor = 1 / len or simply using equivalent Wilders() function.

Here is my attempt:

_SECTION_BEGIN( "Impulse MACD" );
/// @link https://www.tradingview.com/script/qt6xLfLi-Impulse-MACD-LazyBear/
/// Impulse MACD is a modified MACD, formed by filtering out the values in a MA range
/// (region between MAs of high and low), thereby reducing whipsaw typical in a sideways
/// market. 
///

/// SMMA - SMoothed moving average i.e. wilders
function calc_smma( src, length )
{
    return Wilders( src, length );
}

function calc_zlema( src, length )
{
    ema1 = EMA( src, length );
    ema2 = EMA( ema1, length );
    diff = ema1 - ema2;
    result = ema1 + diff;
    return result;
}

src = ParamField("Price", 4);
lengthMA = Param( "length MA", 34, 1, 50, 1 );
lengthSignal = Param( "length Signal", 9, 1, 50, 1 );
paramvalues = _PARAM_VALUES();
linewidth = Param( "Line width", 3, 1, 5, 1 );

// change indicator Impulse MACD default display to line instead of histogram
// select histogram to display like LazyBear's
isMACDhistogram = ParamToggle( "Plot Impulse MACD as", "Line|Histogram", 0 );
show_plot = ParamList( "Show Plot", "Impulse MACD|Impulse w/o histo|Price Chart", 0 );
PriceChartStyle = ParamStyle( "Price Chart Style" );

hi = calc_smma( high, lengthMA );
lo = calc_smma( low, lengthMA );
mi = calc_zlema( src, lengthMA );

md = IIf( mi > hi, ( mi - hi ), IIf( ( mi < lo ), ( mi - lo ),  0 ) );
sb = ma( md, lengthSignal );
sh = md - sb;
mdc = IIf( src > mi, IIf( src > hi, colorLime, colorGreen ), IIf( src < lo, colorRed, colorOrange ) );

if( show_plot == "Price Chart" )
{
    SetChartOptions( 1, chartShowArrows | chartShowDates );
    mode_candle = ( GetPriceStyle() & styleCandle ) == styleCandle;
    pricestyle = PriceChartStyle | GetPriceStyle();
    Color_outline = mdc;
    Color_fill = IIf( mode_candle, IIf( C > O, GetChartBkColor(), Color_outline ), Color_outline );

    SetBarFillColor( Color_fill );
    Plot( C, "Close", Color_outline, pricestyle, Null, Null, 0, 0, linewidth );
    Plot( hi, "Hi", colorAqua, styleLine, Null, Null, 0, 1, linewidth );
    Plot( lo, "Lo", colorAqua, styleLine, Null, Null, 0, 1, linewidth );
    Plot( mi, "Mi", colorBlue, styleLine, Null, Null, 0, 1, linewidth );
}
else
{
    SetChartOptions( 1, !chartShowDates );
    PlotGrid( 0, colorGrey40, 9, 2, True );

plot( IIf( isMACDhistogram, md, Null ), "", mdc, styleHistogram | stylenolabel, Null, Null, 0, -2, linewidth );
plot( md, "ImpulseMACD" + paramvalues, mdc, styleLine, Null, Null, 0,  0, linewidth );
plot( sb, "ImpulseMACDSignal", colorBrown, styleLine, Null, Null, 0, 0, linewidth );

if( show_plot != "Impulse w/o histo" )
    plot( sh, "ImpulseHisto", colorBlue, stylehistogram, Null, Null, 0, -1, linewidth );

}
_SECTION_END();
5 Likes

@newbie that is excellent point made. I can't count the number of places where people re-invent the wheel and re-implement for the Nth time everything known from dozes of years as it was something fresh. This is just Wilders average (built-in function) known from 1978 (in TA field, it was known way before that in electronic engineering).

2 Likes

@Tomasz, I did a little exploration to compare the results using the 3 different methods.
Using "Wilders" the result is essentially the same (except for the first non-null element).
(I visually ignore any minor differences using AlmostEqual() empirically).

On the other hand AMA, gives different results at the start of the arrays, but after a while it lines up (is this due to the values calculated​ ​at the front of the array where the others are null?).

The methods don't seem to be entirely interchangeable, but I'm probably missing something, and the differences in practical terms may not be relevant to a trader.

Thanks in advance for any clarification.

Initial results:
image

Some bars later:
image

Further in the arrays:
image

(and from here onward results are essentially aligned).

Code used for the above screenshots:

lengthEMA = 20; // differences using AMA seem to increase when increasing this length 
Filter = 1;
for (i = 0; i < 2; i ++) {
	switch(i) {
		case 0: price = High; label = "H"; break;
		case 1: price = Low;  label = "L"; break;
	}
	sm = calc_smma( price, lengthEMA ); // see the code posted in a previous answe
	wi = Wilders( price, lengthEMA );
	am = AMA( price, 1 / lengthEMA );
	AddColumn( sm, label + " calc_smma()", 1.3 );
	color = IIf( AlmostEqual( sm, wi, 50 ), colorDefault, colorRed );
	AddColumn( wi, label + " Wilders", 1.3, color ); // same result except first value
	color = IIf( AlmostEqual( sm, am, 50 ), colorDefault, colorRed );
	AddColumn( am, label + " AMA", 1.3, color ); // not always the same
}
5 Likes

The reason is that is being IIR filter. Infinite Impulse Response. The values depend how do you initialise. These averages are mathematically the same. What is different is value/method for initialization (and it is not standardised in any way). The impact of different initialisation exponentially diminishes to zero as time goes.

BTW this was discussed to death already on this forum.

2 Likes

Thanks for all your answers. It's much appreciated

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.