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/

    Request for code review

    General Code/Help
    3
    6
    1048
    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.
    • T
      Trade Prophet last edited by

      Hello,
      since these are my first lines of code in backtrade(and Python),can anyone run a quick code review and post comments?
      a few words about the logic:

      1. rank the stocks in a list according to volatility(r_squared of last 90 days linear regression)
      2. open the first ones with positive linear regression slope
      3. close the ones with negative linear regression slope

      comments are highly appreciated,go brutal...

      imports ...
      class TestStrategy(bt.Strategy):
          params = (
              ('atr_parameter', 20),
              ('rank_period', 90),
          )
      
          def __init__(self):
              self.atrs = {data._name: bt.indicators.ATR(data, period=self.p.atr_parameter)
                           for data in self.datas}
      
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted]:
                  return
      
              dt = self.datas[0].datetime.date(0)
              order_type = None
              order_value = None
              if order.status in [order.Completed]:
                  if order.isbuy():
                      order_type= 'buy'
                      order_value = order.executed.value
                  else:  # Sell
                      order_type= 'sell'
                      order_value = order.executed.pnl
                  print('%s : %s %s, (#%d@%.2f$),%.2f$' %(dt.isoformat(), order_type, order.data._name, order.executed.size, order.executed.price, order_value))
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  print('Order Canceled/Margin/Rejected')
      
          def next(self):
              open_candiates = []
              close_positions = []
              for ticker in self.getdatanames():
                  symbol_quotes = self.getdatabyname(ticker)
                  rank_period_quotes=list(symbol_quotes)[-self.p.rank_period:]
                  x = np.arange(len(rank_period_quotes))
                  slope, intercept, r_value, p_value, std_err = stats.linregress(x, rank_period_quotes)
                  if(slope <= 0):
                      close_positions.append(ticker)
                  else:
                      ticker_values = {}
                      ticker_values['ticker_r'] = r_value**2
                      ticker_values['position_size'] = 0.001 * self.broker.getvalue()/self.atrs[ticker][0]
                      ticker_values['ticker']=ticker
                      open_candiates.append(ticker_values)
      
              open_candiates.sort(key=itemgetter('ticker_r'), reverse=True)
      
              # close positions
              for ticker in close_positions:
                  if(0 != self.broker.getposition(data = self.getdatabyname(ticker)).size):
                      self.close(data=self.getdatabyname(ticker))
      
              # open position
              for ticker in open_candiates:
                  ticker_data = self.getdatabyname(ticker['ticker'])
                  current_size = self.broker.getposition(data = ticker_data).size
                  if(0 == current_size):
                      self.buy(data = ticker_data, size=ticker['position_size'])
      
      if __name__ == '__main__':
          isOptimizing = False    # backtesting and not optimizing
          # Create a cerebro entity
          cerebro = bt.Cerebro()
      
          # load symbol list from file
          with open('ticker_list.txt', 'r') as f:
              reader = csv.reader(f)
              tickers = list(reader)
      
          for ticker in tickers:
              print("Loading .csv for %s" % ticker[0])
              # Create a Data Feed
              data = bt.feeds.QuandlCSV(
                  dataname=ticker[0]+'.csv',
                  fromdate=datetime.datetime(2013, 1, 1),
                  todate=datetime.datetime(2016, 12, 29),
                  adjclose=False, reverse=True)
              # Add the Data Feed to Cerebro
              cerebro.adddata(data=data,name=ticker[0])
      
          # Add a strategy
          if(isOptimizing):
              strats = cerebro.optstrategy(TestStrategy,maperiod=range(10, 31))
          else:
              cerebro.addstrategy(TestStrategy)
      
          cerebro.broker.setcash(100000.0)
          cerebro.broker.setcommission(commission=0.0015)
          cerebro.run()
      
      P 1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        go brutal...

        You've asked. Why don't you debug your code by yourself?

        • If my answer helped, hit reputation up arrow at lower right corner of the post.
        • Python Debugging With Pdb
        • New to python and bt - check this out
        1 Reply Last reply Reply Quote 0
        • T
          Trade Prophet last edited by

          Thank you for the reply,
          I'm not looking to debug the code, I'm looking for reviews, such as :

          • could I have done things differently? using other backtrader (excellent) components?

          • Could the purpose of ranking be done another way?

          • What are the potential pitfalls in the code?

          • Did I use backtrader the way it was supposed to be used?

          1 Reply Last reply Reply Quote 0
          • P
            Paska Houso @Trade Prophet last edited by

            @Trade-Prophet said in Request for code review:

                        symbol_quotes = self.getdatabyname(ticker)
                        rank_period_quotes=list(symbol_quotes)[-self.p.rank_period:]
            

            Out of curiosity ... what's the intention of that. I imagine:

            • list(symbolquotes) uses the fact that a data feed has a __len__ (one can say len(data)) and __getitem__ (one can use data[x]

            But given that backtrader doesn't use standard indexing (starting and 0 and growing), but the built-in mechanisms in Python don't know it and will construct the list by iterating from 0 -> len(data) ... this probably won't deliver the expected result ... which seems to gather all data and then slice.

            @Trade-Prophet said in Request for code review:

            if(0 == current_size):
            

            That isn't very Pythonic ... if not current_size would be. But each uses his/her own patterns.

            P 1 Reply Last reply Reply Quote 0
            • T
              Trade Prophet last edited by

              Thank you very much for your reply
              and you are absolutely right! the lines you have mentioned do not produce the expected result, I'm constructing an indicator to provide linear regression data(slope,r squared) instead of the current code.
              coming from C++ lines like "if(0 == current_size):" make sense to me but I will gladly honor the Pythonic tradition.
              Thanks for the time and the professional review

              1 Reply Last reply Reply Quote 0
              • P
                Paska Houso @Paska Houso last edited by

                @Paska-Houso said in Request for code review:

                • list(symbolquotes) uses the fact that a data feed has a __len__ (one can say len(data)) and __getitem__ (one can use data[x])

                See this recent thread. You probably want to use data.get(ago=x, size=y). The results will be in the expected order.

                • https://community.backtrader.com/topic/753/indicator-slicing/
                1 Reply Last reply Reply Quote 0
                • 1 / 1
                • First post
                  Last post
                Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors