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.


Log in to reply
 

});