Array Subscript out of Range Error

Moderator comment: Instead of posting to forum each and every question press F1 in the program. All errors are explained in detail in the help file
http://www.amibroker.com/guide/errors/10.html . There is also plenty of additional material in the Knowledge Base: http://www.amibroker.com/kb/2014/09/22/do-not-make-assumptions-on-number-of-bars/

I am new to AFL programming. I am writing a function to count a streak of closing prices s.t. each subsequent closing price is higher than the previous one. That is, we have C[k] > C[k+1]. This assumes C[0] is the lastest closing price, c[1] the day before and so on (to be clear, Is this correct?) Here is the code...

function StreakCountN( n )
{
    k = C;
	count = 0;
	for( i = 0; i < n; i++ ) {
		if ( C[ i ] > C[ i + 1 ] )
			count++;
	}
  return count;

Any help in these matters is appreciated.

[ i + 1 ] is looking into future. I have changed to [ i - 1 ].
In AFL "[i-n]" means accessing previous bars. "[i+n]" accesses future bars.

function StreakCountN( n )
{
    k = C;
	count = 0;
	for( i = 1; i < n && n <= BarCount; i++ ) {
		if ( C[ i ] > C[ i - 1 ] )
			count++;
	}
  return count;
}
2 Likes

@pmfiorini, as demonstrated in the example of @codejunkie, keep in mind that AmiBroker bars are indexed differently from other platforms.

Directly quoting the official documentation:

“Accessing array elements: [ ] - subscript operator

An array identifier followed by an expression in square brackets ([ ]) is a subscripted representation of an element of an array object.

arrayidentifier [ expression ]

It represents the value of expression-th element of array.

BarCount constant gives the number of bars in array (such as Close, High, Low, Open, Volume, etc).

Array elements are numbered from 0 (zero) to BarCount-1.

BarCount does NOT change as long as your formula continues execution, but it may change between executions when new bars are added, zoom factor is changed or symbol is changed.

To get the first bar you can use array[ 0 ], to get the last bar of array you can use array[ BarCount - 1 ];

For example:

Close[ 5 ];

Represents the sixth element (bar) of the close array.

Close[ 0 ];

Represents the very first available bar of the close array.

High[ BarCount - 1 ];

Represents the last bar of High array.

This means that each time you use a loop you should verify that you index is always >= 0 AND < BarCount.

Since you are new to AFL, I recommend studying this thread to better understand how to work with Amibroker Formula Language: you'll find that many times no loop is needed.

2 Likes

@pmfiorini how about a simple way of using arrays?

UpBarStreak = BarsSince(C<=Ref(C, -1));
4 Likes
function StreakCountN( n )
{
    k = C;
	count = 0;
	for( i = 0; i < n; i++ ) {
		if ( C[ i ] > C[ i + 1 ] )
			count++;
	}
  return count;
  }
  
  
  x=StreakCountN( BarCount-1 );

You were missing a right bracket "}". Also make sure that "n" parameter is not greater than Barcount-1.

Also, check this out:

1 Like

Ok - so I updated the code - One of the problems was that I did not know that C[BarCount-1] is the last closing price of the underlying. So here is the modified code and I am still getting an "Array Subscript out of Range Error" - I have no idea what is going on. When I debugged the code, the indexing seemed Ok (I am new so I must be missing something) - Thanks in advance...

function StreakCountN( n )
{
	iters = 0;
	count = 0;
	for( i = BarCount - 1; i > BarCount - n - 1; i-- ) {
		iters++;
		if ( C[ i ] > C[ i - 1 ] )
			count++;
	}
  return count;
}

Quite honestly, I do not understand this code at this point - Let me digest this answer - Thanks

I'm not following you...

Here is the updated code and I'm still getting the error...

function StreakCountN( n )
{
	iters = 0;
	count = 0;
	for( i = BarCount - 1; i > BarCount - n - 1; i-- ) {
		iters++;
		if ( C[ i ] > C[ i - 1 ] )
			count++;
	}
  return count;
}

Nice answer. Thanks for your time - Let me look into this. A lot to learn!

@pmfiorini, as you are new to AmiBroker and AFL, this might help you get up to speed a bit quicker to understand the Array processing.

Think of it like Excel. You have a Row of Prices, and the Columns are the days.
So you have rows with Open, High, Low, Close, and Volume.

Now you want to do a calculation, you will need to write the code in a cell that ONLY references Rows above and Cells above and/or to the Left. For Example: Midpoint =(H + L)/2

Since your new Row - Midpoint is Below the H & L rows, you can reference them.

Similarly, a new Row - PriorClose = Close from one Column to the left of the current cell.

Thinking this way should help you get started.

Next step is to READ READ READ the Manual. After the Tutorial, check out the Function References. Specifically see if you can understand BarsSince and Ref from @portfoliobuilder's suggestion.

This is ok:

x = StreakCountN( 10 );

This cause the subscript error:

x = StreakCountN( 100000 );

You should make sure that the indexes [i] and [i-1] always stay within the range 0..barcount-1.

The problem lies here: C[ i - 1 ]

When i==0 the i-1 becomes nagative ==> ERROR.

When i becomes 0, it means that :
i > BarCount - n - 1 =>
0 > BarCount - n - 1 =>
n > BarCount - 1

Therefore you need to make sure that:
n <= Barcount-1

Here is a code that always works:

function StreakCountN( n )
{
	n = Min(n, BarCount-1);

	iters = 0;
	count = 0;

	for( i = BarCount - 1; i > BarCount - n - 1; i-- ) {
		iters++;
		if ( C[ i ] > C[ i - 1 ] )
			count++;
	}
  return count;
}

BTW, you need to clean this up, I don't know exactly what you want to do:

i > BarCount - n - 1;
1 Like

Hi..
Please find the below code

_SECTION_BEGIN("creating dynamic array");
array=0;
i=0;
while (i<10)
{
array[i]=i;
i=i+1;
}
AddColumn(array,"array values");
_SECTION_END();

When i run the code in the editor it is working fine as expected. But the same code if i run through explorer getting the error as "Array subscript out of range.You must not access array elements outside o barcount-1 range. you attempt to access non existing of 7th element of array." Please let me know the issue. you can reproduce the issue just to run the program in explorer window.
Please find the attachment for more details.Dynamic%20array_error

First of all read about how to add code taggs if adding code to forum posts.

Secondly, read here about not making assumptions on available bars.

So several examples to prevent subscript being outside of Barcount range error message...

_SECTION_BEGIN("creating dynamic array");
array = 0;
i = 0;
while ( i < 10 && i < BarCount )
{
    array[i] = i;   
    i++;
}
AddColumn(array,"array values");
Filter = 1;
_SECTION_END();
_SECTION_BEGIN("creating dynamic array");
array = 0;
i = 0;
while ( i < Min(10, BarCount) )
{
    array[i] = i;   
    i++;
}
AddColumn(array,"array values");
Filter = 1;
_SECTION_END();
_SECTION_BEGIN("creating dynamic array");
array = 0;
i = 0;
while ( i < 10 ) 
{
    if ( i < BarCount )
    {
        array[i] = i;
    }
    i++;
}
AddColumn(array,"array values");
Filter = 1;
_SECTION_END();
_SECTION_BEGIN("creating dynamic array");
array = 0;
i = 0;
if( BarCount > 10  ) 
{
	while ( i < 10 ) 
	{
		array[i] = i;
		i++;
	}
}
AddColumn(array,"array values");
Filter = 1;
_SECTION_END();
3 Likes

A few issues here:

  1. you're new to AB, and having a go, that's a good thing, IMO.
  2. providing code, and explanations & examples of the type of problem and where/ when being experienced, even better.
  3. your use of "C[k] > C[k+1]" and "This assumes C[0] is the lastest closing price, c[1] the day before and so on", suggests that you didn't/ don't understand how AB indexes quotes, which is potentially a source of errors in your code. You probably do understand it by now.
  4. I don't understand the purpose of the n argument to the function.

In regard to #3, I presume you mean that the closing price today is higher than yesterday's closing price.

When putting your original code, and @bobptz's into an AFL, I get horizontal lines, whose value "jumps" around a lot when scrolling backwards and forwards. Also, I don't understand what your function is doing - loops can be very useful, but they're always a headache, and need lots of time to think them through properly. Did I also mention that they're hard to debug.:

SetChartOptions(0,chartShowArrows|chartShowDates|chartWrapTitle);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("PriceColor", colorBlack ), ParamStyle("PriceStyle", styleCandle, maskPrice)); 


function StreakCountN1( n )
{
    k = C;
	count = 0;
	for( i = 1; i < n; i++ ) {
		if ( C[ i ] > C[ i - 1 ] )
			count++;
	}
  return count;
}

function StreakCountN2( n )
{
	n = Min(n, BarCount-1);

	iters = 0;
	count = 0;

	for( i = BarCount - 1; i > BarCount - n - 1; i-- ) {
		iters++;
		if ( C[ i ] > C[ i - 1 ] )
			count++;
	}
  return count;
}


selMaxStreak	= Param("selMaxStreak", 2, 1, 100, 1, 1) ;

clcStreak1	= StreakCountN1(selMaxStreak) ;
clcStreak2	= StreakCountN2(selMaxStreak) ;

Plot(clcStreak1, "clcStreak1", ParamColor("Streak1", colorCycle), ParamStyle("Streak1 style", styleLine + styleOwnScale)) ;
Plot(clcStreak2, "clcStreak2", ParamColor("Streak2", colorCycle), ParamStyle("Streak2 style", styleLine + styleOwnScale)) ;


// Break the problem down into manageable chunks
function Streaker1(inpArray) 
{
	isHigher = inpArray > Ref(inpArray, -1) ;
	return BarsSince(!isHigher) ;
}

// Now, optimise it for speed - remove any unnecessary/ intermediary steps.
function Streaker2(inpArray) 
{
	return BarsSince(!(inpArray > Ref(inpArray, -1))) ;
}

clcStreaker1		= Streaker1(Close) ;
clcStreaker2		= Streaker2(Close) ;
Plot(clcStreaker1, "clcStreaker1", ParamColor("Streaker1", colorCycle), ParamStyle("Streaker1 style", styleLine + styleOwnScale)) ;
Plot(clcStreaker2, "clcStreaker2", ParamColor("Streaker2", colorCycle), ParamStyle("Streaker2 style", styleLine + styleOwnScale)) ;

Towards the end, are a couple of new functions which use array processing, ie. no loops - my interpretation of what you're trying to achieve in the original question.