bt.If operator/function

Is there a version of
bt.If
function that only returns the True value? (instead of the True value or False value)
and
can an indexed value be used withinbt.If
?
and
would I be able to call previous occurrences of function result with [1], [2], for a strategy?From the documentation:
https://backtrader.com/docu/concepts/#somenonoverridenoperatorsfunctionsclass MyStrategy(bt.Strategy): def __init__(self): sma1 = btind.SMA(self.data.close, period=15) high_or_low = bt.If(sma1 > self.data.close, self.data.low, self.data.high)# returns Low if True, High if False sma2 = btind.SMA(high_or_low, period=15)
I would like to use the function/operator like this:
class MyStrategy(bt.Strategy): def __init__(self): sma1 = btind.SMA(self.data.close, period=15) only_low = bt.If(sma1[2] > self.data.close[1], self.data.low) # if sma1[2]>close[1] then return just the Low value sma2 = btind.SMA(high_or_low, period=15)
and then use it in strategy like this:
def next(self): if only_low[1]>only_low[2]: self.buy() # enter long
If
bt.If
cannot do this, which other function/operator would be able to?
or how would I modifybt.If
to do this?I tried to filter out 2nd result with below, but it does not work:
class MyStrategy(bt.Strategy): def __init__(self): sma1 = btind.SMA(self.data.close, period=15) low_or_9000 = bt.If(sma1[2] > self.data.close[1], self.data.low, 9000.0) # if sma1>close ture then return Low, false returns 9000.0 sma2 = btind.SMA(high_or_low, period=15) self.data.only_low = low_or_9000 < 9000.0

@kamdorra I think this should work in
__init()__
:low_or_9000 = bt.If(sma1(2) > self.data.close(1), self.data.low, 9000.0)

@kamdorra said in bt.If operator/function:
I tried to filter out 2nd result with below, but it does not work:
Why? You probably want to use what @ab_trader has suggested.

@ab_trader said in bt.If operator/function:
low_or_9000 = bt.If(sma1(2) > self.data.close(1), self.data.low, 9000.0)
Wouldn't that create a "line" with the value "9000" in it still?
I would like to create a line from function/operator result without "9000" and a line with only "self.data.low".

You can create the line with only
self.data.low
elements only like this:self.lows = self.data.low
If you have certain conditions and only part of the new line elements should be equal to
self.data.low
elements, then you need to define a placeholder for missing elements.Also if you want to pass variables between class methods, then these variables should be defined as
self.variable
, but notvariable
as in the script above.And other question on this:
if only_low[1]>only_low[2]: self.buy() # enter long
Say element [2] has no
low
value (condition didn't meet) and element[1] haslow
value. What do you expect from the script?

@ab_trader
I have no coding experience at all, everything i've posted here is just what I took from the documentation, so if you have time; could you show me how to only have theself.data.low
results in the line? how to define a placeholder for 9000?
 how and where do I create a
self.variable
that represents only the True return of a function/operator? indef __init__(self):
?
if only_low[1]>only_low[2]: self.buy() # enter long
"Say element [2] has no low value (condition didn't meet) and element[1] has low value. What do you expect from the script?"
That statement was just to show I wanted to use the most recent previous low value and the one before that for trading logic; it already assumes I have created a line without the false value (9000)return.thanks for you help.

@kamdorra said in bt.If operator/function:
I have no coding experience at all
The problem is not there (that's another problem), the problem is understanding why
bt.If
delivers two values.bt.If
returns a line. This is just like, for example,self.data.close
.Which means that for each tick (call iteration if you wish) it has to have a value.
@kamdorra said in bt.If operator/function:
could you show me how to only have the self.data.low results in the line?
@ab_trader cannot show you that, neither can anyone else, because you cannot have a line that sometimes has values and some other times doesn't. You have something similar if you don't fill the value (which is often done when developing an indicator), because if you skip setting a value, the default value is filled in for you, with the default value bein
NaN
(aka "Not a Number" or a default representation in the IEEE Floating Point Standard to indicate that it doesn't represent an actual value)The thing with
NaN
is that it may actually be what you need or it may not. Because, not being a number, arithmetic and logic operations won't work the way you expect them to (they will work, but the result may not match your expectations, which in fact means ... it doesn't work)Use a well defined floating point value such as
Inf
orInf
is better in order to have well defined operations and results. If your problem is thelow
, what seems plausible is:low_or_inf = bt.If(sma1(2) > self.data.close(1), self.data.low, float('Inf'))
One can be sure that the
low
will always be less thanInf
.Later in your code you can do the following
if low_or_inf[0] < float('Inf') do_something_here()
With that logic implying that if something is less than infinitum ... it has to be
low
Given that your initial statement gave an example
@kamdorra said in bt.If operator/function:
def next(self): if only_low[1]>only_low[2]: self.buy() # enter long
the obvious thing would be
def next(self): if low_or_inf[0] < float('Inf'): if low_or_inf[1] > low_or_inf[2]: # this may also be precalculated as a line self.buy() # enter long
To pack everything as a line
low_or_inf = bt.If(sma1(2) > self.data.close(1), self.data.low, float('Inf')) low_signal = bt.If(low_or_inf < float('Inf'), low_or_inf(1) > low_or_inf(2), False)
Later in the code
def next(self): if low_signal[0]: self.buy()

@backtrader
thank you very much for your time and assistance, you have been very helpful.