class IBBroker(Broker): cid = 0 # connection id oid = 0 # order id tid = 0 # tick id (for fetching quotes) tws = None # Trader WorkStation wrapper = None # instance of EWrapper sid_to_tid = {} # map of security id to tick id def __init__(self, wrapper=None): Broker.__init__(self) # initialize a default wrapper if wrapper: self.wrapper = wrapper else: self.wrapper = WrapperDefault() # initialize the wrapper's portfolio object self.wrapper.portfolio = IBPortfolio() # get next order id def get_next_oid(self): IBBroker.oid += 1 return IBBroker.oid # get next connection id def get_next_cid(self): IBBroker.cid += 1 return IBBroker.cid # get next tick request id (for getting quotes) def get_next_tid(self): self.tid += 1 return self.tid # connect to TWS def connect(self, port=7496): if self.is_connected(): self.disconnect() cid = self.get_next_cid() self.tws = EPosixClientSocket(self.wrapper) self.tws.eConnect('', port, cid) # disconnect from TWS def disconnect(self): self.tws.eDisconnect() # check if TWS is connected def is_connected(self): if self.tws is None: return False return self.tws.isConnected() # Convert Zipline order signs into IB action strings def order_action(self, iSign): if iSign > 0: return 'BUY' elif iSign < 0: return 'SELL' raise Exception('Order of zero shares has no IB side: %i' % iSign) # get an IB contract by ticker def get_contract_by_sid(self, sid): contract = Contract() contract.symbol = sid contract.secType = 'STK' contract.exchange = 'SMART' contract.currency = 'USD' return contract # get a default IB market order def get_market_order(self, sid, amt): order = Order(); order.action = self.order_action(amt) order.totalQuantity = abs(amt) order.orderType = 'MKT' order.tif = 'DAY' order.outsideRth = False return order # get a default IB limit order def get_limit_order(self, sid, amt, lmtPrice): order = Order(); order.action = self.order_action(amt) order.totalQuantity = abs(amt) order.orderType = 'LMT' order.tif = 'DAY' order.outsideRth = False order.lmtPrice = lmtPrice return order # send the IB (contract, order) order to TWS def place_order(self, contract, order): oid = self.get_next_oid() self.tws.placeOrder(oid, contract, order) return oid # send order with Zipline style order arguments # <TODO> stop_price is not implemented def order(self, sid, amt, limit_price=None, stop_price=None): contract = self.get_contract_by_sid(sid) amt = int(amt) if limit_price is None: order = self.get_market_order(sid, amt) else: order = self.get_limit_order(sid, amt, limit_price) return self.place_order(contract, order) # subscribe to market data ticks def subscribe(self, sid): tid = self.get_next_tid() self.sid_to_tid[sid] = tid contract = self.get_contract_by_sid(sid) self.tws.reqMktData(tid, contract, '', False) return tid # subscribe to market data ticks for a list of tickers def subscribe_list(self, tickers): for tkr in tickers: self.subscribe(tkr) # cancel a market data subscription def unsubscribe(self, sid): if sid not in self.sid_to_tid.keys(): return tid = self.sid_to_tid[sid] self.tws.cancelMktData(tid) # cancel all market data subscriptions def unsubscribe_all(self): sids = self.sid_to_tid.keys() for sid in sids: self.unsubscribe(sid) # fetch a quote by ticker id tid def get_quote_by_tid(self, tid): return self.wrapper.tid_to_price[tid] # fetch a quote by ticker sid def get_quote(self, sid): if sid not in self.sid_to_tid: self.subscribe(sid) return (None, None) tid = self.sid_to_tid[sid] if tid not in self.wrapper.tid_to_price: price = None else: price = self.wrapper.tid_to_price[tid] if tid not in self.wrapper.tid_to_size: size = None else: size = self.wrapper.tid_to_size[tid] return (price, size) # fetch a price by ticker sid def get_price(self, sid): if sid not in self.sid_to_tid: self.subscribe(sid) return None tid = self.sid_to_tid[sid] if tid not in self.wrapper.tid_to_price: return None else: price_dict = self.wrapper.tid_to_price[tid] if 'price' in price_dict: return price_dict['price'] return None # get a Pandas DataFrame of current positions def get_positions_frame(self): ib_dict = {} for sid, position in self.wrapper.portfolio.sid_to_position.iteritems(): # <TODO> don't use vars here #ib_dict[sid] = vars(position) ib_dict[sid] = {'marketValue': position.marketValue, 'realizedPNL': position.realizedPNL, 'marketPrice': position.marketPrice, 'unrealizedPNL': position.unrealizedPNL, 'accountName': position.accountName, 'averageCost': position.averageCost, 'sid': position.sid, 'position': position.position} return pd.DataFrame.from_dict(ib_dict, orient='index')
class IBBroker(Broker): cid = 0 # connection id oid = 0 # order id tid = 0 # tick id (for fetching quotes) tws = None # Trader WorkStation wrapper = None # instance of EWrapper sid_to_tid = {} # map of security id to tick id def __init__(self, wrapper=None): Broker.__init__(self) # initialize a default wrapper if wrapper: self.wrapper = wrapper else: self.wrapper = WrapperDefault() # initialize the wrapper's portfolio object self.wrapper.portfolio = IBPortfolio() # get next order id def get_next_oid(self): IBBroker.oid += 1 return IBBroker.oid # get next connection id def get_next_cid(self): IBBroker.cid += 1 return IBBroker.cid # get next tick request id (for getting quotes) def get_next_tid(self): self.tid += 1 return self.tid # connect to TWS def connect(self, port=7496): if self.is_connected(): self.disconnect() cid = self.get_next_cid() self.tws = EPosixClientSocket(self.wrapper) self.tws.eConnect('', port, cid) # disconnect from TWS def disconnect(self): self.tws.eDisconnect() # check if TWS is connected def is_connected(self): if self.tws is None: return False return self.tws.isConnected() # Convert Zipline order signs into IB action strings def order_action(self, iSign): if iSign > 0: return 'BUY' elif iSign < 0: return 'SELL' raise Exception('Order of zero shares has no IB side: %i' % iSign) # get an IB contract by ticker def get_contract_by_sid(self, sid): contract = Contract() contract.symbol = sid contract.secType = 'STK' contract.exchange = 'SMART' contract.currency = 'USD' return contract # get a default IB market order def get_market_order(self, sid, amt): order = Order() order.action = self.order_action(amt) order.totalQuantity = abs(amt) order.orderType = 'MKT' order.tif = 'DAY' order.outsideRth = False return order # get a default IB limit order def get_limit_order(self, sid, amt, lmtPrice): order = Order() order.action = self.order_action(amt) order.totalQuantity = abs(amt) order.orderType = 'LMT' order.tif = 'DAY' order.outsideRth = False order.lmtPrice = lmtPrice return order # send the IB (contract, order) order to TWS def place_order(self, contract, order): oid = self.get_next_oid() self.tws.placeOrder(oid, contract, order) return oid # send order with Zipline style order arguments # <TODO> stop_price is not implemented def order(self, sid, amt, limit_price=None, stop_price=None): contract = self.get_contract_by_sid(sid) amt = int(amt) if limit_price is None: order = self.get_market_order(sid, amt) else: order = self.get_limit_order(sid, amt, limit_price) return self.place_order(contract, order) # subscribe to market data ticks def subscribe(self, sid): tid = self.get_next_tid() self.sid_to_tid[sid] = tid contract = self.get_contract_by_sid(sid) self.tws.reqMktData(tid, contract, '', False) return tid # subscribe to market data ticks for a list of tickers def subscribe_list(self, tickers): for tkr in tickers: self.subscribe(tkr) # cancel a market data subscription def unsubscribe(self, sid): if sid not in self.sid_to_tid.keys(): return tid = self.sid_to_tid[sid] self.tws.cancelMktData(tid) # cancel all market data subscriptions def unsubscribe_all(self): sids = self.sid_to_tid.keys() for sid in sids: self.unsubscribe(sid) # fetch a quote by ticker id tid def get_quote_by_tid(self, tid): return self.wrapper.tid_to_price[tid] # fetch a quote by ticker sid def get_quote(self, sid): if sid not in self.sid_to_tid: self.subscribe(sid) return (None, None) tid = self.sid_to_tid[sid] if tid not in self.wrapper.tid_to_price: price = None else: price = self.wrapper.tid_to_price[tid] if tid not in self.wrapper.tid_to_size: size = None else: size = self.wrapper.tid_to_size[tid] return (price, size) # fetch a price by ticker sid def get_price(self, sid): if sid not in self.sid_to_tid: self.subscribe(sid) return None tid = self.sid_to_tid[sid] if tid not in self.wrapper.tid_to_price: return None else: price_dict = self.wrapper.tid_to_price[tid] if 'price' in price_dict: return price_dict['price'] return None # get a Pandas DataFrame of current positions def get_positions_frame(self): ib_dict = {} for sid, position in self.wrapper.portfolio.sid_to_position.iteritems( ): # <TODO> don't use vars here #ib_dict[sid] = vars(position) ib_dict[sid] = { 'marketValue': position.marketValue, 'realizedPNL': position.realizedPNL, 'marketPrice': position.marketPrice, 'unrealizedPNL': position.unrealizedPNL, 'accountName': position.accountName, 'averageCost': position.averageCost, 'sid': position.sid, 'position': position.position } return pd.DataFrame.from_dict(ib_dict, orient='index')