For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

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 within bt.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/#some-non-overriden-operatorsfunctions

    class 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 modify bt.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
    


  • @kam-dorra I think this should work in __init()__:

    low_or_9000 = bt.If(sma1(-2) > self.data.close(-1), self.data.low, 9000.0)
    

  • administrators

    @kam-dorra 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 not variable 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] has low 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 the self.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? in def __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.


  • administrators

    @kam-dorra 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.

    @kam-dorra 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 or -Inf is better in order to have well defined operations and results. If your problem is the low, 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 than Inf.

    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

    @kam-dorra 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 pre-calculated 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.


Log in to reply
 

});