ZigZag ATR vs Percentage

Hello,
I have created a version of the Zigzag indicator that uses ATR to determine the reversals rather than % swings. In the process of doing that, I have messed up somewhere. The lines are not straight. If you look below, the first chart shows a jagged looking Zigzag and the 2nd chart is the standard 5% Zigzag. Can you tell me how to get the swings on the ATR chart to look like the 5% swing chart?
Thanks,
Joe

ZIGZAG USING ATR CREATES JAGGED LINE FROM LOW TO HIGH AND HIGH TO LOW

SECTION_BEGIN("ATRSwing");

pr=0;

TLB = C > LLV(L,14)+ ATR(15)*2.5 ;

TLT = C < HHV(H,14)- ATR(15)*2.5;

red = Flip( TLT , TLB);

green = Flip( TLB, TLT );

pk=PeakBars(green,pr)==0;

tr=TroughBars(red,pr)==0;

zzHi=Zig(H,pr);

zzLo=Zig(L,pr);

Avg=(zzHi+zzLo)/2;

x=IIf(pk,zzHi,IIf(tr,zzLo,IIf(Avg>Ref(Avg,-1),H,L)));

zzHiLo=Zig(x,pr);

Plot( zzHiLo, "", ParamColor("Color",colorRed), ParamStyle("Style"));

_SECTION_END();

AAPL ATRzigzag

ZIGZAG USING 5% SWING CREATES STRAIGHT LINES FROM LOW TO HIGH AND HIGH TO LOW--

_SECTION_BEGIN("ZigZag");

pr=Param("ZigZag change amount", 5, 0.1,100,0.1);

pk=PeakBars(H,pr)==0;

tr=TroughBars(L,pr)==0;

zzHi=Zig(H,pr);

zzLo=Zig(L,pr);

Avg=(zzHi+zzLo)/2;

x=IIf(pk,zzHi,IIf(tr,zzLo,IIf(Avg>Ref(Avg,-1),H,L)));

zzHiLo=Zig(x,pr);

Plot( zzHiLo, "", ParamColor("Color",colorRed), ParamStyle("Style"));

_SECTION_END();

AAPL %zigzag

I suggest you start here: How do I debug my formula?

In particular, I would use an Exploration to focus on the values of your intermediate variables like TLB, TLT, red, green, etc. Then think about how PeakBars() and TroughBars() are likely to behave when you pass them boolean arrays instead of price arrays.

You might also want to search the forum for "ZigZag". For example, there is a lengthy discussion here related to a price-based ZigZag rather than percentage based.

1 Like

Thank you! Ed P. had the code using ATR already in place. This is everything I need! I appreciate it. Joe

So, i am now realizing the code from Ed P. using ATR was looking for ATR multiple from Closing price instead of high/low. Anyone know how to change that? it is over my head.

per = Param( "ATR Period", 50, 1, 100, 1 );
mult = Param( "ATR Multiple", 10, 1, 20, 1 );
labelsswitch = ParamToggle( "Show Labels", "Off|On", 1 );

upColor = ColorRGB( 0, 255, 0 );
dnColor = ColorRGB( 255, 0, 0 );

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

sup = C - mult * ATR( per );
res = C + mult * ATR( per );

trailArray = Null;
trailstop = 0;

for( i = 1; i < BarCount; i++ )
{
    if( C[ i ] > trailstop AND C[ i - 1 ] > trailstop )
        trailstop = Max( trailstop, sup[ i ] );
    else
        if( C[ i ] < trailstop AND C[ i - 1 ] < trailstop )
            trailstop = Min( trailstop, res[ i ] );
        else
            trailstop = IIf( C[ i ] > trailstop, sup[ i ], res[ i ] );

    trailArray[ i ] = trailstop;
}

dntrend = IIf( trailArray > C, trailArray, Null ); // dntrend
uptrend = IIf( trailArray < C, trailArray, Null ); // uptrend

lll = LLV( L, BarsSince( !IsEmpty( uptrend ) ) );
//lll = LowestSince( !IsEmpty( uptrend ), L );
lll = IIf( dntrend, lll, Null );
trm = dntrend AND L == lll;

hhh = HHV( H, BarsSince( !IsEmpty( dntrend ) ) );
//hhh = HighestSince( !IsEmpty( dntrend ), H );
hhh = IIf( uptrend, hhh, Null );
pkm = uptrend AND H == hhh;

tr = ExRem( Reverse( trm ), Reverse( pkm ) );
pk = ExRem( Reverse( pkm ), Reverse( trm ) );

tr = Reverse( tr );
pk = Reverse( pk );

for( i = 0; i < 3; i++ )
{
    VarSet( "px" + i, ValueWhen( pk, bi, i ) );
    VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
    VarSet( "ph" + i, ValueWhen( pk, H, i ) );
    VarSet( "tl" + i, ValueWhen( tr, L, i ) );
}

ll = tr AND tl1 < tl2;
hl = tr AND tl1 > tl2;
hh = pk AND ph1 > ph2;
lh = pk AND ph1 < ph2;
dt = pk AND ph1 == ph2;
db = tr AND tl1 == tl2;

trn = LowestSince( pk, L ) == L && dntrend;
pkn = HighestSince( tr, H ) == H && uptrend;

// create ZIGZAG array line
zigup = Flip( tr, pk );
zigupLow = ValueWhen( tr, L, 1 );
zigupHigh = ValueWhen( pk, H, 0 );
zigupLowIndex = ValueWhen( tr, bi, 1 );
zigupHighIndex = ValueWhen( pk, bi, 0 );
slopeup = IIf( zigup, ( zigupHigh - zigupLow ) / ( zigupHighIndex - zigupLowIndex ) , Null );
zigupLine = IIf( zigup, zigupLow + slopeup * BarsSince( tr ), Null );

zigdn = Flip( pk, tr );
zigdnLow = ValueWhen( tr, L, 0 );
zigdnHigh = ValueWhen( pk, H, 1 );
zigdnLowIndex = ValueWhen( tr, bi, 0 );
zigdnHighIndex = ValueWhen( pk, bi, 1 );
slopedn = IIf( zigdn, ( zigdnLow - zigdnHigh ) / ( zigdnLowIndex - zigdnHighIndex ) , Null );
zigdnLine = IIf( zigdn, zigdnHigh + slopedn * BarsSince( pk ), Null );

ZigZag = IIf( zigup, zigupLine, IIf( zigdn, zigdnLine, Null ) );
ZigZag = IIf( bi > Max( LastValue( ValueWhen( tr, bi ) ), LastValue( ValueWhen( pk, bi ) ) ), Null, ZigZag );

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 0 );
Plot( ZigZag, "", IIf( uptrend, ColorRGB( 0, 0, 255 ), ColorRGB( 255, 0, 0 ) ), styleLine, Null, Null, 0, 0, 4 );

PlotShapes( shapeSmallDownTriangle * trn, ColorRGB( 0, 100, 0 ), 0, L, 10 );
PlotShapes( shapeSmallUpTriangle * pkn, ColorRGB( 100, 0, 0 ), 0, H, 10 );
PlotShapes( shapeSmallCircle * tr, ColorRGB( 0, 255, 0 ), 0, L, -10 );
PlotShapes( shapeSmallCircle * pk, ColorRGB( 255, 0, 0 ), 0, H, 10 );

ft = "Arial Black";
clr = colorDefault;
sz = 7;

GfxSetZOrder( 0 );
GfxSetCoordsMode( 1 );

if( labelsswitch )
{
    for( i = fvb; i <= lvb; i++ )
    {

        if( ll[i] )
        {
            str = "LL";
            PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -30 );
        }

        if( hl[i] )
        {
            str = "HL";
            PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -30 );
        }

        if( db[i] )
        {
            str = "DB";
            PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -30 );
        }

        if( hh[i] )
        {
            str = "HH";
            PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 20 );
        }

        if( lh[i] )
        {
            str = "LH";
            PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 20 );
        }

        if( dt[i] )
        {
            str = "DT";
            PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 20 );
        }
    }
}

this code uses the Close, not the H/L. I have some code for H/L also but this is tricky because when the price starts moving with large swing inside 1 bar at some point you get signals all over the place and that can get messy. So the code you have there uses the Close price.

here is a nice version where you can toggle between using the Close or the High/Low. It is based on the thread where I made a zigzag for the absolute price change. Fast afl code for ZigZag based on Price Change- anyone?

I have been trying a few things to avoid special cases but come up with this code. And it works very well. Let me know if you find problems.

// Amibroker code, ATR pivots + trail
// Aug 2020, E.M.Pottasch

per = Param( "ATR Period", 50, 1, 100, 1 ); // you need at least "per" data points to run this code
mult = Param( "ATR Multiple", 3, 1, 20, 0.1 );
priceswitch = ParamToggle( "Use Close or High and Low price", "Use Close|Use High and Low", 1 );
labelsswitch = ParamToggle( "Show Labels", "Off|On", 1 );
plottrailswitch = ParamToggle( "Show Trail Line", "No|Yes", 1 );

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
pk = tr = Buy = Sell = BuyPrice = SellPrice = 0;
trailarrayup = trailarraydn = Null;

if( priceswitch )
{
    prch = H;
    prcl = L;
}
else
{
    prch = C;
    prcl = C;
}

// if ticksize is not set in code or information window use 0.01
if( TickSize == 0 )
{
    TickSize = 0.01;
}

sup = round( ( prch - mult * ATR( per ) ) / TickSize ) * TickSize;
res = round( ( prcl + mult * ATR( per ) ) / TickSize ) * TickSize;

trend = 1; // start trend at 1 or -1 doesnt matter
topprc = prch[per];
topidx = 0;
botprc = prcl[per];
botidx = 0;
trailarrayup[per] = sup[per];
trailarraydn[per] = res[per];

for( i = per + 1; i < BarCount; i++ )
{
    if( trend > 0 )
    {
        if( prcl[i] <= trailarrayup[i - 1] AND prch[i] < topprc )
        {
            // trend turning down, avoid same bar as the peak
            pk[topidx] = 1;
            botprc = prcl[i];
            botidx = i;
            trend = -1;
            Sell[i] = 1;
            trailarraydn[i] = res[i];
            trailarrayup[i] = trailarrayup[i - 1];

            if( priceswitch )
                SellPrice[i] = Min( O[i], trailarrayup[i] );
            else
                SellPrice[i] = C[i];
        }
        else
            if( prch[i] >= topprc )
            {
                // still in uptrend but new top reached
                topprc = prch[i];
                topidx = i;
                trailarrayup[i] = Max( trailarrayup[i - 1], sup[i] );
            }
            else
            {
                // continuation inside uptrend
                trailarrayup[i] = Max( trailarrayup[i - 1], sup[i] );
            }
    }
    else
        if( trend < 0 )
        {
            if( prch[i] >= trailarraydn[i - 1] AND prcl[i] > botprc )
            {
                // trend turning up, avoid same bar as the trough
                tr[botidx] = 1;
                topprc = prch[i];
                topidx = i;
                trend = 1;
                Buy[i] = 1;
                trailarrayup[i] = sup[i];
                trailarraydn[i] = trailarraydn[i - 1];

                if( priceswitch )
                    BuyPrice[i] = Max( O[i], trailarraydn[i] );
                else
                    BuyPrice[i] = C[i];
            }
            else
                if( prcl[i] <= botprc )
                {
                    // still in downtrend but new trough reached
                    botprc = prcl[i];
                    botidx = i;
                    trailarraydn[i] = Min( trailarraydn[i - 1], res[i] );
                }
                else
                {
                    // continuation inside downtrend
                    trailarraydn[i] = Min( trailarraydn[i - 1], res[i] );
                }
        }
}

line1 = Null;
lastidxpk = LastValue( ValueWhen( pk, bi ) );
lastidxtr = LastValue( ValueWhen( tr, bi ) );
lastvalpk = LastValue( ValueWhen( pk, prch ) );
lastvaltr = LastValue( ValueWhen( tr, prcl ) );
lastidxbuy = LastValue( ValueWhen( Buy, bi ) );
lastidxsell = LastValue( ValueWhen( Sell, bi ) );
valpk = LastValue( HighestSince( Ref( tr, -1 ), prch , 1 ) );
idxpk = LastValue( ValueWhen( prch == valpk, bi ) );
valtr = LastValue( LowestSince( Ref( pk, -1 ), prcl, 1 ) );
idxtr = LastValue( ValueWhen( prcl == valtr, bi ) );

if( lastidxsell > lastidxbuy AND lastidxsell > lastidxpk AND lastidxpk > lastidxtr )
{
    x0 = lastidxpk;
    y0 = lastvalpk;
    x1 = idxtr;
    y1 = valtr;
    line1 = linedn = LineArray( x0, y0, x1, y1 );
    tr[idxtr] = 1;
    valpk = LastValue( HighestSince( Ref( tr, -1 ), prch, 1 ) );
    idxpk = LastValue( ValueWhen( prch == valpk, bi ) );
}

if( lastidxsell < lastidxbuy AND lastidxbuy > lastidxtr AND lastidxpk < lastidxtr )
{
    x0 = lastidxtr;
    y0 = lastvaltr;
    x1 = idxpk;
    y1 = valpk;
    line1 = lineup = LineArray( x0, y0, x1, y1 );
    pk[idxpk] = 1;
    valtr = LastValue( LowestSince( Ref( pk, -1 ), prcl, 1 ) );
    idxtr = LastValue( ValueWhen( prcl == valtr, bi ) );
}

for( i = 0; i < 3; i++ )
{
    VarSet( "px" + i, ValueWhen( pk, bi, i ) );
    VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
    VarSet( "ph" + i, ValueWhen( pk, H, i ) );
    VarSet( "tl" + i, ValueWhen( tr, L, i ) );
}

ll = tr AND tl1 < tl2;
hl = tr AND tl1 > tl2;
hh = pk AND ph1 > ph2;
lh = pk AND ph1 < ph2;
dt = pk AND ph1 == ph2;
db = tr AND tl1 == tl2;

// create ZIGZAG array line
zigup = Flip( tr, pk );
zigupLow = ValueWhen( tr, prcl, 1 );
zigupHigh = ValueWhen( pk, prch, 0 );
zigupLowIndex = ValueWhen( tr, bi, 1 );
zigupHighIndex = ValueWhen( pk, bi, 0 );
slopeup = IIf( zigup, ( zigupHigh - zigupLow ) / ( zigupHighIndex - zigupLowIndex ) , Null );
zigupLine = IIf( zigup, zigupLow + slopeup * BarsSince( tr ), Null );

zigdn = Flip( pk, tr );
zigdnLow = ValueWhen( tr, prcl, 0 );
zigdnHigh = ValueWhen( pk, prch, 1 );
zigdnLowIndex = ValueWhen( tr, bi, 0 );
zigdnHighIndex = ValueWhen( pk, bi, 1 );
slopedn = IIf( zigdn, ( zigdnLow - zigdnHigh ) / ( zigdnLowIndex - zigdnHighIndex ) , Null );
zigdnLine = IIf( zigdn, zigdnHigh + slopedn * BarsSince( pk ), Null );

ZigZag = IIf( zigup, zigupLine, IIf( zigdn, zigdnLine, Null ) );
ZigZag = IIf( bi > Max( LastValue( ValueWhen( tr, bi ) ), LastValue( ValueWhen( pk, bi ) ) ), Null, ZigZag );
ZigZag = IIf( !IsEmpty( line1 ), line1, ZigZag );

uptrend = Flip( Buy, Sell );
dntrend = Flip( Sell, Buy );
trn = LowestSince( pk, prcl ) == prcl && dntrend;
pkn = HighestSince( tr, prch ) == prch && uptrend;

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 0 );
Plot( IIf( !IsEmpty( line1 ), line1, Null ), "", ColorRGB( 255, 255, 0 ), styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 2 );
Plot( ZigZag, "", IIf( uptrend, ColorRGB( 0, 0, 255 ), ColorRGB( 255, 0, 0 ) ), styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 2 );

PlotShapes( shapeSmallDownTriangle * trn, ColorRGB( 100, 0, 0 ), 0, L, 10 );
PlotShapes( shapeSmallUpTriangle * pkn, ColorRGB( 0, 60, 0 ), 0, H, 10 );
PlotShapes( shapeSmallCircle * tr, colorGreen, 0, L, -10 );
PlotShapes( shapeSmallCircle * pk, colorRed, 0, H, 10 );

if( plottrailswitch )
{
    Plot( trailarrayup, "trail up", colorLightBlue, styleDots | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
    Plot( trailarraydn, "trail dn", colorOrange, styleDots | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
    PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), colorLightBlue, 0, L, -15 );
    PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorOrange, 0, H, -15 );
    PlotShapes( IIf( Buy, shapeSmallSquare, shapeNone ), colorYellow, 0, BuyPrice, 0 );
    PlotShapes( IIf( Sell, shapeSmallSquare, shapeNone ), colorYellow, 0, SellPrice, 0 );
}

ft = "Arial Black";
clr = colorDefault;
sz = 7;
GfxSetZOrder( -1 );
GfxSetCoordsMode( 1 );

if( labelsswitch )
{
    str1 = "";

    for( i = fvb; i <= lvb; i++ )
    {
        if( pk[i] )
        {
            if( dt[i] )
                str1 = "DT";
            else
                if( hh[i] )
                    str1 = "HH";
                else
                    if( lh[i] )
                        str1 = "LH";

            PlotTextSetFont( str1, ft, sz, i, H[i], colorRed, clr, sz * 3 );
            PlotTextSetFont( "" + prch[i], ft, sz, i, H[i], colorRed, clr, sz * 5 );
        }

        if( tr[i] )
        {
            str1 = "";

            if( db[i] )
                str1 = "DB";
            else
                if( ll[i] )
                    str1 = "LL";
                else
                    if( hl[i] )
                        str1 = "HL";


            PlotTextSetFont( str1, ft, sz, i, L[i], colorGreen, clr, -sz * 4 );
            PlotTextSetFont( "" + prcl[i], ft, sz, i, L[i], colorGreen, clr, -sz * 6 );
        }
    }
}
5 Likes

Hi,

Thanks for sharing the code.

I was wondering if it would be possible to print the wave volume instead of printing HH, HL, etc. ?
By wave volume i mean the volume should be added beginning such that counting starts at a trough and ends at a peak or begins at a peak and ends at a trough.

Thanks.

you have quite a complicated name :smile:

yes is possible. This is basicly what is done in the MBox method. I will add it to the code tomorrow because trading now. But basicaly the calculation you do as (see below). You need to use the arrays CumVolumeUpMBoxChart and CumVolumeDnMBoxChart to print the volumes in the chart

uptrend = Ref( Flip( tr, pk ), -1 );
dntrend = Ref( Flip( pk, tr ), -1 );

// volume
CumVolumeUpMBox = SumSince( tr, Volume );
CumVolumeDnMBox = SumSince( pk, Volume );
CumVolumeUpMBoxChart = IIf( uptrend, ValueWhen( pk, CumVolumeUpMBox, 0 ), Null );
CumVolumeUpMBoxChart = IIf( uptrend AND pk, CumVolumeUpMBox, CumVolumeUpMBoxChart );
CumVolumeDnMBoxChart = IIf( dntrend, ValueWhen( tr, CumVolumeDnMBox, 0 ), Null );
CumVolumeDnMBoxChart = IIf( dntrend AND tr, CumVolumeDnMBox, CumVolumeDnMBoxChart );

below the code where I added the cumulative volume

// Amibroker code, ATR pivots + trail
// Aug 2020, E.M.Pottasch

per = Param( "ATR Period", 50, 1, 100, 1 ); // you need at least "per" data points to run this code
mult = Param( "ATR Multiple", 3, 1, 20, 0.1 );
priceswitch = ParamToggle( "Use Close or High and Low price", "Use Close|Use High and Low", 1 );
labelsswitch = ParamToggle( "Show Labels", "Off|On", 1 );
plottrailswitch = ParamToggle( "Show Trail Line", "No|Yes", 1 );
sz = Param( "Text Size", 8, 5, 20, 1 );

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
pk = tr = Buy = Sell = BuyPrice = SellPrice = 0;
trailarrayup = trailarraydn = Null;

if( priceswitch )
{
    prch = H;
    prcl = L;
}
else
{
    prch = C;
    prcl = C;
}

// if ticksize is not set in code or information window use 0.01
if( TickSize == 0 )
{
    TickSize = 0.01;
}

sup = round( ( prch - mult * ATR( per ) ) / TickSize ) * TickSize;
res = round( ( prcl + mult * ATR( per ) ) / TickSize ) * TickSize;

trend = 1; // start trend at 1 or -1 doesnt matter
topprc = prch[per];
topidx = 0;
botprc = prcl[per];
botidx = 0;
trailarrayup[per] = sup[per];
trailarraydn[per] = res[per];

for( i = per + 1; i < BarCount; i++ )
{
    if( trend > 0 )
    {
        if( prcl[i] <= trailarrayup[i - 1] AND prch[i] < topprc )
        {
            // trend turning down, avoid same bar as the peak
            pk[topidx] = 1;
            botprc = prcl[i];
            botidx = i;
            trend = -1;
            Sell[i] = 1;
            trailarraydn[i] = res[i];
            trailarrayup[i] = trailarrayup[i - 1];

            if( priceswitch )
                SellPrice[i] = Min( O[i], trailarrayup[i] );
            else
                SellPrice[i] = C[i];
        }
        else
            if( prch[i] >= topprc )
            {
                // still in uptrend but new top reached
                topprc = prch[i];
                topidx = i;
                trailarrayup[i] = Max( trailarrayup[i - 1], sup[i] );
            }
            else
            {
                // continuation inside uptrend
                trailarrayup[i] = Max( trailarrayup[i - 1], sup[i] );
            }
    }
    else
        if( trend < 0 )
        {
            if( prch[i] >= trailarraydn[i - 1] AND prcl[i] > botprc )
            {
                // trend turning up, avoid same bar as the trough
                tr[botidx] = 1;
                topprc = prch[i];
                topidx = i;
                trend = 1;
                Buy[i] = 1;
                trailarrayup[i] = sup[i];
                trailarraydn[i] = trailarraydn[i - 1];

                if( priceswitch )
                    BuyPrice[i] = Max( O[i], trailarraydn[i] );
                else
                    BuyPrice[i] = C[i];
            }
            else
                if( prcl[i] <= botprc )
                {
                    // still in downtrend but new trough reached
                    botprc = prcl[i];
                    botidx = i;
                    trailarraydn[i] = Min( trailarraydn[i - 1], res[i] );
                }
                else
                {
                    // continuation inside downtrend
                    trailarraydn[i] = Min( trailarraydn[i - 1], res[i] );
                }
        }
}

line1 = Null;
lastidxpk = LastValue( ValueWhen( pk, bi ) );
lastidxtr = LastValue( ValueWhen( tr, bi ) );
lastvalpk = LastValue( ValueWhen( pk, prch ) );
lastvaltr = LastValue( ValueWhen( tr, prcl ) );
lastidxbuy = LastValue( ValueWhen( Buy, bi ) );
lastidxsell = LastValue( ValueWhen( Sell, bi ) );
valpk = LastValue( HighestSince( Ref( tr, -1 ), prch , 1 ) );
idxpk = LastValue( ValueWhen( prch == valpk, bi ) );
valtr = LastValue( LowestSince( Ref( pk, -1 ), prcl, 1 ) );
idxtr = LastValue( ValueWhen( prcl == valtr, bi ) );

if( lastidxsell > lastidxbuy AND lastidxsell > lastidxpk AND lastidxpk > lastidxtr )
{
    x0 = lastidxpk;
    y0 = lastvalpk;
    x1 = idxtr;
    y1 = valtr;
    line1 = linedn = LineArray( x0, y0, x1, y1 );
    tr[idxtr] = 1;
    valpk = LastValue( HighestSince( Ref( tr, -1 ), prch, 1 ) );
    idxpk = LastValue( ValueWhen( prch == valpk, bi ) );
}

if( lastidxsell < lastidxbuy AND lastidxbuy > lastidxtr AND lastidxpk < lastidxtr )
{
    x0 = lastidxtr;
    y0 = lastvaltr;
    x1 = idxpk;
    y1 = valpk;
    line1 = lineup = LineArray( x0, y0, x1, y1 );
    pk[idxpk] = 1;
    valtr = LastValue( LowestSince( Ref( pk, -1 ), prcl, 1 ) );
    idxtr = LastValue( ValueWhen( prcl == valtr, bi ) );
}

for( i = 0; i < 3; i++ )
{
    VarSet( "px" + i, ValueWhen( pk, bi, i ) );
    VarSet( "tx" + i, ValueWhen( tr, bi, i ) );
    VarSet( "ph" + i, ValueWhen( pk, H, i ) );
    VarSet( "tl" + i, ValueWhen( tr, L, i ) );
}

ll = tr AND tl1 < tl2;
hl = tr AND tl1 > tl2;
hh = pk AND ph1 > ph2;
lh = pk AND ph1 < ph2;
dt = pk AND ph1 == ph2;
db = tr AND tl1 == tl2;

// create ZIGZAG array line
zigup = Flip( tr, pk );
zigupLow = ValueWhen( tr, prcl, 1 );
zigupHigh = ValueWhen( pk, prch, 0 );
zigupLowIndex = ValueWhen( tr, bi, 1 );
zigupHighIndex = ValueWhen( pk, bi, 0 );
slopeup = IIf( zigup, ( zigupHigh - zigupLow ) / ( zigupHighIndex - zigupLowIndex ) , Null );
zigupLine = IIf( zigup, zigupLow + slopeup * BarsSince( tr ), Null );

zigdn = Flip( pk, tr );
zigdnLow = ValueWhen( tr, prcl, 0 );
zigdnHigh = ValueWhen( pk, prch, 1 );
zigdnLowIndex = ValueWhen( tr, bi, 0 );
zigdnHighIndex = ValueWhen( pk, bi, 1 );
slopedn = IIf( zigdn, ( zigdnLow - zigdnHigh ) / ( zigdnLowIndex - zigdnHighIndex ) , Null );
zigdnLine = IIf( zigdn, zigdnHigh + slopedn * BarsSince( pk ), Null );

ZigZag = IIf( zigup, zigupLine, IIf( zigdn, zigdnLine, Null ) );
ZigZag = IIf( bi > Max( LastValue( ValueWhen( tr, bi ) ), LastValue( ValueWhen( pk, bi ) ) ), Null, ZigZag );
ZigZag = IIf( !IsEmpty( line1 ), line1, ZigZag );

uptrend1 = Flip( Buy, Sell );
dntrend1 = Flip( Sell, Buy );
trn = LowestSince( pk, prcl ) == prcl && dntrend1;
pkn = HighestSince( tr, prch ) == prch && uptrend1;

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 0 );
Plot( IIf( !IsEmpty( line1 ), line1, Null ), "", ColorRGB( 255, 255, 0 ), styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 2 );
Plot( ZigZag, "", IIf( uptrend1, ColorRGB( 0, 0, 255 ), ColorRGB( 255, 0, 0 ) ), styleLine | styleNoRescale | styleNoLabel, Null, Null, 0, 0, 2 );

PlotShapes( shapeSmallDownTriangle * trn, ColorRGB( 100, 0, 0 ), 0, L, 10 );
PlotShapes( shapeSmallUpTriangle * pkn, ColorRGB( 0, 60, 0 ), 0, H, 10 );
PlotShapes( shapeSmallCircle * tr, colorGreen, 0, L, -10 );
PlotShapes( shapeSmallCircle * pk, colorRed, 0, H, 10 );

if( plottrailswitch )
{
    Plot( trailarrayup, "trail up", colorLightBlue, styleDots | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
    Plot( trailarraydn, "trail dn", colorOrange, styleDots | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
    PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), colorLightBlue, 0, L, -15 );
    PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorOrange, 0, H, -15 );
    PlotShapes( IIf( Buy, shapeSmallSquare, shapeNone ), colorYellow, 0, BuyPrice, 0 );
    PlotShapes( IIf( Sell, shapeSmallSquare, shapeNone ), colorYellow, 0, SellPrice, 0 );
}

// volume
CumVolumeUpMBoxChart = SumSince( tr, Volume );
CumVolumeDnMBoxChart = SumSince( pk, Volume );

ft = "Arial Black";
clr = colorDefault;
//sz = 7;
GfxSetZOrder( -1 );
GfxSetCoordsMode( 1 );

if( labelsswitch )
{
    str1 = "";

    for( i = fvb; i <= lvb; i++ )
    {
        if( pk[i] )
        {
            if( dt[i] )
                str1 = "DT";
            else
                if( hh[i] )
                    str1 = "HH";
                else
                    if( lh[i] )
                        str1 = "LH";

            PlotTextSetFont( str1, ft, sz, i, H[i], colorRed, clr, sz * 3 );
            PlotTextSetFont( "" + prch[i], ft, sz, i, H[i], colorRed, clr, sz * 5 );
            PlotTextSetFont( "" + CumVolumeUpMBoxChart[i], ft, sz, i, H[i], colorBlue, colorWhite, sz * 7 );
        }

        if( tr[i] )
        {
            str1 = "";

            if( db[i] )
                str1 = "DB";
            else
                if( ll[i] )
                    str1 = "LL";
                else
                    if( hl[i] )
                        str1 = "HL";


            PlotTextSetFont( str1, ft, sz, i, L[i], colorGreen, clr, -sz * 4 );
            PlotTextSetFont( "" + prcl[i], ft, sz, i, L[i], colorGreen, clr, -sz * 6 );
            PlotTextSetFont( "" + CumVolumeDnMBoxChart[i], ft, sz, i, L[i], colorRed, colorWhite, -sz * 8 );
        }
    }
}
6 Likes

This is super. The code is really hard to understand would it be possible to throw some light on the logic used. Thanks a ton :pray:

i think the code is pretty straightforward. But it is always tough to read somebody elses code. Also if you are new to coding it takes some practice to learn to code. Start with simple pieces of code and plot the result in a chart to see what the result of your coding is.

Sure lemme again give a try to decode the logic and see if can make sense. Will post querries if any. Thanks.

@mdwiwhekucybhfhzni, you really need to get your "Verified Badge". It shows you are a Registered Owner of AmiBroker, and only verified owners are supposed to post questions.

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