Paul
Paul

Reputation: 297

Seemingly wrong evaluation of simple condition inside a function

I want to have a function that usually returns the integer 100, but deviates from that, when certain conditions are met, in my case if the given oscillator (rsi) is below 20. In case the close price at that time is closer to the 100 day price minimum than the maximum the return value shall rise above 100, if closer to the maximum it shall fall below.

But strangely in most cases (but not all) the value returned behaves exactly the other way.

I have plotted all the relevant values in the two following Screens (green > 50 means closer to highest < 50 closer to lowest; teal is the return value of the function, and red is the rsi, the blue function should only change, when that is below 20 - which it does). I highlight the bars where the conditions for increase of the blue line are met with green background (the conditions for rising are not met in the examples), that is done correctly, so outside of a function evaluation of the same condition does work as intended..

Screen of wrongly falling teal line

Screen of wrongly falling teal line As you can see, the background is colored green, so the expression rsi <= 20 and closeRelativeToHighestLowest() <= 50 is evaluated correctly inside the bgcolor() function.

Screen of correctly rising teal line

Screen of correctly rising teal line

Here also the background is colored green, so with the evaluation of the comparison nothing is different - at least in the bgcolor() function.

Here is my code:

//@version=4
study("My lookback minimum example")

closeRelativeToHighestLowest() =>
    ret = (close - lowest(low,100)) * 100 / (highest(high,100) - lowest(low,100))
    ret

myOptimalLookback(oscillator) => // will increase currentLength if oscillator is low and above optimalLevelForLow (relative to highest/lowest)
    ret = 100
    if oscillator <= 20
        if (closeRelativeToHighestLowest() > 50) //same condition as outside of function
            ret := round(ret[1] * 0.9)
        else
            ret := round(ret[1] * 1.12)
    ret := max(min(ret, 200), 10) // cap ret at 10 and 200


rsi = rsi(close, 10)
var lookback = 100
lookback := myOptimalLookback(rsi)

plot(lookback)
plot(closeRelativeToHighestLowest(), color = color.green)
plot(rsi, color = color.red)
hline(20)
hline(50)
bgcolor(rsi <= 20 and closeRelativeToHighestLowest() > 50 ? color.red : na)
bgcolor(rsi <= 20 and closeRelativeToHighestLowest() <= 50 ? color.green : na)

Any ideas what could be tried to narrow down the problem?

Upvotes: 1

Views: 134

Answers (1)

PineCoders-LucF
PineCoders-LucF

Reputation: 8779

Evaluation of conditional branches has changed in v4. Contrary to prior versions, all branches are no longer evaluated all the time, so it's safer (and often necessary) to pre-evaluate function calls prior to entering conditional branches. See Release Notes:

myOptimalLookback(oscillator) => // will increase currentLength if oscillator is low and above optimalLevelForLow (relative to highest/lowest)
    ret = 100
    c = closeRelativeToHighestLowest()
    if oscillator <= 20
        if (c > 50) //same condition as outside of function
            ret := round(ret[1] * 0.9)
        else
            ret := round(ret[1] * 1.12)
    ret := max(min(ret, 200), 10) // cap ret at 10 and 200

Upvotes: 1

Related Questions