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/

    Error with simple custom indicator

    Indicators/Strategies/Analyzers
    3
    8
    208
    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.
    • H
      hanaan last edited by

      Hi all,
      I'm looking for a way to eliminate opening trades when the EMA lines are flat, (indicating a sideway market.) I want to do that by checking how much the EMA line moved in the past x bars. (Suggestions on the strategy are always welcome!)
      I created a custom indicator that does one simple thing:
      Takes the high and Low of the last x number of periods and calculates the difference in percent. If too low, then no new positions get opened.
      I can use the close data, or better, a moving average.
      I get this error:

      TypeError: must be real number, not array.array
      

      Can't figure it out for the life of me - thank you for the help.

      Here's the indicator:

      class PercentVariationInPeriod(bt.Indicator):
          lines = ('Variation',)
      
          params = (
              ('period', 180),
          )
      
          def __init__(self):
              ar = self.data.get(size=self.p.period)
              high = bt.Max(ar)
              low = bt.Min(ar)
              self.lines.Variation = (high - low)/low
      

      And the call:

      self.emaVariation = vol.PercentVariationInPeriod(self.ema_slow, plotname='EMA Variation', subplot=True)
      

      (Note period=180 is in minutes...)

      run-out 1 Reply Last reply Reply Quote 0
      • run-out
        run-out @hanaan last edited by

        @hanaan said in Error with simple custom indicator:

        self.emaVariation = vol.PercentVariationInPeriod(self.ema_slow, plotname='EMA Variation', subplot=True)

        There a two built in indicators that make this a bit easier for you. Highest aka MaxN and Lowest aka MinN.

        You can use them in your indicator like this:

        class PercentVariationInPeriod(bt.Indicator):
            lines = ("Variation",)
        
            params = (("period", 180),)
        
            def __init__(self):
                high = bt.ind.MaxN(period=self.p.period)
                low = bt.ind.MinN(period=self.p.period)
                self.lines.Variation = (high - low) / low
        

        RunBacktest.com

        1 Reply Last reply Reply Quote 1
        • H
          hanaan last edited by

          Okay, thank you that worked perfectly.

          Would you know what didn't work in my original code?
          Did I use self.data.get(size=self.p.period) incorrectly?

          run-out 1 Reply Last reply Reply Quote 1
          • run-out
            run-out @hanaan last edited by

            @hanaan Yes. You need to use get in next. It returns an array based on the parameters size and ago.

            RunBacktest.com

            H 1 Reply Last reply Reply Quote 1
            • H
              hanaan @run-out last edited by

              @run-out Ah... get in next, not init. Got it.

              1 Reply Last reply Reply Quote 1
              • E
                EMR last edited by

                @hanaan said in Error with simple custom indicator:

                Hi all,
                I'm looking for a way to eliminate opening trades when the EMA lines are flat, (indicating a sideway market.) I want to do that by checking how much the EMA line moved in the past x bars. (Suggestions on the strategy are always welcome!)

                In addition to previous solution, and for all those who may be looking at the same thing, you may want to check the "angle" of the moving average.
                In Sierra Chart, there is study for this : https://www.sierrachart.com/index.php?page=doc/StudiesReference.php&ID=231
                Implementing this code for a moving average in BT could be done that way (testing not complete - to be fully tested) :

                    params = (('length', 10), ('period', 10), ('movav', MovAv.EMA), ('pointvalue', 1),)
                
                    def __init__(self):
                        self.ma = self.p.movav(self.data.close, period=self.p.period)
                
                    def next(self):
                        self.l.maangle[0] = math.atan((self.ma[0]-self.ma[-self.p.length])/(self.p.pointvalue * self.p.length)) *(180/math.pi)
                
                1 Reply Last reply Reply Quote 1
                • H
                  hanaan last edited by

                  @emr Interesting. Instead of angle isn't it easier to just check the percent change over a certain period?
                  I think it gives you the same indication of direction over time.

                  E 1 Reply Last reply Reply Quote 0
                  • E
                    EMR @hanaan last edited by

                    @hanaan easier, maybe but yes it provides more or less the same information. Analysis of the resulting data and plotting (I use btplotting) may help to visualize the sometimes subtle differences.

                    1 Reply Last reply Reply Quote 0
                    • 1 / 1
                    • First post
                      Last post
                    Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors