PAIR TRADING IMPLEMENTATION ON BACKTRADER
-
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 rangeimport 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 :)
-
@houba coul you please stay within one topic you opened before? There are no 24/7 support here, so be patient.
-