For loop doesn't accept array. How to work around for this code?

The following code will calculate the high-low range in percentage of certain bars when an event occurred and calculate the average of the high-low range.

event_up = get_event_up();
event_down = get_event_low();	
num_events_in_range = get_num_events_in_range();

sum_pct_updown_dist = 0;
for (i=1;i<num_events_in_range; i++) //for cannot accept array type	
	event_up_high_i = ValueWhen(event_up, High, i);
	event_down_low_i = ValueWhen(event_down, Low, i);
	pct_updown_dist_i = (event_up_high_i-event_down_low_i)/event_up_high_i*100;
	sum_pct_updown_dist = sum_pct_updown_dist + pct_updown_dist_i;

avg_pct_updown_dist = sum_pct_updown_dist/num_events_in_range;

The code doesn't work in Amibroker because of this line for (i=1;i<num_events_in_range; i++) which violates Amibroker syntax. For loop does not accept array type. num_events_in_range is an array.

How can this code be modified to work around this problem?

Understanding how AFL works.
AmiBroker AFL loop.

The end value of loop range within loop statement can not be array. It is has to be number.
So to get element of array there is e.g. LastValue() function.

end_value = LastValue(num_events_in_range);

for (i=1;i<end_value; i++) 

1 Like

Thank you for the answer. It is partially correct. If I were to use end_value = LastValue(num_events_in_range);, then the correct answer will be only for the last bar. A slight improvement will be SelectedValue(num_events_in_range) but this will not work for back-testing and exploration on past specific dates.

get_num_events_in_range() returns an array which may have different value for every bar. This is why it presents to me a headache when using it in the for loop which violates Amibroker syntax.

No! It is not partially correct. Post #2 is technically completely correct!
Don't tell nons.... if you do not get it.

And as for number of events all you need is LastValue(...) otherwise you would have to create nested loop.

In general if i is higher than actual number of events at "current" bar then all that is happening is ValueWhen returning EMPTY (Null) so result (sum_pct_updown_dist) will be EMPTY too. So all you have to do is converting EMPTY to zero via Nz() function.

And no, it will not create for last bar only.

bi = BarIndex();
event1 = bi % 10 == 0;
event2 = bi % 20 == 0;
event = IIf(event1==event2 AND event1 > 0, 1, event1+event2);
event_num = Cum(event);//SumSince(bi == FirstVisibleValue(bi), event);
end_value = LastValue(event_num);

sum_pct_updown_dist = 0;
for (i=1;i<end_value; i++) 
	event_up_high_i = (ValueWhen(event1, High, i));
	event_down_low_i = (ValueWhen(event2, Low, i));
	pct_updown_dist_i = (event_up_high_i-event_down_low_i)/(event_up_high_i+1e-9)*100;
	sum_pct_updown_dist += Nz(pct_updown_dist_i);

avg_pct_updown_dist = sum_pct_updown_dist/event_num;

I have tested and confirmed that you are absolutely right and I am wrong. Thank you for your helpful posts.

I re-read the documentation on lastvalue. It says "Returns last calculated value of the specified ARRAY." I took the function name literally and had the misconception that it will return only the last bar value.

1 Like