Page 1 of 1

Check if condition first becomes true and holds within n bars?

Posted: Mon Apr 12, 2021 11:42 pm
by stakeprophet
I want to create a function to check if a condition first becomes true anywhere within a history of n bars, and if it does return true for the first bar and return true for every subsequent bar within the range where the condition held true without breaking the series of trues since the first. I understand barssince may work for this but causes repainting so not an option for me.

e.g if n = 0 bars the function is only true when the condition is true on the current bar but not the bar immediately previous n + 1. If instead the function input is n > 0 bars, for the function to return true the condition must become true somewhere m within n history of bars, but false for m + 1, and any bar after m within n history forming a series of unbroken true conditions the function will also return true.

In this crude example where n = 4 for bars[3,2,1] the function would return true but if n = 2 no bars would be true because the condition first became true outside of n at bar[3]:

Code: Select all

    bars: 76543210
    cond: 00001110
I am also interested in an alternate function version that would only return true if after the condition first becomes true, anywhere within n history, the condition must hold true until the current bar[0]. This version could only every return false for the previous example but would return true for any n <= 3 in this example:

Code: Select all

    bars: 76543210 
    cond: 00001111
Some of my attempts to code this seem to check for one of these versions correctly but for some reason when I plot the output it is only marking the nth bar true when instead I would like it to mark all bars where the function was true within n history bars. If you can see the problem please let me know:

Code: Select all

    f_confirmCond(_n) =>
        for _i = 0 to _n
            _i == _n ? cond[_i] and not cond[_i+1] : cond[_i]


    f_confirmCond(_n) =>
        for _i = 0 to _n
            if (not cond[_i])
                false
            else
                if (_i == _n)
                    cond[_i] and not cond[_i + 1]
                else
                    cond[_i]


    f_confirmCond(_n) =>
         if (not cond[0])
             false
         else 
             for _i = 0 to _n
                 if (_i == _n and (cond[_i] and not cond[_i + 1]))
                     for _i = 0 to _n
                         true
    f_confirmCond(_n) =>
        _confirmCond = true
        _j = 0
        _found = false
        for _i = _n to 0
            if (_found == false and cond[_i] and not cond[_i+1])
                _found := true
            _confirmCond := _confirmCond and cond[_i] and (_found == false? not cond[_i+1] : true)

Re: Check if condition first becomes true and holds within n bars?

Posted: Tue Apr 13, 2021 7:15 am
by K4eMi
Can de Cond function you calling be something like close<sma(50,close)? and you verifying if the last 4 bar are below the sma 50?

in order for me to take a look at this

Re: Check if condition first becomes true and holds within n bars?

Posted: Tue Apr 13, 2021 9:44 am
by stakeprophet
I think it should work for that though I thought it should work for any function.

In the example you suggested the function should only return true for the last 4 bars if all 4 bars were below sma 50 AND bar[5] was > 50. I am trying to check if the condition *starts* being true within the last n bars and if so mark the first bar true AND any condition true bar following the first bar *without a false condition bar between the true condition bars*.

Basically instead of my function returning true just when the condition is true on the current bar[0], I want it to return true if:

condition *starts* being true on the current bar[0] OR the previous bar[1]

OR

condition *starts* being true on the current bar[0] OR the previous bar[1] OR bar[2]

OR

condition *starts* being true on the current bar[0] OR the previous bar[1] OR bar[2] OR... ...bar[n]


Below are some steps that may be how I should approach this:

Code: Select all

for i ← 0 to n do
     if condition true for current bar[i] and not true for the previous bar[i + 1]
           return true and exit function
     else
          If condition true for previous bar[i + 1] and not true for bar[i + 2]
                return true and exit function
false