Reversed array that causes Barcount error

Hi mates, I'm having some troubles with barcount. I've searched into the forum and into the KB but I can't find a solution.

Generally speaking, the main scope of the script I'm writing is to evaluate some parameters for generating events and then sort those events in a way that the more recent are consecutively and in inverse order at the beginning of an "event array" (so the more recent events have lower index).

My idea is to let a function determine the events and return a (generally sparse) array then the main part of the script compresses and inverses the array to get the latter events at the beginning of the event array.

Seeing that the program I'm working on is quite chumbersome, I've recreated the issue by the following dummy script.

Here's the code:

function testFunction(tgtBarIndex)	//dummy function - only for recreating the issue
{
	ans = null;
	for (i = 0; i < tgtBarIndex; i++)
	{
		ans[i] = i % 10;
	}
	return ans;
}

//	main script
SetBarsRequired(sbrAll, sbrAll);
targetBarIndex = 2000;
values = testFunction(targetBarIndex);
multiplyPositions = IIf(values == 0, BarIndex(), Null);
compressedValues = SparseCompress(multiplyPositions, multiplyPositions);
reversedMultiplyPositions = Reverse(compressedValues);
p0_pos = reversedMultiplyPositions[0];
p0_val = C[p0_pos]; 

PlotOHLC(O, H, L, C, "", colorBlack, styleBar);
PlotShapes(IIf(BarIndex() == p0_pos, shapeCircle, shapeNone), colorBlue, 0, p0_val,0);

The problem is that when I run in debug mode (code check and profile, and also line by line debugging) everything is ok, but when I try to apply the script Amibroker responds with an indexing error.
Precisely the error is a reference to an inexistent 200th bar, despite the fact I've forced to use all the bars via the command

SetBarsRequired(sbrAll, sbrAll);

and the that the time series is long more than 2000 (BarCount >2000).

Here's the screenshots:

code check and profile returns no errors:
Schermata 2022-12-05 alle 07.20.50

line by line debugging shows no errors:
Schermata 2022-12-05 alle 07.20.24

Apply this script to the chart causes the BarCount error:
Schermata 2022-12-05 alle 07.21.08

I'm using version 6.42.0, build date: Nov 27 2022 Pro 64bit

Can you replicate this issue? What I'm doing wrong here? why the difference between code check and application to the chart?

Print out the BarCount _TRACEF("BarCount: %g", BarCount) prior to calling testFunction but after you've called SetBarsRequired. You'll likely find that this number is strictly less than the hardcoded 2000 barcount you've provided.

Here is your testFunction with annotations

function testFunction(tgtBarIndex)	//dummy function - only for recreating the issue
{
	ans = null; // ans here is a SCALAR of value -1000000000.00000
        // this is what _TRACEF("%f", ans) is telling me

	for (i = 0; i < tgtBarIndex; i++)
        // when iterating over an Amibroker array, you almost always
        // want for ( ...., i < BarCount - 1, ...), nothing else
        // I have not seen an Amibroker array that was any more or any less
        // than of size BarCount

	{
		ans[i] = i % 10; 
        // the first time you refer to a offset of ans, even ans[0]
        // Amibroker will convert ans into an array of size BarCount
	}
	return ans;
}

The _TRACEF function just dumps to the windows debug log, be careful stepping through the debugger as it is limited ( via Preferences ) a small number of bars so as not to overwhelm so I find logging to be a much more reliable way of getting the root causes of these things.

Hope that helps.

1 Like

On re-read, you might actually be hitting something to do with this. The 200th element is just too convenient a place to stop.

I think your debugger is limiting count to 200 hence index 200 is out of bounds ( 0 - 199 )

image

You are making invalid assumptions.

Please read the Knowledge Base:

1 Like

Thank you Joe and Tomasz for your help, both of your ideas has been precious for pointing me into the right way.
I finally found that the issue is caused by the loop length.
According to the knowledge base article, to avoid the error I substituted the hardcoded end of the loop with BarCount and for breaking the loop at the target bar I've added a checking inside the loop.

This is the test function code that works:

function testFunction(tgtBarIndex)	//dummy function - only for recreating the issue
{
	ans = null;
	for (i = 0; i < BarCount; i++)
	{
		ans[i] = i % 10;
		if ( i == tgtBarIndex)
			break;
	}
	return ans;
}

According to the knowledge base:

" 1. during AFL Editor’s Verify Syntax not more than 200 most recent bars are used "

the debugger probably skipped the issue for the above reason, but it is not still clear to me how the debugger can correctly determine the events and loop thru 4542 data bars (see above screenshot) only using the 200 most recent bars, but clearly it do it so :slightly_smiling_face:

BTW you don't need any loop

function testFunction(tgtBarIndex)	//dummy function - only for recreating the issue
{
	//ans = null;
	//for (i = 0; i < BarCount; i++)
	//{
	//	ans[i] = i % 10;
	//	if ( i == tgtBarIndex)
	//		break;
	//}
	
	ans = IIf(BarIndex() <= tgtBarIndex, BarIndex() % 10, Null);
	return ans;
}

1 Like

Verify Syntax operation does NOT involve the debugger. These are two different operations. Verify Syntax is done WITHOUT running debugger, if you for example press "Apply Indicator" or "Send to analysis"

1 Like

hi fxshrat and thank you for your hint. The function I've written above is very simplified and returns only one value. In my original script, the function returns several parameter at the same time (via VarSet() function).

Thank to your suggestion, I've just tried and learned that I can embed any function inside IIF(), for example:

function squareXplus3(val)
{
	return (val^2 + 3);
}

SetBarsRequired(sbrAll, sbrAll);

bi = BarIndex();
startIndex = 0;
endIndex = 20; 
x = IIf(bi >= startIndex AND bi <= endIndex, Cum(1), Null);
y = IIf( bi >= startIndex AND bi <= endIndex, squareXplus3(x), null);

Plot(x, "X", colorLightBlue, styleLine|styleThick);
Plot(y, "y", colorPink,styleline|styleThick);

that produces:
Schermata 2022-12-05 alle 18.27.41

And I further learned that it works also for multiple parameters:

function powX_multipleReturn(val)
{
	VarSet("squared", val^2);
	VarSet("cubed", val^3);
	return val;
}

SetBarsRequired(sbrAll, sbrAll);

bi = BarIndex();
startIndex = 0;
endIndex = 10; 
x = IIf(bi >= startIndex AND bi <= endIndex, Cum(1), Null);
y = IIf( bi >= startIndex AND bi <= endIndex, powX_multipleReturn(x), null);
sq = IIf( bi >= startIndex AND bi <= endIndex, VarGet("squared"), null);
cu = IIf( bi >= startIndex AND bi <= endIndex, VarGet("cubed"), null);

Plot(x, "X", colorLightBlue, styleLine|styleThick);
Plot(y, "val", colorBlack, styleLine|styleThick);
Plot(sq, "squared", colorPink,styleline|styleThick);
Plot(cu, "cubed", colorGreen,styleline|styleThick);

that produces this:
Schermata 2022-12-05 alle 18.52.40

Many thanks, really , this idea should be very useful for my future projects, and I hope for others here in the forum :slightly_smiling_face:

Hi Tomasz, ok got it.
The thing that fools me is the statement "4542 data bars used during this check" that appear when I profile the code. this value is also confirmed by the variable watch.
This made appear at my eyes that the code was run on the whole dataset.