Faster array approach for this function instead of using slow for-loop approach

I would like to have a function which returns an output array output_arr of number of past bars in the past n days which are greater than the present bar of price_arr. An example will illustrate the meaning more clearly. In this example, n = 3.

price_arr    =   [1.1   1.2   8.2   4.1   7.6   3.1   0.8]
output_arr =     [ 0     0     0     1     1     3     3]

I have coded a solution. However, it is too slow as it uses for loop to solve the problem. I would like a faster array approach.

Here is my retarded solution. It is unpractical as it is slow for charts with too many bars. The amibroker way should use array, not for-loop.

function GetNumDaysAbove(price_arr, Index, NumDays)
{	
	NumDaysAbove = Sum( price_arr > price_arr[Index], NumDays);
	return NumDaysAbove;
}

function GetNumberOfDaysAbovePresentBarArr(price_arr, NumberOfDays)
{		
	NumDaysAboveArr = 0;
	for( i = 1; i < BarCount; i++ )
	{
		arr=GetNumDaysAbove(price_arr, i, NumberOfDays);
		NumDaysAboveArr[i] = arr[i];
	}

	return NumDaysAboveArr;
}

@thankyou18, I believe you will need to do some looping for this type of exercise. However, instead of looping over every bar, you can loop over the number of days instead. Try this code:


function GetNumberOfDaysAbovePresentBarArr2(price_arr, NumberOfDays)
{		
	NumDaysAboveArr = 0;
	for( i = 1; i <= NumberOfDays; i++ )
	{
		NumDaysAboveArr += price_arr <= Ref(price_arr, -i);
	}

	return NumDaysAboveArr;
}

Filter = True;
numDaysAbove = GetNumberOfDaysAbovePresentBarArr2(C,10);
AddColumn(numDaysAbove, "# Days Above", 1.0);

Note that my code is comparing NumberOfDays previous bars to the current bar, whereas your code was including the current bar in NumberOfDays, i.e. only comparing the current bar to NumberOfDays-1 previous bars. That's easy to change if you want your original behavior.

In my quick test, your code took 3.1 seconds to run against 25 years worth of data for the S&P 100, and my code took 0.34 seconds.

5 Likes
function GetNumDaysAbove2(price_arr, NumDays)
{
	return NumDays - PercentRank(price_arr, NumDays)* 0.01* NumDays;
	//return NumDays - round(PercentRank(price_arr, NumDays)* 0.01* NumDays);
}

The original question was "<" instead of "<=".
Therefore you need:

function GetNumDaysAbove(price_arr, NumDays)
{
	return PercentRank(-price_arr, NumDays)* 0.01* NumDays;
	//return round(PercentRank(-price_arr, NumDays)* 0.01* NumDays);
}
2 Likes