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/

    PAIR TRADING IMPLEMENTATION ON BACKTRADER

    General Code/Help
    3
    3
    15
    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
      houba last edited by

      Hi guys , I have a problem with code as I get the following error :

      Traceback (most recent call last):
      File "PairTradingStrategy.py", line 174, in <module>
      cerebro.run()
      File "/opt/anaconda3/lib/python3.7/site-packages/backtrader/cerebro.py", line 1127, in run
      runstrat = self.runstrategies(iterstrat)
      File "/opt/anaconda3/lib/python3.7/site-packages/backtrader/cerebro.py", line 1212, in runstrategies
      data.preload()
      File "/opt/anaconda3/lib/python3.7/site-packages/backtrader/feed.py", line 688, in preload
      while self.load():
      File "/opt/anaconda3/lib/python3.7/site-packages/backtrader/feed.py", line 479, in load
      _loadret = self._load()
      File "/opt/anaconda3/lib/python3.7/site-packages/backtrader/feed.py", line 710, in _load
      return self._loadline(linetokens)
      File "/opt/anaconda3/lib/python3.7/site-packages/backtrader/feeds/yahoo.py", line 134, in _loadline
      h = float(linetokens[next(i)])
      IndexError: list index out of range

      import backtrader as bt
      import backtrader.analyzers as btanalyzers
      import backtrader.indicators as btind
      import datetime
      
      class PairTradingStrategy(bt.Strategy):
      params = dict(
      period=10,
      stake=10,
      qty1=0,
      qty2=0,
      printout=True,
      upper=2.1,
      lower=-2.1,
      up_medium=0.5,
      low_medium=-0.5,
      status=0,
      portfolio_value=10000,
      )
      
      def log(self, txt, dt=None):
         if self.p.printout:
             dt = dt or self.data.datetime[0]
             dt = bt.num2date(dt)
             print('%s, %s' % (dt.isoformat(), txt))
      
      def __init__(self):
        # To control operation entries
         self.orderid = None
         self.qty1 = self.p.qty1
         self.qty2 = self.p.qty2
         self.upper_limit = self.p.upper
         self.lower_limit = self.p.lower
         self.up_medium = self.p.up_medium
         self.low_medium = self.p.low_medium
         self.status = self.p.status
         self.portfolio_value = self.p.portfolio_value
      
      # Signals performed with PD.OLS :
         self.transform = btind.OLS_TransformationN(self.data1, self.data2,
                                                    period=self.p.period)
         self.zscore = self.transform.zscore
      
         # Checking signals built with StatsModel.API :
         # self.ols_transfo = btind.OLS_Transformation(self.data1, self.data2,
         #                                             period=self.p.period,
         #                                             plot=True)
      
      def next(self):
      if self.orderid:
      return # if an order is active, no new orders are allowed
      
         if self.p.printout:
             print('Self  len:', len(self))
             print('Data1 len:', len(self.data1))
             print('Data2 len:', len(self.data2))
             print('Data1 len == Data2 len:',
                   len(self.data1) == len(self.data2))
      
             print('Data1 dt:', self.data1.datetime.datetime())
             print('Data2 dt:', self.data2.datetime.datetime())
      
         print('status is', self.status)
         print('zscore is', self.zscore[0])
      
      
         # Step 2: Check conditions for SHORT & place the order
         # Checking the condition for SHORT
         if (self.zscore[0] > self.upper_limit) and (self.status != 1):
      
             # Calculating the number of shares for each stock
             value = 0.5 * self.portfolio_value  # Divide the cash equally
             x = int(value / (self.data1.close))  # Find the number of shares for Stock1
             y = int(value / (self.data2.close))  # Find the number of shares for Stock2
             print('x + self.qty1 is', x + self.qty1)
             print('y + self.qty2 is', y + self.qty2)
      
             # Placing the order
             self.log('SELL CREATE %s, price = %.2f, qty = %d' % ("AACQW", self.data1.close[0], x + self.qty1))
             self.sell(data=self.data1, size=(x + self.qty1))  # Place an order for buying y + qty2 shares
             self.log('BUY CREATE %s, price = %.2f, qty = %d' % ("KO", self.data2.close[0], y + self.qty2))
             self.buy(data=self.data2, size=(y + self.qty2))  # Place an order for selling x + qty1 shares
      
             # Updating the counters with new value
             self.qty1 = x  # The new open position quantity for Stock1 is x shares
             self.qty2 = y  # The new open position quantity for Stock2 is y shares
      
             self.status = 1  # The current status is "short the spread"
      
             # Step 3: Check conditions for LONG & place the order
             # Checking the condition for LONG
         elif (self.zscore[0] < self.lower_limit) and (self.status != 2):
      
             # Calculating the number of shares for each stock
             value = 0.5 * self.portfolio_value  # Divide the cash equally
             x = int(value / (self.data1.close))  # Find the number of shares for Stock1
             y = int(value / (self.data2.close))  # Find the number of shares for Stock2
             print('x + self.qty1 is', x + self.qty1)
             print('y + self.qty2 is', y + self.qty2)
      
             # Place the order
             self.log('BUY CREATE %s, price = %.2f, qty = %d' % ("AACQW", self.data1.close[0], x + self.qty1))
             self.buy(data=self.data1, size=(x + self.qty1))  # Place an order for buying x + qty1 shares
             self.log('SELL CREATE %s, price = %.2f, qty = %d' % ("AAME", self.data2.close[0], y + self.qty2))
             self.sell(data=self.data2, size=(y + self.qty2))  # Place an order for selling y + qty2 shares
      
             # Updating the counters with new value
             self.qty1 = x  # The new open position quantity for Stock1 is x shares
             self.qty2 = y  # The new open position quantity for Stock2 is y shares
             self.status = 2  # The current status is "long the spread"
      
      
             # Step 4: Check conditions for No Trade
             # If the z-score is within the two bounds, close all
      
         elif (self.zscore[0] < self.up_medium and self.zscore[0] > self.low_medium):
             self.log('CLOSE LONG %s, price = %.2f' % ("PEP", self.data1.close[0]))
             self.close(self.data1)
             self.log('CLOSE LONG %s, price = %.2f' % ("KO", self.data2.close[0]))
             self.close(self.data2)
      
      
      def stop(self):
             print('==================================================')
             print('Starting Value - %.2f' % self.broker.startingcash)
             print('Ending   Value - %.2f' % self.broker.getvalue())
             print('==================================================')
      
      #Instantiate Cerebro engine
      cerebro = bt.Cerebro()
      
      #Add data feed to Cerebro
      data1 = bt.feeds.YahooFinanceCSVData(dataname='/Users/bibani/Desktop/AACQW.csv',
      dtformat=('%Y.%m.%d'),
      fromdate = datetime.datetime(2018,1,2),
      todate = datetime.datetime(2021,1,15),
      datetime=0,
      time=-1,
      high=-1,
      low=-1,
      open=-1,
      close=1,
      volume=-1,
      openinterest=-1)
      cerebro.adddata(data1)
      
      data2 = bt.feeds.YahooFinanceCSVData(dataname='/Users/bibani/Desktop/AAME.csv',
      dtformat=('%Y.%m.%d'),
      fromdate = datetime.datetime(2018,1,2),
      todate = datetime.datetime(2021,1,15),
      datetime=0,
      time=-1,
      high=-1,
      low=-1,
      open=-1,
      close=1,
      volume=-1,
      openinterest=-1)
      cerebro.adddata(data2)
      
      #Add strategy to Cerebro
      cerebro.addstrategy(PairTradingStrategy)
      
      
      if name == 'main':
      # Run Cerebro Engine
      start_portfolio_value = cerebro.broker.getvalue()
      
      cerebro.run()
      
      end_portfolio_value = cerebro.broker.getvalue()
      
      pnl = end_portfolio_value - start_portfolio_value
      print(f'Starting Portfolio Value: {start_portfolio_value:2f}')
      print(f'Final Portfolio Value: {end_portfolio_value:2f}')
      print(f'PnL: {pnl:.2f}')
      #Run Cerebro Engine
      cerebro.run()
      

      Thank you very much for your help :)

      A run-out 2 Replies Last reply Reply Quote 0
      • A
        ab_trader @houba last edited by

        @houba coul you please stay within one topic you opened before? There are no 24/7 support here, so be patient.

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

          See duplicate here: https://community.backtrader.com/topic/3498/pair-trading-implementation-with-backtrader/4?_=1614112981197

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