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/

    Stock Screening

    Blog
    3
    11
    3332
    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.
    • B
      backtrader administrators last edited by

      Use the link below to go the original post

      Click here to see the full blog post

      1 Reply Last reply Reply Quote 0
      • C
        cwse last edited by

        How do you stop the output printing:
        """- Datas:
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        - Data0:"""
        for each data source added?

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

          You cannot with the standard WriterFile which is the one creating the output.

          You can if you subclass it, check the sources, and create your own output.

          1 Reply Last reply Reply Quote 0
          • C
            cwse last edited by

            Thank you. How do I subclass it, check the sources and create a different output?

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

              There is no other way.

              In any case the expected (even if small) API of the Writer should have a small documentation page to ease up subclassing.

              1 Reply Last reply Reply Quote 0
              • spyamine
                spyamine last edited by

                Thank you for this example. can you please complete it by using this screener as input to a strategy. for instance to be long under and short the long list and close the trades if they go out of the list. thx a lot

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

                  See this reddit post: Reddit - The Conservative Formula in Python: Quantitative Investing made Easy

                  The code

                  class St(bt.Strategy):
                      params = dict(
                          rperiod=1,  # period for the returns calculation, default 1 period
                          vperiod=36,  # lookback period for volatility - default 36 periods
                          mperiod=12,  # lookback period for momentum - default 12 periods
                          torank=100,  # number of stocks to rank as top
                          reserve=0.05  # 5% reserve capital
                      )
                  
                      def __init__(self):
                          # Return, volatility and momentum
                          rets = [bt.ind.PctChange(d, period=self.p.rperiod) for d in self.datas]
                          vols = [bt.ind.StdDev(ret, period=self.p.vperiod) for ret in rets]
                          moms = [bt.ind.ROC(d, period=self.p.mperiod) for d in self.datas]
                  
                          # simple rank formula: (momentum * net payout) / volatility
                          # The highest ranked: low vol, large momentum, large payout
                          self.ranks = [d.npy * m / v for d, v, m in zip(self.datas, vols, moms)]
                  
                          # allocation perc pro stock
                          # reserve kept to make sure orders are not rejected due to
                          # margin. Prices are calculated when known (close), but orders can only
                          # be executed next day (opening price). Price can gap upwards
                          self.perctarget = (100.0 - self.p.reserve) % self.p.torank
                  
                      def next(self):
                          # get the ranks sorted for each iteration in a list
                          ranks = sorted(
                              ((self.datas[i], rank[0]) for i, rank in enumerate(self.ranks)),
                              key=lambda x: x[1],  # use rank (elem 1 in the tuple) to sort
                              reverse=True,  # highest ranked 1st ... please
                          )
                          # Put top 100 in ordereddict with data as key to test for presence
                          r100 = collections.OrderedDict(ranks[:self.p.torank])
                  
                          # Remove those no longer Top 100, prepare quick lookup dict
                          positions = {pos: pos.data for pos in self.getpositions() if pos}
                          for pos, data in positions.items():
                              if data not in r100:  # open and no rank100 ... close
                                  self.order_target_percent(data, target=0.0)
                  
                          # Add the newcomers to the Top 100, prepare easy reverse lookup
                          revpositions = {data: pos for pos, data in positions.items()}
                          for data in (d for d in r100 if d not in revpositions):
                              self.order_target_percent(data, target=self.perctarget)
                  
                  spyamine 1 Reply Last reply Reply Quote 0
                  • spyamine
                    spyamine @backtrader last edited by

                    @backtrader You are awesome!! many thanks

                    spyamine 1 Reply Last reply Reply Quote 0
                    • spyamine
                      spyamine @spyamine last edited by spyamine

                      @backtrader Hi, I've tryed to test your code but unfortunatly it didn't work properly as the compiler do not reconignize "pos.data" from this line "{pos: pos.data for pos in self.getpositions() if pos}" and also i suspect this line too "self.order_target_percent(data, target=self.perctarget)" the self.order_target percent part. Can you please share the full code that works for you?

                      1 Reply Last reply Reply Quote 0
                      • spyamine
                        spyamine last edited by

                        from backtrader.feeds import PandasData

                        class PycaishenData(PandasData):

                        # Add a 'pe' line to the inherited ones from the base class
                        lines = ('turnover','mkt_cap')
                        
                        # openinterest in GenericCSVData has index 7 ... add 1
                        # add the parameter to the parameters inherited from the base class
                        params = (('turnover', -1),('mkt_cap',-1))
                        

                        class StAmine(bt.Strategy):
                        params = dict(
                        rperiod=1, # period for the returns calculation, default 1 period
                        vperiod=36, # lookback period for volatility - default 36 periods
                        mperiod=12, # lookback period for momentum - default 12 periods
                        torank=10, # number of stocks to rank as top
                        reserve=0.05 # 5% reserve capital
                        )

                        def __init__(self):
                        
                        
                            # The highest ranked: mkt_cap
                        
                            self.ranks = [bt.ind.movav(d.mkt_cap,period = 1) for d in self.datas]
                        
                            # allocation perc pro stock
                            # reserve kept to make sure orders are not rejected due to
                            # margin. Prices are calculated when known (close), but orders can only
                            # be executed next day (opening price). Price can gap upwards
                            self.perctarget = (100.0 - self.p.reserve) % self.p.torank
                        
                        def next(self):
                            # get the ranks sorted for each iteration in a list
                            ranks = sorted(
                                ((self.datas[i], rank[0]) for i, rank in enumerate(self.ranks)),
                                key=lambda x: x[1],  # use rank (elem 1 in the tuple) to sort
                                reverse=True,  # highest ranked 1st ... please
                            )
                            # Put top 100 in ordereddict with data as key to test for presence
                            r100 = collections.OrderedDict(ranks[:self.p.torank])
                        
                            # Remove those no longer Top 100, prepare quick lookup dict
                            positions = {pos: pos.data for pos in self.getpositions().values() if pos}
                            for pos, data in positions.items():
                                if data not in r100:  # open and no rank100 ... close
                                    self.order_target_percent(data, target=0.0)
                        
                            # Add the newcomers to the Top 100, prepare easy reverse lookup
                            revpositions = {data: pos for pos, data in positions.items()}
                            for data in (d for d in r100 if d not in revpositions):
                                self.order_target_percent(data, target=self.perctarget)
                        

                        def run(tickers, datas,strategy = StAmine,plotdetails= True,writedetail = False):

                        cerebro = bt.Cerebro()
                        
                        print ('Starting Portfolio Value: %.2f ' % cerebro.broker.getvalue())
                        
                        cerebro.addstrategy(strategy)
                        
                        for ticker, data in zip(tickers , datas):
                            dt = PycaishenData(dataname=data)
                            if plotdetails == False:
                                dt.plotinfo.plot = False
                            cerebro.adddata(dt,ticker)
                        
                        cerebro.broker.set_fundmode(True)
                        cerebro.broker.set_fundstartval(10.0)  # the default is 100
                        cerebro.broker.setcommission(commission=0.0025)
                        
                        # Add the Analyzers
                        cerebro.addanalyzer(btanalyser.SQN)
                        cerebro.addanalyzer(btanalyser.AnnualReturn)
                        cerebro.addanalyzer(btanalyser.SharpeRatio)
                        
                        cerebro.broker.setcash(100000.0)
                        
                        cerebro.addanalyzer(btanalyser.TradeAnalyzer)
                        
                        if writedetail:
                            cerebro.addwriter(bt.WriterFile, csv=True, rounding=4)
                        
                        cerebro.run()
                        
                        cerebro.plot()
                        
                        print ('Final portfolio value: %.2f' % cerebro.broker.getvalue())
                        

                        run(tickers, datas,strategy = StAmine,plotdetails= False,writedetail = False)

                        the code seems to do nothing!!

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

                          @spyamine said in Stock Screening:

                          Hi, I've tryed to test your code but unfortunatly it didn't work properly as the compiler do not reconignize "pos.data" from this line "{pos: pos.data for pos in self.getpositions() if pos}" and also i suspect this line too "self.order_target_percent(data, target=self.perctarget)" the self.order_target percent part. Can you please share the full code that works for you?

                          It is a hand-crafted snippet, giving an indication and orientation as to how a proposed algorithm could be implemented.

                          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(); }); }