Help me understand PeakBars/TroughBars

I am trying to build a system using Zig function and would like to refer to “peak/trough x peaks/troughs ago”. Thus using PeakBars/TroughBars looked like the way to go.

However with following test code:

Plot( C, "", colorBlack , styleBar );

pr = Param( "ZigZag change amount", 5, 0.05, 20, 0.05 );

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, "", colorBlue , styleNoLabel );


for(i = 200; i<BarCount-1; i++)
{

PlotText( "" + pk[i], i , H[i] + 0.2 ,colorRed );
}

I do not have all the Peaks numbered as “1” and that’s confuses me:

peaks

Any hint why the peaks using PeakBars are not the same like the lines using Zig?

I am quite new to AFL so my code is copy/paste from other codes. Can you help me understand why people use "pk = PeakBars( H, pr ) == 0;" (the ==0 part) with the PeakBars function?

Thank you.

this is because initially your pk and tr are calculated using the High and Low price respectively. Then you calculate an artificial price array called x. This array you use to calculate the ZigZag function.

So the price arrays you use are different.

However, if you now use the artificial price array x to calculate the pk and tr again, then it will show all peaks and troughs, see code below.

pk = PeakBars( H, pr ) == 0; is simple. Just look at the definition of Peakbars: number of bars that have past since the n-th peak. So at the peak itself the number of bars passed is 0.

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );
pr = Param( "ZigZag change amount", 5, 0.05, 20, 0.05 );

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

pk = PeakBars( H, pr ) == 0;
tr = TroughBars( L, pr ) == 0;

zzHi = Zig( H, pr );
zzLo = Zig( L, pr );

Avg = ( zzHi + zzLo ) / 2;

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

// recalculate the pk and tr using x
pk = PeakBars( x, pr ) == 0;
tr = TroughBars( x, pr ) == 0;
zzHiLo = Zig( x, pr );

Plot( zzHiLo, "", colorBlue , styleNoLabel );

ft = "Tahoma";
sz = 10;
clr1 = ColorRGB( 0, 0, 0 );
clr2 = ColorRGB( 250, 250, 250 );

for( i = fvb; i < lvb; i++ )
{
    //PlotText( "" + pk[i], i , H[i] + 0.2 , colorRed );
    if( pk[i] )
    {
        str = "" + pk[i];
        PlotTextSetFont( str, ft, sz, i, H[i], clr1, clr2, 20 - sz );
    }

    if( tr[i] )
    {
        str = "" + tr[i];
        PlotTextSetFont( str, ft, sz, i, L[i], clr1, clr2, -20 );
    }
}
1 Like

if we add buy sell signal to them , will they be non-repainting and non-lagging?

no, there is a lag. Best do a playback and see for yourself. These peaks and troughs can be used to draw trend lines or look for patterns but it will not give you a peak and trough in real time unfortunately.

Ok , in that case is it possible to implement the below idea:

The last appeared pk or tr be stored in a varaiable and let another indicator (lets say ema 5 and ema 3 crossovers) be used to generate signals as long as they both are in same direction and just close the trade when either one of the two change the direction.

Ok , in that case is it possible to implement the below idea:

The last appeared pk or tr be stored in a varaiable and let another indicator (lets say ema 5 and ema 3 crossovers) be used to generate signals as long as they both are in same direction and just close the trade when either one of the two change the direction.

@santy this KB article shows a technique to Detect Look-Ahead Problems.

The code provided uses the Zig() function (that looks ahead by varying amounts so it is perfect for this demonstration).

It is very clearly stated in the documentation:

Caveat: this function is based on Zig-Zag indicator and may look into the future - this means that you can get unrealistic results when back testing trading system using this indicator. This function is provided rather for pattern and trend recognition formulas.

This caveat is also valid for all the other related functions based on the same indicator like Peak(), PeakBars(), Trough(), TroughBars().

ok, can you just comment on my idea I just pasted above?

@santy, I'm no expert at all, but the fact that in the Member's Zone AFL library none of the referenced formulas that use the Zig() is using it in a well-defined trading system is a hint that it is not an easy task to find something that will provide consistent returns.

i find it tough to work with that version above, with the average price. Below an example using the "classic" Zig top and bottoms when the top and bottom are valid

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );
pr = Param( "ZigZag change amount", 5, 0.05, 20, 0.05 );

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

x = C;
pk = PeakBars( x, pr ) == 0;
tr = TroughBars( x, pr ) == 0;

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

zzHiLo = Zig( x, pr );
PeakVal = Peak( x, pr );
TroughVal = Trough( x, pr );

validUp = Troughval + ( TroughVal / 100 ) * pr;
validDn = Peakval - ( PeakVal / 100 ) * pr;

Buy = ( Cross( C, validUp ) OR C > validUp ) AND tx1 > px1 AND BarsSince( tr ) >= 1;
Buy = ExRem( Buy, pk ); BuyPrice = C;
Short = ( Cross( validDn, C ) OR C < validDn ) AND px1 > tx1 AND BarsSince( pk ) >= 1;
Short = ExRem( Short, tr ); ShortPrice = C;
PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), ColorRGB( 0, 250, 250 ), 0, L, -15 );
PlotShapes( IIf( Buy, shapeSmallSquare, shapeNone ), colorLightBlue, 0, BuyPrice, 0 );
PlotShapes( IIf( Short, shapeDownArrow, shapeNone ), ColorRGB( 250, 250, 0 ) , 0, H, -15 );
PlotShapes( IIf( Short, shapeSmallSquare, shapeNone ), colorOrange, 0, SellPrice, 0 );

Plot( zzHiLo, "", colorBlue , styleNoLabel );
Plot( validUp, "", colorBrightGreen, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( validDn, "", colorRed, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );

ft = "Tahoma";
sz = 10;
clr1 = ColorRGB( 0, 0, 0 );
clr2 = ColorRGB( 250, 250, 250 );

for( i = fvb; i < lvb; i++ )
{
    if( pk[i] )
    {
        str = "Top";
        PlotTextSetFont( str, ft, sz, i, H[i], clr1, clr2, 20 - sz );
    }

    if( tr[i] )
    {
        str = "Bot";
        PlotTextSetFont( str, ft, sz, i, L[i], clr1, clr2, -20 );
    }
}
1 Like

That means this codes' signals are non-repainting and non-lagging?

yes, did you try to do a "Bar Replay"?

I will do that once I go home and get back.

ok well the code is also not yet error free.

i adjusted the code. I almost thought I found the Holy Grail :blush: many system developers know the feeling I guess. I found the Holy Grail and I posted it on the forum, how stupid can one be?

There was an error in there that when a signal appeared at the peak or trough itself, it would disappear. I corrected for that. Not sure if there are more problems. If you find 1 let me know

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );
pr = Param( "ZigZag change amount", 5, 0.05, 20, 0.05 );

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

x = C;
pk = PeakBars( x, pr ) == 0;
tr = TroughBars( x, pr ) == 0;

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

zzHiLo = Zig( x, pr );
PeakVal = Peak( x, pr );
TroughVal = Trough( x, pr );

validUp = Troughval + ( TroughVal / 100 ) * pr;
validDn = Peakval - ( PeakVal / 100 ) * pr;

Buy = ( ( Cross( C, validUp ) || C > validUp ) && tx1 > px1 ) || ( ( Cross( C, validUp ) || C > validUp ) && tx1 < px1 && pk );
BuyPrice = C;
Short = ( ( Cross( validDn, C ) || C < validDn ) && px1 > tx1 ) || ( ( Cross( validDn, C ) || C < validDn ) && px1 < tx1 && tr );
ShortPrice = C;
Buy = ExRem( Buy, Short );
Short = ExRem( Short, Buy );
Sell = Short; SellPrice = ShortPrice;
Cover = Buy; CoverPrice = BuyPrice;

PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), ColorRGB( 0, 250, 250 ), 0, L, -15 );
PlotShapes( IIf( Buy, shapeSmallSquare, shapeNone ), colorLightBlue, 0, BuyPrice, 0 );
PlotShapes( IIf( Short, shapeDownArrow, shapeNone ), ColorRGB( 250, 250, 0 ) , 0, H, -15 );
PlotShapes( IIf( Short, shapeSmallSquare, shapeNone ), colorOrange, 0, SellPrice, 0 );

Plot( zzHiLo, "", colorBlue , styleNoLabel );
Plot( validUp, "", colorBrightGreen, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( validDn, "", colorRed, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );

ft = "Tahoma";
sz = 10;
clr1 = ColorRGB( 0, 0, 0 );
clr2 = ColorRGB( 250, 250, 250 );

for( i = fvb; i < lvb; i++ )
{
    if( pk[i] )
    {
        str = "Top";
        PlotTextSetFont( str, ft, sz, i, H[i], clr1, clr2, 20 - sz );
    }

    if( tr[i] )
    {
        str = "Bot";
        PlotTextSetFont( str, ft, sz, i, L[i], clr1, clr2, -20 );
    }
}
2 Likes

So, we found the HG?

nah, but I think the code itself is correct, at least I did not find an error yet. But these type of systems I worked on before. That is why I posted the code without testing a backtest, since I know it will never work. But for certain percentage setting it makes some money

I do not see any signals and validUp/validDn plotting also!!!

what time frame are you using and at what did you set the percentage parameter in the parameter window? Did you try to change the parameter setting?

I did not change anything. just put on 5min TF. please advise the ideal setting if required.