How to make this code that counts the number of times a certain event happened in the past more elegant?

I have the following code for function count_event to count the number of times a certain condition related to an event happened in the past.

The problem with this code is it manually gets the information regarding each event one by one. It manually gets 3 events in the past defined by numBars which is the number of bars in the past to count the events. It is entirely possible that far more than 3 events happened in the past. I do not know how to work around this problem due to the way Amibroker handles array.

//get number of bars that have passed since nth occurrence when array was true
function bars_since_n(array, nth_occurence)
{
	bi = BarIndex();
	bars_since_nth = bi - ValueWhen(  array, bi, nth_occurence );
	
	return bars_since_nth;
}

//Count number of times a certain condition related an event happened in the past defined by numBars
function count_event(numBars)
{
	event_high = get_event();
	
	bars_since_high_1 = bars_since_n(event_high, 1);
	bars_since_high_2 = bars_since_n(event_high, 2);
	bars_since_high_3 = bars_since_n(event_high, 3);
	
	event_high_1 = ValueWhen(event_high, High, 1);
	event_high_2 = ValueWhen(event_high, High, 2);
	event_high_3 = ValueWhen(event_high, High, 3);
			
	count_1 = iif((event_high_1 >= 0.99*Close AND bars_since_high_1 <= numBars), 1, 0 );
	count_2 = iif((event_high_2 >= 0.99*Close AND bars_since_high_2 <= numBars), 1, 0 );
	count_3 = iif((event_high_3 >= 0.99*Close AND bars_since_high_3 <= numBars), 1, 0 );
		
	count = count_1 + count_2 + count_3;
	
	return count;
}

Have you tried functions like Sum , SumSince , Cum ?

1 Like

Here you go... as for repetitions -> we do iterate....

In cum_events variable in my below loop version of last function of first code you can set max. nth_occurence.


// Sample event within array

function get_event() {

     return C > O;
}

//get number of bars that have passed since nth occurrence when array was true
function bars_since_n(array, nth_occurence)
{

     bi = BarIndex();

     bars_since_nth = bi - ValueWhen( array, bi, nth_occurence );

     return bars_since_nth;
}

//Count number of times a certain condition related an event happened in the past defined by numBars
function count_event(numBars)
{
    	/// code source

     /// @link [https://tinyurl.com/yxh3rhzj](https://tinyurl.com/yxh3rhzj)

/// loop version by fxshrat@gmail.com

event = get_event();

     cum_events = LastValue(Cum(event)); // LastVisibleValue(Cum(event));//

     //_TRACEF( "%g", cum_events);

//

count = 0;

pcnt_close = 0.99*Close;

// we start at zero in case cum_events being zero

// iterates to max. set value numBars

for ( i = 0; i <= Min(numBars, cum_events); i++ )	{

          if ( i > 0 ) {

               bars_since_high = bars_since_n(event, i);

               event_high = ValueWhen(event, High, i);

               cond = Nz(event_high >= 
pcnt_close
AND bars_since_high <= numBars);

               count += cond;

          }

     }    

     return count;
}

cnt = count_event(numbars = 10);
Plot( cnt, "cnt", colorRed );

Note: only converted to loop. Not checked for more simplicity.

If you do this (using Sum) then it's differently.


// Sample event within array

function get_event() {

     return C > O;
}

event = get_event();
event_high = IIf(event, H, 0);
cnt = Sum(event_high >=
0.99*Close, numbars = 10);
Plot( Cnt, "cnt", colorRed );

Anyway the loop version returns the same results as the code of first post
if that's what you want it to be returned
(for comparison set cum_events = 3; and in both ones e.g. numBars = 10).

5 Likes

Both solutions tested to work. I like your second solution more. It is more in step with Amibroker array architecture. Thank you very much.

// Sample event within array

function get_event() {

     return C > O;
}

event = get_event();
event_high = IIf(event, H, 0);
cnt = Sum(event_high >=
0.99*Close, numbars = 10);
Plot( Cnt, "cnt", colorRed );
1 Like

@thankyou18,

you are mistaken. Sorry for confusion I may have caused.

Please note... The two versions are not doing the same thing!

If you intend to do the same things as in your first post's code then you would need to use the loop version (and it is array architecture). In your 1st post's code you intend to count the occurrences where past highs at n past events are greater than "current" x*Close.


That is not what the second code I posted is doing.
I have clearly written that the second one using Sum() is different one.
It does different thing that you do not want (according to first post's code).

The second code (following one)

// Sample event within array
function get_event() {
   return C > O;
}

event = get_event();
event_high = IIf(event, H, 0);
cnt = Sum(event_high >= 0.99*Close, numbars = 10);
Plot( Cnt, "cnt", colorRed );

is doing the same thing as next following one (because in upper code "current" high at event is always greater or equal than "current" close at event... so you can remove that condition and simply replace it by event variable.. it will have the same outcome):

// Sample event within array
function get_event() {
   return C > O;
}

event = get_event();
cnt = Sum(event, numbars);
Plot( Cnt, "cnt", colorRed );

So both ones just count C > O (or any other set condition's) true occurrences over certain number of bars. So they got nothing to do with comparing past highs at event to current Close (as you do in 1st post).


That's what the looping version is doing. So it is completely different kind of animal than upper Sum() ones. But it is doing the "same" as your first's post code but just more flexibly... e.g. you don't need to write ten times x 2 times = 20 times ValueWhen.

I am re-posting the loop one since format got messed up through sending it by mail.

// Sample event within array
function get_event() {
    return C > O;
}

//get number of bars that have passed since nth occurrence when array was true
function bars_since_n(array, nth_occurence)
{
    bi = BarIndex();
    bars_since_nth = bi - ValueWhen( array, bi, nth_occurence );
    return bars_since_nth;
}

//Count number of times a certain condition related an event happened in the past defined by numBars
function count_event( numBars )
{
    /// code source
    /// @link https://tinyurl.com/yxh3rhzj
    /// loop version by fxshrat@gmail.com
    event = get_event();
    cum_events = LastValue(Cum(event)); //LastVisibleValue(Cum(event));//
    //_TRACEF( "%g", cum_events);
    //
    count = 0;
    pcnt_close = 0.99 * Close;
    event_num = Min(numBars, cum_events);
    // we start at zero in case cum_events being zero
    // iterates to max. set value numBars
    for ( i = 0; i <= event_num; i++ ) {
        if ( i > 0 ) {
            bars_since_high = bars_since_n(event, i);
            event_high = ValueWhen(event, High, i);
            cond = Nz(event_high >= pcnt_close AND bars_since_high <= numBars);
            count += cond;
        }
    }

    return count;
}

numbars = 10;

SetBarsRequired(numbars);

cnt = count_event(numbars);
Plot( cnt, "cnt", colorRed );
6 Likes