For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
self.array[self.idx + ago]: IndexError: array index out of range - generated from btind.OLS_TransformationN(X, Y, period=self.p.period)
-
As in the title the error I'm getting is self.array[self.idx + ago]: IndexError: array index out of range and it stems from
btind.OLS_TransformationN(X, Y, period=self.p.period)
After some investigation it seems the same error is generated by
self.idx
which I note is used in the above function.
At first I thought the issue was that I was comparing two data feeds of different length but I noticed that if I fed in the same datafeed into each of the first two arguments I got the same error. For context here is the rest of the relevent code
class PairTradingStrategy(bt.Strategy): params = dict( period=100, stake=1, qty1=0, qty2=0, printout=True, upper=1, lower=-1, up_medium=0.75, low_medium=-0.75, status=0, portfolio_value=50, ) 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 notify_order(self, order): if order.status in [bt.Order.Submitted, bt.Order.Accepted]: return # Await further notifications if order.status == order.Completed: if order.isbuy(): buytxt = 'BUY COMPLETE, %.2f' % order.executed.price self.log(buytxt, order.executed.dt) else: selltxt = 'SELL COMPLETE, %.2f' % order.executed.price self.log(selltxt, order.executed.dt) elif order.status in [order.Expired, order.Canceled, order.Margin]: self.log('%s ,' % order.Status[order.status]) pass # Simply log # Allow new orders self.orderid = None def __init__(self,pairs_list): # To control operation entries self.pairs_list = pairs_list 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 def next(self): ########PRETTTYYYYYYYYYY SURE SHORT SELLS ARENT WORKING AS THEY SHOULDDDD...... def hedge_ratio(X, Y): print('calc hedgggeee') ratio_data = btind.OLS_BetaN(X, Y, period=self.p.period) print(ratio_data) print(ratio_data) return ratio_data def z_ratio(X, Y): print('calc z_ratio:namesssss') print(len(X)) print(len(Y)) print(self.p.period) print(X._name) print(Y._name) print(self.get(size=self.p.period)) print(self.idx) z_data = btind.OLS_TransformationN(X, Y, period=self.p.period) print(z_data) return z_data for pair in self.pairs_list: p0_data = self.getdatabyname(pair[0]) p1_data = self.getdatabyname(pair[1]) print(pair) #if data isnt available just skip it if p0_data is not None and p1_data is not None : print(p0_data) print(p1_data) print(p0_data._name) print(p1_data._name) print('positions') print(self.getposition(pair[0]) ) print(self.getposition(pair[1]) ) if self.getposition(pair[0]).size == 0 and self.getposition(pair[1]).size == 0: hedge_ratio = hedge_ratio(p0_data,p1_data) z_ratio = z_ratio(p0_data,p0_data) if self.p.printout: print('Self len:', len(self)) print('Data0 len:', len(self.data0)) print('Data1 len:', len(self.data1)) print('Data0 len == Data1 len:', len(p0_data) == len(p1_data)) print('Data0 dt:', p0_data.datetime.datetime()) print('Data1 dt:', p1_data.datetime.datetime()) print('status is', self.status) print('zscore is', z_ratio[0]) # Step 2: Check conditions for SHORT & place the order # Checking the condition for SHORT if (z_ratio[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 / (p0_data.close)) # Find the number of shares for Stock1 y = int(value / (p1_data.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 --- not sure sell is correct!!!!!!!!!!!!!!!!!!!!! self.log('SELL CREATE %s, price = %.2f, qty = %d' % (p0_data._name, p0_data.close[0], x + self.qty1)) self.sell(data=p0_data, size=(x + self.qty1)) # Place an order for buying y + qty2 shares self.log('BUY CREATE %s, price = %.2f, qty = %d' % (p1_data._name, p1_data.close[0], y + self.qty2*self.beta[0])) self.buy(data=p1_data, size=(y + self.qty2*hedge_ratio[0])) # 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 # doesnt make sense for multiple feeds 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 (z_ratio[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.p0_data.close)) # Find the number of shares for Stock1 y = int(value / (self.data1.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' % (p0_data._name, p0_data.close[0], x + self.qty1)) self.buy(data=p0_data, size=(x + self.qty1)) # Place an order for buying x + qty1 shares self.log('SELL CREATE %s, price = %.2f, qty = %d' % (p1_data._name, p1_data.close[0], y + self.qty2*self.beta[0])) self.sell(data=p1_data, size=(y + self.qty2*hedge_ratio[0])) # 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 (z_ratio[0] < self.up_medium and z_ratio[0] > self.low_medium): self.log('CLOSE LONG %s, price = %.2f' % (p0_data._name, p0_data.close[0])) self.close(p0_data) self.log('CLOSE LONG %s, price = %.2f' % (p1_data._name, p1_data.close[0])) self.close(p1_data) def stop(self): print('==================================================') print('Starting Value - %.2f' % self.broker.startingcash) print('Ending Value - %.2f' % self.broker.getvalue()) print('==================================================') def runstrategy(stocks_of_interest,financial_history_dict, pairs_list): args = parse_args() # Create a cerebro cerebro = bt.Cerebro() # Get the dates from the args fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d') todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d') #must be a better way to do this stocks_in_order_used = [] skipped = [] #cerebro.adddata(self.benchmark_snp_500, name='snp500') for stock in stocks_of_interest: try: dataframe = financial_history_dict[stock] data = bt.feeds.PandasData(dataname=dataframe) cerebro.adddata(data, name=stock) except KeyError: print('skipping ' + stock) skipped += [stock] adj_pairs_list=[] print(pairs_list) for pair in pairs_list: dont_skip = True for skip_stock in skipped: if skip_stock in pair: dont_skip = False if dont_skip: adj_pairs_list.append(pair) print('adj') print(adj_pairs_list) # Add the strategy cerebro.addstrategy(PairTradingStrategy,pairs_list = adj_pairs_list, period=args.period, stake=args.stake) # Add the commission - only stocks like a for each operation cerebro.broker.setcash(args.cash) # Add the commission - only stocks like a for each operation cerebro.broker.setcommission(commission=args.commperc) cerebro.run(runonce= False, preload= False, oldsync= False) # Plot if requested if args.plot: cerebro.plot(numfigs=args.numfigs, volume=False, zdown=False)
Where you can see my attempts to interogate the issue in the Z_ratio function.