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/

    Optimizing Strategy with IBStore data returns pickle error

    Indicators/Strategies/Analyzers
    3
    4
    1785
    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.
    • D
      d416 last edited by d416

      I'm not sure if I'm doing this correctly: Trying the Quickstart code with Optimization and using Interactive Brokers IBStore data, I get

      File "C:\Program Files\Anaconda2\lib\multiprocessing\pool.py", line 668, in next
      raise value TypeError: can't pickle thread.lock objects
      

      Full code is below. Am I doing something wrong? Maybe it's my environment (windows with Anaconda). I haven't been able to find any similar issues in the discussion threads.

      from __future__ import (absolute_import, division, print_function,
      						unicode_literals)
      						# -*- coding: utf-8 -*-
      
      import backtrader as bt
      import datetime # for datetime objects
      import os.path # to manage paths
      from backtrader.stores import ibstore
      # import sys # to detrmine the script name in argv[0]
      
      # -----  STRATEGY DEFINITION -----
      
      
      class TestStrategy(bt.Strategy):
      	def log(self,txt,dt=None):
      		''' Logging function fot this strategy'''
      		dt = dt or self.datas[0].datetime.date(0)
      		print('%s, %s' % (dt.isoformat(),txt))
      		
      	def __init__(self):
      		# Keep a reference to the "close" line in the data[0] dataseries
      		self.dataclose = self.datas[0].close
      
      		# To keep track of pending orders and buy price/commission                        
      		self.order = None
      		self.buyprice = None
      		self.buycomm = None
      		
      		
      	def notify(self, order):
      		if order.status in [order.Submitted, order.Accepted]:
      			# Buy/Sell order submitted/accepted to/by broker - Nothing to do
      			return
      
      		# Check if an order has been completed
      		# Attention: broker could reject order if not enougth cash
      		if order.status in [order.Completed, order.Canceled, order.Margin]:
      			if order.isbuy():
      				self.log('BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
      				(order.executed.price,
      				 order.executed.value,
      				 order.executed.comm))
      				self.buyprice = order.executed.price
      				self.buycomm = order.executed.comm
      			else:  #Sell
      				self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
      				(order.executed.price,
      				 order.executed.value,
      				 order.executed.comm))
      				 
      			self.bar_executed = len(self)
      		
      		# Write down: no pending order
      		self.order = None
      		
      	def notify_trade(self, trade):
      		if not trade.isclosed:
      			return
      				  
      		self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
      			(trade.pnl, trade.pnlcomm))
      		
      		
      	def next(self):
      		# Simply log the closing price of the series from the reference
      		self.log('Close, %.2f' % self.dataclose[0])
      		# Check if an order is pending ... if yes, we cannot send a 2nd one
      		if self.order:
      			return
      		# Check if we are in the market
      		if not self.position:
      			# Not yet ... we MIGHT BUY if ...
      		# -------  STRATEGY LOGIC -----
      			if self.dataclose[0] < self.dataclose[-1]:
      				#i.e. current close less than previous close
      				if self.dataclose[-1] < self.dataclose[-2]:
      					
      					# buy with default params
      					self.log('BUY CREATE, %.2f' % self.dataclose[0])                 
      					# Keep track of the created order to avoid a 2nd order
      					self.order = self.buy()
      		else:
      			# Already in the market... we might sell if holding > 5 bars
      			if len(self) > (self.bar_executed + 5):
      				# SELL, SELL, SELL!!! (with all possible default parameters)
      				self.log('SELL CREATE, %.2f' % self.dataclose[0])
      			# Keep track of the created order to avoid a 2nd order
      				self.order = self.sell()
      			
      # -----  END STRATEGY DEFINITION -----
      					
      				
      if __name__ == '__main__':
      	# create a cerebro entity
      	cerebro = bt.Cerebro()
      	
      	# Add a strategy
        
      	cerebro.optstrategy(
      		TestStrategy,
      		maperiod=range(10, 31))
        
      	
      # Create a Data Feed
      	ibstore = bt.stores.IBStore(host='127.0.0.1',port=7496,clientId=5)
      	mysymbol = 'EUR.USD-CASH-IDEALPRO'
      	fromdate = datetime.datetime(2016,3,1,00,00)
      	todate = fromdate = datetime.datetime(2017,3,30,00,00)
      
      	data = ibstore.getdata(dataname=mysymbol, timeframe=bt.TimeFrame.Days, compression=1, fromdate=fromdate, todate=todate, historical=True)
      
      #    cerebro.resampledata(data, timeframe=bt.TimeFrame.minutes, compression=60)
      	
      	# Add the Data Feed to Cerebro
      	cerebro.adddata(data)
      	
      	
      	cerebro.broker.setcash(100000)
      	cerebro.broker.setcommission(commission=0.001) # 0.1% ... divide by 100 to remove the %
      	
      	print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      	
      	cerebro.run()
      	
      	print('Final Portfolio Value:  %.2f' % cerebro.broker.getvalue())
      1 Reply Last reply Reply Quote 0
      • D
        d416 last edited by

        Solved: adding the 'maxcpus=1' parameter to the cerebro call worked

        ie.:

        cerebro = bt.Cerebro(maxcpus=1)
        

        Not sure why this is... perhaps because of the way data requests to IB are split into tasks.

        1 Reply Last reply Reply Quote 2
        • B
          backtrader administrators last edited by

          Threads are part of the pack when using IbPy and they are not pickable across processes. A lot of tweaking might be needed to remove all those objects after a historical download.

          1 Reply Last reply Reply Quote 0
          • N
            nooby_mcnoob last edited by

            I tried to resolve this issue by walking recursively down the object tree rooted at cerebro and setting all lock types to None. Didn't work, still found a lock somewhere.

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