# Fill Peaks and Troughs arrays with values

Hi,

I have the below code to calculate peaks and troughs. I need to fill in the values without using loops is it possible.? For example, if PEAKS_BOOL==1 then its high value should be assigned to PEAKS. That can be easily done using ValueWhen, but till i get the new peak the old value should be carryforward.

``````PEAKS =Null;
TROUGHS = Null;

PEAKS_BOOL = H > Ref( H, 1 ) AND H > Ref( H, -1 ) AND (Ref(H, -1) > Ref(H, -2) OR Ref(L, -1) > Ref(L, -2));

TROUGHS_BOOL = L < Ref( L, 1 ) AND L < Ref( L, -1 ) AND (Ref(L, -1) < Ref(L, -2) OR Ref(H, -1) < Ref(H, -2));
``````

Vinay

To get what youâ€™re asking for - and because you canâ€™t use recursion in AFL - you can just turn it into a two step process. First get the values at all the peaks, and then fill in the values elsewhere.

``````ONLY_PEAKS = IIf( PEAKS_BOOL, H, Null );
ONLY_TROUGHS = IIf( TROUGHS_BOOL, L, Null );

PEAKS = ValueWhen( !IsNull(ONLY_PEAKS),ONLY_PEAKS,1);
TROUGHS = ValueWhen( !IsNull(ONLY_TROUGHS),ONLY_TROUGHS,1);``````

But I question your definitions of peaks & troughs.

I get why you wouldnâ€™t use the built-in zigzag based peaks & troughs, but if youâ€™re using a definition that seems odd to me.

Traditionally a peak is held to be a higher-high than the prior period, with an equal-or-higher low - while a trough is the opposite (lower-low, equal-or-lower high). Inside & Outside days are continuation of prior.

So I donâ€™t get why youâ€™re checking â€śtomorrowâ€™sâ€ť value (and hence also eliminating results for the most recent period), or looking back 2 periods.

That said, unless Iâ€™m misunderstanding you or have had a brain fart, the code provided should do what youâ€™re asking for (and you could just alter your boolean conditional if you want a more traditional version).

canâ€™t use recursion

@pache
Nonsense. If you donâ€™t know AFL it is better to stay quiet than to speak up. Two errors in one sentence. FYI: a) you can have recursion AFL, but b) this code does not need recursion at all.

The code is single liner and it is

``````Peaks = ValueWhen( Peaks_Bool, High );
``````

and does not require recursion nor loops. One function call. And it keeps the value between peaks as original poster wanted.

If somebody is interested in looping code that draws lines between peaks/troughs here it is:

So before posting:
b) nonsense answers that make false claims

would you be so clever next time to use Google.

Edited: apparently â€śbrain fartâ€ť is a part of innocent nice chit-chat in Australia, so author did not really wanted to offend anyone. Still assuming everybody is from Australia is quite risky

1 Like

in answer to the original poster. I think you are referring to â€śFractal Pivotsâ€ť defined by Bill Williams.

to my knowledge the first 1 to put them in AFL was Edakad, see => http://www.inditraders.com/amibroker/1934-afl-harmonic-patterns.html

here is some of my code using Edakadâ€™s formula extracted from the link above:

``````// Fractal Pivots
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

rightstrength = Param( "Right Strength", 5, 2, 50, 1 );
leftstrength = Param( "Left Strength", 5, 2, 50, 1 );
fact = Param( "Chart Time Frame Factor", 1, 1, 10, 1 );

rightStrength = rightStrength * fact;
leftStrength = leftStrength * fact;

pk = H == HHV( H, leftstrength ) AND Ref( HHV( H, rightstrength ), rightstrength ) < H;
tr = L == LLV( L, leftstrength ) AND Ref( LLV( L, rightstrength ), rightstrength ) > L;

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;

GraphXSpace = 5;
SetChartBkColor( colorBlack );
SetChartOptions( 1, chartShowDates, chartGridMiddle, 0, 0, 0 );
SetBarFillColor( IIf( C > O, ColorRGB( 0, 75, 0 ), IIf( C <= O, ColorRGB( 75, 0, 0 ), colorLightGrey ) ) );
Plot( C, "", IIf( C > O, ColorRGB( 0, 255, 0 ), IIf( C <= O, ColorRGB( 255, 0, 0 ), colorLightGrey ) ), 64, Null, Null, 0, 0, 1 );

PlotShapes( shapeSmallCircle * tr, ColorRGB( 0, 0, 255 ), 0, L, -10 );
PlotShapes( shapeSmallCircle * pk, ColorRGB( 255, 0, 0 ), 0, H, 10 );

clr = ColorRGB( 10, 10, 10 );

for( i = lvb; i > fvb; i-- )
{
// troughs
if( ll[i] )
{
str = "LL";
PlotTextSetFont( str, "Arial Black", 8, i, L[i], ColorRGB( 0, 0, 250 ), colorDefault, -30 );
}

if( hl[i] )
{
str = "HL";
PlotTextSetFont( str, "Arial Black", 8, i, L[i], ColorRGB( 0, 0, 250 ), colorDefault, -30 );
}

if( db[i] )
{
str = "DB";
PlotTextSetFont( str, "Arial Black", 8, i, L[i], ColorRGB( 0, 0, 250 ), colorDefault, -30 );
}

//peaks
if( hh[i] )
{
str = "HH";
PlotTextSetFont( str, "Arial Black", 8, i, H[i], ColorRGB( 250, 0, 0 ), colorDefault, 20 );
}

if( lh[i] )
{
str = "LH";
PlotTextSetFont( str, "Arial Black", 8, i, H[i], ColorRGB( 250, 0, 0 ), colorDefault, 20 );
}

if( dt[i] )
{
str = "DT";
PlotTextSetFont( str, "Arial Black", 8, i, H[i], ColorRGB( 250, 0, 0 ), colorDefault, 20 );
}
}

Title = Name() +
" | " + Now( 2 ) +
" | " + "Pivot Timeframe Factor: " + fact;
``````
3 Likes

I actually use a non-zigzag peaks and troughs function that calculates traditional peaks & troughs via a bar-by-bar approach (extremely similar to the example you provided - I combine the peaks and troughs into a single array). Itâ€™s why the OPâ€™s question interested me.

My understanding of recursion is that itâ€™s a function calling itself (or at least thatâ€™s what I was taught when I learnt Miranda, many years back). From looking at the wikipedia page on recursion in computer science, thatâ€™s clearly a pretty simplistic definition.

But in https://www.amibroker.com/guide/a_userfunctions.html it specifies: Note also that recursion (having a function call itself from within itself) is NOT supported as for now.

Has that changed? Cos Iâ€™d love to be able to call functions from within themselves, itâ€™s an approach I feel comfortable with.

One of the things Iâ€™ve been wanting to do with my own bar-by-bar version of a peaks-and-troughs function is getting it working in an indefinite number of additional higher timeframes (e.g. peak-of-the-peaks, etc) and I was struggling to come up with a version that wasnâ€™t limited to looping through a pre-set number of higher timeframes.

Edit: Actuallyâ€¦ you could make a matrix, and keep expanding it by one row while the peaks/troughs were still getting meaningful/non-identical results, and then run the separate peaks & troughs function to make each new row until then? Or is that getting over-elaborate & thereâ€™s a simpler version?

No, recursion is a mathematical term. It was invented LONG LONG time before computers. Fibonacci was using recursion in 1202. Did you see computers back then?

In math it is simply:

yn = f( x, yn-1 )

In computer science recursive algorithm is the one that uses previous result(s) to calculate current value.

Wikipedia unfortunately is written by amateurs and they are focusing on narrowest meaning, but this is wrong understanding of recursion.

All infinite impulse response filtering (like EMA), cumulative sums (Cum) and such are recursive in nature as they use previous value to calculate current:

``````y (current) = factor * input + ( 1 - factor ) * y( previous )
``````

This kind of calculation can easily be done in AmiBroker explicitly

``````y = 0;
for( i = 1; i < BarCount; i++ )
{
y[ i ] = factor * x[ i ] + ( 1 - factor ) * y[ i - 1 ];
}
``````

or using built-in AmiBroker function

``````y = AMA2( x,factor,1 - factor );
``````

Internally it does the same as loop given above.

What you pointed out from the manual is a narrowest meaning of recursion (calling function from within itself) and it is prohibited on purpose as doing so leads to highly inefficient algorithms.

Fundamentally recursive algorithms (in math sense) - like the FACTORIAL or Fibonacci series (in which every number after the first two is the sum of the two preceding ones) can be implemented either using calling the function itself or using one loop.
If implemented using function-based recursion Fibonacci series algorithm has complexity of O(N*N),while the same done using loop has complexity of O(N). With N being 10000 it means 10000 times faster.

``````// code in C
int fibonacci(int n)
{
if(n == 0)
return 0;
else
if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2); // these calls cause HUGE exponentially growing cost
}

// contrary to the above example - the code below has linear complexity O(n)
int fibbonaci_loop(int n)
{
int prev2 = 0;
int prev1 = 1;
int current = 0;
for (int i = 0; i < n; i++)
{
current = prev1 + prev2;
prev2 = prev1;
prev1 = current;
}
return current;
}

``````

This plus the fact that function calls are costly because they cause CPU pipeline invalidation causes poor performance of nested function calls.
Any half-skilled programmer knows the difference and avoids nested function call recursion as hell.

8 Likes