Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    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

    Indicators/Strategies/Analyzers
    3
    8
    185
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • kam dorra
      kam dorra last edited by

      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
      
      B 1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        @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)
        
        1 Reply Last reply Reply Quote 2
        • B
          backtrader administrators @kam dorra last edited by

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

          1 Reply Last reply Reply Quote 0
          • kam dorra
            kam dorra last edited by

            @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".

            1 Reply Last reply Reply Quote 0
            • A
              ab_trader last edited by

              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?

              kam dorra 1 Reply Last reply Reply Quote 1
              • kam dorra
                kam dorra @ab_trader last edited by

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

                1 Reply Last reply Reply Quote 0
                • B
                  backtrader administrators last edited by backtrader

                  @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()
                  
                  kam dorra 1 Reply Last reply Reply Quote 2
                  • kam dorra
                    kam dorra @backtrader last edited by

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

                    1 Reply Last reply Reply Quote 0
                    • 1 / 1
                    • First post
                      Last post
                    Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                    $(document).ready(function () { app.coldLoad(); }); }