Fast afl code for ZigZag based on Price Change- anyone?

Hi there,

I am using my own version of a modern Wyckoff trading method. So in order to identify the Wyckoff Waves, I need a ZigZag version that uses Close (optional High/Low) and is based on Price Change, not Percentage. So before I write the code, I want to check if any existing code out there that can be used?

I already have such ZigZag code, but it takes way to much power, especially since I am running a Tick Database.

Thanks,

Jorgen

2 Likes

Hello BJW,

use this place here for your research:

https://forum.amibroker.com/search?q=zigzag

Please see AB SUPPORT - "Members' zone" - "AFL Library" and search for "ZigZag".

http://www.amibroker.com/members/library/list.php

Alternate use Google and you will find tons of AFL ... search: "Amibroker AFL Zig"

https://www.google.com/search?source=hp&ei=lyY0X_yvCorClAaG653wBA&q=amibroker+afl+zig&oq=amibroker+afl+zig&gs_lcp=CgZwc3ktYWIQAzIGCAAQFhAeOggIABCxAxCDAToFCAAQsQM6AggAOgIILjoFCC4QsQM6CAguELEDEJMCOgQIABAKOgQILhAKUPQPWOg7YKZBaABwAHgAgAHQAYgBkwmSAQYxNi4wLjGYAQCgAQGqAQdnd3Mtd2l6&sclient=psy-ab&ved=0ahUKEwi81-COmJbrAhUKIcUKHYZ1B04Q4dUDCAg&uact=5

regards, Peter

Hi Pietro,

I wish it was that simple. So far I have not found a zigzag afl code that fulfill my requirement- uses Close (optional High/Low) and is based on Price Change, not Percentage.

Regards,

Jorgen

Hello BJW,

yes sure, it is often a hard way to go for optimize and performance tuning. I don't know which way you are going just in time with your AFL code. A good place to start is to analyze your code by AB "Check Code & Profile". You find this tool via AFL Editor - Tools - "Check Code & Profile".

Next think about the number of bars you calculate. You could limit the number of bars in your loop for example to 250 iterations, so AB will save much time in processing your AFL code.

Ed Pottasch, one "of the Great" at this community, did excellent work in AFL development. You could start by study his code. Please Google for "ed pottasch alternate zig"

https://www.google.com/search?source=hp&ei=6e00X8eKJoy0kwX03IPQDg&q=ed+pottasch+alternate+zig&oq=ed+pottasch+alternate+zig&gs_lcp=CgZwc3ktYWIQAzIHCCEQChCgATIHCCEQChCgATIHCCEQChCgAToCCAA6AgguOgsILhDHARCjAhCTAjoFCC4QkwI6BAgAEAo6CAguEMcBEK8BOgUIIRCgAToGCAAQFhAeOgQIIRAVUL4QWKI6YPpGaABwAHgAgAGWAYgB1A-SAQQyNC4xmAEAoAEBqgEHZ3dzLXdpeg&sclient=psy-ab&ved=0ahUKEwiHo4ia1pfrAhUM2qQKHXTuAOoQ4dUDCAk&uact=5

regards, Peter

well thanks for the compliment but im just a simple coder. The ATR zig code I like best is this 1:

but I didnt reply to this post because he is talkinh about a "tick database" and most likely that code will not function well, not sure, i didnt test

here i add a simplified version where I add the ZigZag line based on ATR in an array form. Didn't test extensively so i might need to correct it

perBull = perBear = Param( "perBear", 50, 1, 100, 1 );
multBull = multBear = Param( "multBear", 10, 1, 20, 1 );
labelsswitch = ParamToggle( "Show Labels", "Off|On", 1 );

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

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

sup = C - multBull * ATR( perBull );
res = C + multBear * ATR( perBear );

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 = ts = IIf( trailArray > C, trailArray, Null ); // dntrend
uptrend = tl = IIf( trailArray < C, trailArray, Null ); // uptrend

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

hhh = HHV( H, BarsSince( !IsEmpty( ts ) ) );
//hhh = HighestSince( !IsEmpty( ts ), H );
hhh = IIf( tl, hhh, Null );
pkm = tl 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;

// 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, 1 );
Plot( ZigZag, "", colorWhite, styleLine, Null, Null, 0, 0, 1 );
//Plot( ts, "Buy Trigger", upColor, styleDashed | styleStaircase | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
//Plot( tl, "Short Trigger", dnColor, styleDashed | styleStaircase | styleNoRescale | styleNoLabel, Null, Null, 0, 1, 1 );
//Plot( 1, "", IIf( uptrend, ColorRGB( 0, 0, 20 ), ColorRGB( 20, 0, 0 ) ), styleArea | styleOwnScale | styleNoLabel | styleNoRescale, 0, 1, 0, -2, 5 );
PlotShapes( shapeSmallCircle * tr, ColorRGB( 0, 255, 0 ), 0, L, -10 );
PlotShapes( shapeSmallCircle * pk, ColorRGB( 255, 0, 0 ), 0, H, 10 );

ft = "Arial Black";
clr = ColorRGB( 10, 10, 10 );//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 );
        }

        /*
        if( tr[i] )
        {
            GfxSelectPen( dnColor, 1 );
            GfxMoveTo( tx1[i], tl1[i] );
            GfxLineTo( px1[i], ph1[i] );
        }

        if( pk[i] )
        {
            GfxSelectPen( upColor, 1 );
            GfxMoveTo( px1[i], ph1[i] );
            GfxLineTo( tx1[i], tl1[i] );
        }
        */
    }
}
3 Likes

Interesting code! Just some clarifications, I use a Tick Database since I need the Buy and Sell Volumes and as a result the Delta Volume. The chart I use to trade in is 1 min TF.

I trade S&P 500 e-mini future where 1 point is equal to 4 ticks. The ZigZag I need should be based on the change of the Close (optional High/Low) and the Wyckoff Wave is defined by specifying the Tick Change- for example, zigzag at a change of 3 ticks (0.75 points).

I need to study the code to figure out if that is what the code is doing, but a first glance it doesn't look like it....

Anyway, thanks for the code!

Regards,

Jorgen

I have been AFL coding for 12 years, so modifying existing code is not a problem. I just wanted to check what's available instead of directly code such zigzag from scratch.

After looking into this code in more detail, it will most probably be very useful and it's fast!

Jorgen

thanks, this version uses the close price. Basically it is just a chandelier type trail stop. The code I copied from Tomasz. Was posted somewhere on the Amibroker site, can't find it at the moment. That is the part where the trailarray is calculated. This defines the uptrend and the downtrend. If you want to use the high and low you will have to adjust that part of the code.

here I added some colors to the ZigZag line :slight_smile:

perBull = perBear = Param( "perBear", 50, 1, 100, 1 );
multBull = multBear = Param( "multBear", 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 - multBull * ATR( perBull );
res = C + multBear * ATR( perBear );

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 );
        }
    }
}
1 Like

Looks very promising! I will look into this as soon as I get some spare time! :slight_smile:

I will report back.

Thanks and Regards,

Jorgen Wallgren

this was the code I used inside my code:

http://amibroker.com/members/traders/05-2009.html

I probably did something wrong when I changed the code, but it looks right- except for this part:

Wrong

I set the change to 1 point- 4 Ticks and in this section, it jumps over a series of ups/downs with a change of 4 ticks or more.

I need to check tomorrow.

Jorgen

you can change the "ATR multiple". That was not really clear in my code. I made it clearer below:

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 );
        }
    }
}
1 Like

Thank you!!! I use the "ATR Multiple" as by Price Change (for example 4 ticks = 1 point for ES), but I realize that the ATR and ATR Periods kind mess things up since I get different results in different TFs. If I set the ZigZag to change at for example 4 ticks, 1 Point, then it should do so in all time frames- 1 min, 5 min and 15 min etc. It can't be dependent on Periods, only the actual Price change:

PriceTicks = Param( "Price Change In Ticks", 4, 1, 40, 1 );
PriceChange = PriceTicks * TickSize;

I will play around with the code and see if I can come up with a solution that is as neat as your original code.

Thanks!

Jorgen

ah ok I think I know what you mean. In that case you need not to use ATR but use a fluctuation in absolute points.

So now my code uses:

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

this you need to write differently using absolute points. This will then use the same fluctuation in every timeframe. So the code then would be (see below). I think that should be correct but you need to check it.

PriceTicks = Param( "Price Change In Ticks", 4, 1, 40, 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 - TickSize * PriceTicks;
res = C + TickSize * PriceTicks;

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 ); 
uptrend = IIf( trailArray < C, trailArray, Null );

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( 255, 0, 0 ), 0, L, 10 );
PlotShapes( shapeSmallUpTriangle * pkn, ColorRGB( 0, 255, 0 ), 0, H, 10 );
PlotShapes( shapeCircle * tr, ColorRGB( 0, 255, 0 ), 0, L, -10 );
PlotShapes( shapeCircle * 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 );
        }
    }
}
1 Like

Thanks! But that's exactly what I did! Interesting- then I was right about something is wrong! :slight_smile:
Unfortunately it doesn't work properly. The screen capture shows a set to 4 ticks price change and the code miss a 2.75 points move.

Wrong 2

I am working on it and try to find where it's going wrong.

Thanks and Regards,

Jorgen Wallgren

yes, i originally just wanted to use ATR to add pivots to the chart. This might need some additional work. Will think about it. If someone else comes up with the solution would even be better :slight_smile:

I let you know if I find a way! :slight_smile:

Jorgen

here is some code. Probably still full of errors but this is the way to go in my opinion. Let me know where things go wrong, or maybe others can make corrections or improvements

PriceTicks = Param( "Price Change In Ticks", 4, 1, 40, 1 );
labelsswitch = ParamToggle( "Show Labels", "Off|On", 1 );
priceswitch = ParamToggle( "Use Close or High and Low price", "Use Close|Use High and Low", 1 );

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

pk = tr = 0;

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

fluc = TickSize * PriceTicks;

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

// initial condition trend is up
trend = 1;
topprc = prch[0];
topidx = 0;
breakl = topprc - fluc;

for( i = 1; i < BarCount; i++ )
{
    if( trend > 0 )
    {
        if( prcl[i] < breakl AND prch[i] <= topprc )
        {
            pk[topidx] = 1;
            botprc = prcl[i];
            botidx = i;
            breakh = botprc + fluc;          
            trend = -1;
        }
        else
            if( prch[i] > topprc )
            {
                topprc = prch[i];
                topidx = i;
                breakl = prch[i] - fluc;
            }
    }
    else
        if( trend < 0 )
        {
            if( prch[i] > breakh AND prcl[i] >= botprc )
            {
                tr[botidx] = 1;
                topprc = prch[i];
				topidx = i;
				breakl = topprc - fluc;
                trend = 1;
            }
            else
                if( prcl[i] < botprc )
                {
                    botprc = prcl[i];
                    botidx = i;
                    breakh = prcl[i] + fluc;
                }
        }
}

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, 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, "", colorwhite, styleLine, Null, Null, 0, 0, 2 );

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\n" + L[i];
            PlotTextSetFont( str, ft, sz, i, L[i], upColor, clr, -30 );
        }

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

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

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

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

        if( dt[i] )
        {
            str = "DT\n" + H[i];
            PlotTextSetFont( str, ft, sz, i, H[i], dnColor, clr, 35 );
        }
    }
}
2 Likes

Dear Ed Pottasch,

You are truly an AFL Genius!!! At a first glance, it looks like it works!

I did a few changes, like turning points when price change is equal to or more than the specified Tick Change. Then I changed some small details to fit into my chart style.

My 3 lower panes uses only 1 tick change by simple array coding:

StartUp = Close > Ref( Close, -1 );
EndUp = Close < Ref( Close, -1 );
UpBox = flip( StartUp, EndUp );
DnBox = flip( EndUp, StartUp );

My Chart
etc. So when I set your code to 1 Tick change, I can directly compare it to my lower panes and looks like an exact match!!!

I will check the High/Low and higher settings tomorrow. But this is fantastic!!! :slight_smile:

If all OK, then I will add the longer Waves Cumulative Delta in the Price chart in order to compare it to what happens within the Longer Waves- using the 3 lower panes. Like This:

My Chart 2

Thank you so much!!!

Jorgen

1 Like