How to streamline this code?

I am trying to put the values of peak and trough into a single array.
With using for loop and if loops i am getting results but it is taking 87.3 ms to complete, is there any other way to streamline this code.

function Edges()
{
	array2 = Peak(C, 0.1);
	array3 = Trough(C, 0.1);
	array[0] = Null ;
	
	for ( i = 0 ; i < BarCount-1; i++ )
    {
        if(!isnull(array2[i]))
        {
			array[i] = array2[i];
		};
			
		if(!IsNull(array3[i]))
		{
			array[i] = array3[i];
		};
    };
	
	array[BarCount-1] = Close[BarCount-1];
	
	return array;
	
};

Have you checked the Docs and simple Debug?
Peak() and Trough() don't return values at true states but the latest value at that bar.

Using IsNull() wont work because non peak/trough bars are not Null, only its corresponding recent Close value,
Since array3 is checked after array2, you'll just have array as a copy of array3.

The time taken to traverse from 0 to Barcount is directly proportional to the number of bars, there is nothing much you can streamline except reducing the number of bars actually needed.

And the semi-colon after For, If and Function { } braces are not part of the syntax ( redundant although code will still execute)

Snap of Trough and Peak bar-by-bar...
image

For the solution part,
You actually need clean intermediate Arrays that can be done like this:

myPeakArray = Iif( C == array2, C, 0 );
// You need handle obstacles where two successive bars have same close etc
// depending on your strategy

// Similarly
myTroughArray = Iif( C == array3, C, 0 );

The 0 above is very important, don't use NULL or something else,

then merge the Arrays cleverly using Binary OR instead of slower looping

array = myPeakArray | myTroughArray;

I loved this bit :smiley:
Remember, Binary OR will add the two arrays, so you need to be sure that there is no overlap of values in the two temp arrays otherwise use the old loop way instead which checks each array index.

2 Likes

Just curious: why would you not simply add the two arrays, which most people would find more intuitive?

array = myPeakArray + myTroughArray;

Well, at that time, it was purely out of a habit :slight_smile: its cool too :stuck_out_tongue:

Ideally, there are two ways to find out,
one is to take a large sample set and test it and the other is TJ for sure knows :smiley:

Todays compilers (and the processor) are far smarter but traditionally, a binary OR would be faster then a normal Addition.

So in general present scenario, an Addition can be as fast as a Binrary OR (as in equal time)
but choosing a Binary OR would probably guarantee you the fastest addition possible.

This was also related to OP saying it takes a lot of time which may imply a lot of Bars in question.

4 Likes

Opps
@travick thank you very much, for the explanation.

last month i wrote a code and i was not sure why this part was working as expected

if( id == 102 && event == 2|8|16)

after your explanation now is clear to me why :wink:
thank again

1 Like

Could you please share the code , as it seems interesting to me and I was searching for something like this since a long time.

If you haven't got around it yet, you can try this way.

array2 = Peak( C, 0.1);
array3 = Trough( C, 0.1);
array[0] = Null;
	
NewP = array2 != Ref( array2, -1);    // Every change in value implies new Peak
NewT = array3 != Ref( array3, -1);    // Same check in Troughs
	
array2 = Iif( NewP && !IsNull( array2), C, 0 );    // retain only Close for Peaks
array3 = Iif( NewT && !IsNull( array3), C, 0 );    // while filtering any Null values
array = array2 | array3;                           // Power Add

In my tests, I get a clean and non-overlap array

one extra check can be thrown in if you really want to be sure, incase there is a Peak and Trough on the same bar which shouldn't happen, but if it does.
so we prioritize peaks over troughs, in that case this line changes to

array3 = Iif( NewT && !IsNull(array3) && !NewP, C, 0 );

If there is a peak on a bar, Trough will be forced to 0

Now you have a full solution :slight_smile:

2 Likes

Binary OR is not the same as addition.

8 | 10 != 8 + 10

These two are completely different. 8 | 10 equals 10. That is totally different than 18 (sum)

http://xcprod.com/titan/XCSB-DOC/binary_or.html

ORing close prices is bad coding practice. Binary OR should be used on integers only (numbers without fractional parts). Nested iif is better in that case.

3 Likes

Agreed @Tomasz you are right. Add not the same as Binary OR would skip the carry bit.
In this case is it suitable because we are having either value at 0 for sure so its going to be X | 0 or 0 | Y always at any given index?

Thank you.

Just to add more so everything is in right context,
unable to Edit previous post but to emphasize on what TJ says,

Binary OR that I was applying should be used on Integers which was the case in my Test.
It should be highlighted in Bold that its good only for integers because a float would loose its values after the decimal anyway (Fractional part).
This is a quick way for rounding a number to its Floor integer used in some codes.

Its not right to replace my test variable that I had used with Close as OP needed because it carries a float meaning.

Binary OR with Bit representation is also good, so 1, 2, 4, 8, 16.... so on will give a correct value.
Binary OR of random integers will not be a correct Sum.
To cite a good example,
https://www.amibroker.com/guide/afl/plot.html
One may see that the style values are Bit Flags.
These bit flags can be Binary OR'd as used like styleNoTitle| styleOwnScale| styleHistogram

Here, test integer variable with | should be fine with a 0 value which I had specified in my first post but overlooked other conditions which didn't seem relevant.

Since integers aren't defined in AFL per se, we should keep in mind that we will consider the integer part of float.
For the code part, if the array will come across float values, then we should Add them array2 + array3

1 Like