Initialized array values are not as expected. Teach me please

Hi All,

I am new to AmiBroker, and this is my first question.
If there are any possible improvements to my question, then please advice.

The code below represent my problem.
In the code, I initialized inTradeArray to 0. Then in the following loop I check and change inTradeArray's value to 1 if a buy is detected. The value should remain 1 for the rest of the array. I expect the code to produce an array with initial values of 0, then after the first buy signal, the rest of the array should be 1. But instead I got an array that start with 1 in the Exploration result.

The codes:

Buy = Cross( Close, EMA( Close, 14 ) );

inTradeArray = 0;

for( i = 1; i < BarCount; i++ )
{
    inTrade = inTradeArray[i - 1];

    if( inTrade == 0 AND Buy[i] )
    {
        inTrade = 1;
    }

    inTradeArray[i] = inTrade;
}

Filter = 1;
AddColumn( Close, "Close", 1.5 );
AddColumn( EMA( Close, 14 ), "EMA", 1.5 );
AddColumn( Buy, "Buy", 1, IIf( Buy, colorGreen, colorDefault ) );
AddColumn( inTradeArray, "In Trade Array", 1, IIf( inTradeArray, colorGreen, colorDefault ) );

Exploration result:

image

I expect the rows before the highlighted one to be value 0 for inTradeArray. Can anyone explain to me what I missed please. Thank you.

P.S. I wish I knew about AmiBroker five years earlier! What a great software!. I'm glad to join AmiBroker.
Thank you @Tomasz

see this posting.

See : AFL Reference Manual:

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.

If you really want to use a loop, then try this slightly modified code instead:

Buy = Cross( Close, EMA( Close, 14 ) );

inTradeArray = 0;

for( i = 1; i < BarCount; i++ )
{
    inRange = Status("BarInRange"); //Save to inRange array.
    if (inRange[i])  //Check inRange array.
	{
		inTrade = inTradeArray[i - 1];
		if( inTrade == 0 AND Buy[i] )
		{
			inTrade = 1;
		}

		inTradeArray[i] = inTrade;
	}	
}


Filter = 1;
AddColumn( Close, "Close", 1.5 );
AddColumn( EMA( Close, 14 ), "EMA", 1.5 );
AddColumn( Buy, "Buy", 1, IIf( Buy, colorGreen, colorDefault ) );
AddColumn( inTradeArray, "In Trade Array", 1, IIf( inTradeArray, colorGreen, colorDefault ) );

2 Likes

And if you prefer to do this without loops and take advantage of Amibroker's array processing then try this:

Buy = Cross( Close, EMA( Close, 14 ) );
inRange = Status("BarInRange");
BuyInRange = Buy AND inRange;
InTradeArray = HighestSince(BuyInRange,BuyInRange,1);  

Filter = 1;
AddColumn( Close, "Close", 1.5 );
AddColumn( EMA( Close, 14 ), "EMA", 1.5 );
AddColumn( Buy, "Buy", 1, IIf( Buy, colorGreen, colorDefault ) );
AddColumn( InTradeArray, "In Trade Array", 1, IIf( inTradeArray, colorGreen, colorDefault ) );
2 Likes

Thank you very much @SwingTradeMonkey.

Wow, I really did missed this. Didn't picked it up on my first manual read through. Thank you for your time.

Great software, great community. I'll strive to be one the contributors in the future. Practice time!.

1 Like

@SwingTradeMonkey,

Your code is not the solution because it is wrong AFL programming! Have you actually read the code I have posted in your linked thread? No, you haven't (for whatever reasons).

Do you see anywhere in that code I posted there in that other thread (if you can see it) that I have added Status( "BarinRange" ) within the Barcount loop? Exactly I have not added it because Status("barinrange") returns an array! Arrays and array functions don't belong within barcount loop.

Your upper code shows that you have NOT yet understood how arrays work and how you deal with them.

This is how you do it:


bir = Status("BarInRange"); //Store array to variable bir

for( i = 1; i < BarCount; i++ )
{   
    if (bir[i])  //Check whether element is within set analysis range
	{
		// do something
	}	
}


SwingtradeMonkey's post should not be marked as solution because it is misleading and just animates beginners to write code in wrong way.

1 Like

@fxshrat Oops... No good deed goes unpunished! You are correct. I should have put the status("BarInRange") outside the loop. My bad. I'm only human...sorry about that. Good catch! I am glad I'm not the only one here trying to help. :grinning:

Any comments on the alternative code?

1 Like

Instead of

InTradeArray = HighestSince(BuyInRange,BuyInRange,1); 

You can do just that

InTradeArray = ValueWhen(BuyInRange, 1);

Or

InTradeArray = Nz(ValueWhen(BuyInRange, 1));

If wanting to have same output as with loop version of this thread.

BTW, which deed? In this case it has been other's wasted time (in this case my one in that other thread) since you haven't read/applied already existing post/code properly. I mean how much more obvious should a very small code have been posted?

@fxshrat But he led me to

Status("BarInRange");

which help solved my problem. Sorry!

Here summarizes the solution.

@SwingTradeMonkey posted:

see this posting.

See : AFL Reference Manual:

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.

@fxshrat Corrected code.

This is how you do it:


bir = Status("BarInRange"); //Store array to variable bir

for( i = 1; i < BarCount; i++ )
{   
    if (bir[i])  //Check whether element is within set analysis range
	{
		// do something
	}	
}

Thank you! @fxshrat.

2 Likes

General rule that must be followed at all times is put all loop-invariant code OUTSIDE the loop.