# Connect to tws running on localhost tws.eConnect("", 7496, 42) # Simple contract for GOOG contract = Contract() contract.exchange = "SMART" contract.symbol = "GOOG" contract.secType = "STK" contract.currency = "USD" today = datetime.today() print("Requesting contract details...") # Perform the request tws.reqContractDetails( 42, # reqId, contract, # contract, ) print("\n=====================================================================") print(" Contract details requested, waiting for TWS responses") print("=====================================================================\n") print("******************* Press ENTER to quit when done *******************\n") input() print("\nDisconnecting...") tws.eDisconnect()
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')
print 'Still waiting for valid order id...' sleep(1) # Order details order = Order() order.action = 'BUY' order.lmtPrice = 0 order.auxPrice = 0 order.orderType = 'MTL' order.totalQuantity = 1 print "Placing order for %d %s's (id: %d)" % (order.totalQuantity, contract.symbol, orderId) # Place the order tws.placeOrder( orderId, # orderId, contract, # contract, order # order ) print "\n=====================================================================" print " Order placed, waiting for TWS responses" print "=====================================================================\n" print "******************* Press ENTER to quit when done *******************\n" raw_input() print "\nDisconnecting..." tws.eDisconnect()
def enterPositions(self, weights, execution_sleep=True): print "----------------------MAKING TRADES ON IB---------------------------" # Instantiate our callback object callback = self.PlaceOrderExample() # Instantiate a socket object, allowing us to call TWS directly. Pass our # callback object so TWS can respond. tws = EPosixClientSocket(callback) # Connect to tws running on localhost tws.eConnect("", 7496, 42) # account updates tws.reqAccountUpdates(True, self.accountNumber) sleep(1) print "available funds: %s" % (self.availableFunds) print "net liquidation value: %s" % (self.netLiquidationValue) ###DELAY UNTIL MARKET HOURS if execution_sleep: day_of_week = datetime.now().isoweekday() # if weekday, and we scanned after midnight, set execution time to this morning at 10:30 am time_now = datetime.now() if ( day_of_week in range(1, 6) and (time_now.hour >= 0 and time_now.hour < 10) and (time_now.minute >= 0 and time_now.minute < 30) ): execution_time = datetime( year=time_now.year, month=time_now.month, day=time_now.day, hour=10, minute=30 ) # otherwise, set to next trading day, morning at 10:30am else: execution_time = datetime.now() execution_time = execution_time + dt.timedelta(days=1) while execution_time.isoweekday() > 5: execution_time = execution_time + dt.timedelta(days=1) execution_time = datetime( year=execution_time.year, month=execution_time.month, day=execution_time.day, hour=10, minute=30 ) to_sleep = (execution_time - datetime.now()).total_seconds() print "----------sleeping until execution time of %s---------------" % (execution_time) # sleep until that time sleep(to_sleep) for stock in weights: print ("\n=====================================================================") print (" Trading " + stock) print ("=====================================================================\n") stock_price = Trader.get_quote([stock])[0][self.QUOTE_LAST] print "%s last stock price: %s" % (stock, stock_price) contract = Contract() contract.symbol = stock contract.secType = "STK" contract.exchange = "SMART" contract.currency = "USD" if self.orderId is None: print ("Waiting for valid order id") sleep(1) while self.orderId is None: print ("Still waiting for valid order id...") sleep(1) # Order details order = Order() order.action = "BUY" # order.lmtPrice = 140 order.orderType = "MKT" dollar_value = self.availableFunds * weights[stock] order.totalQuantity = int(round(dollar_value / stock_price, 0)) # order.algoStrategy = "AD" order.tif = "DAY" # order.algoParams = algoParams order.transmit = True print ( "Placing order for %d %s's, dollar value $%s (id: %d)" % (order.totalQuantity, contract.symbol, dollar_value, self.orderId) ) # Place the order tws.placeOrder(self.orderId, contract, order) # orderId, # contract, # order print ("\n=====================================================================") print (" Order placed, waiting for TWS responses") print ("=====================================================================\n") sleep(3) # reset orderid for next self.orderId = self.orderId + 1 print ("\n=====================================================================") print (" Trade done.") print ("=====================================================================\n") print ("******************* Press ENTER to quit when done *******************\n") input() print ("\nDisconnecting...") tws.eDisconnect()
class TradeManager(object): def __init__(self): self.accountNumber = '' self.optionExpiry = '20121221' # This needs manual updating! self.maxAskBidRatio = 1.25 self.maxAskLastPriceRatio = 1.02 self.maxOrderQueueLength = 3 # Create a file for TWS logging self.twslog_fh = open('/home/mchan/git/Artemis/twslog.txt', 'a', 0) self.twslog_fh.write("Session Started " + str(datetime.datetime.now()) + "\n") self.callback = ArtemisIBWrapperSilent.ArtemisIBWrapper() self.tws = EPosixClientSocket(self.callback) self.orderIdCount = 1 # This will be updated automatically self.requestIdCount = 1 self.invested = False self.maxLimitPriceFactor = 1.02 # No limit orders above 2% of current ask price # Connect the socket self.socketnum = 30 self.tws.eConnect("", 7496, self.socketnum, poll_interval=1) # Strategy Generic object, has methods for interpreting consensus out/under performance self.Strat = strategy.Strategy() # Queue for orders self.orderQueue = [] # Setup DB connector self.db = dbutil.db(h='127.0.0.1', schema='mchan') # Query Cash Account Balance self.updateBuyingPowerNextId() def updateBuyingPowerNextId(self): self.callback.myNextValidId = None self.callback.buyingPower = None self.tws.reqAccountUpdates(1, self.accountNumber) while (self.callback.buyingPower is None or self.callback.myNextValidId is None): pass self.buyingPower = float(self.callback.buyingPower) self.orderIdCount = int(self.callback.myNextValidId) print "Buying Power recognized: ", self.buyingPower, " Next valid id recognized: ", self.orderIdCount self.tws.reqAccountUpdates(0, self.accountNumber) def calcInvSize(self): ''' Calculates proper investment size ''' # We take the total size of the portfolio, cash plus stock, and we divide by four # The reasoning is that we want to avoid the day pattern trader restriction # Dividing our portfolio size by four ensures that we have enough capital # to trade for the four trading opportunities that will happen until we can # finally sell our positions # This also allows for diversification self.updateBuyingPowerNextId() portfolioList = self.getPortfolio() secMarketPositions = 0 for myContract, myPosition, myMarketValue in portfolioList: secMarketPositions += myMarketValue totalPortfolioSize = secMarketPositions + self.buyingPower investmentSize = min(self.buyingPower, (totalPortfolioSize/4.0)) print "CALCULATE INVESTMENT SIZE: ", str(investmentSize) return investmentSize def twsReconnect(self): print "Reconnecting TWS" self.twslog_fh.write("Reconnecting TWS" + str(datetime.datetime.now()) + '\n') self.tws.eDisconnect() try: self.tws.eConnect("", 7496, self.socketnum, poll_interval=1) except TWSError, e: print e print "Attempting to reconnect:" for i in range(0,5): time.sleep(5) print "Try ", i try: self.tws.eConnect("", 7496, self.socketnum, poll_interval=1) break except TWSError, e: print e
class SwigIBClient(EWrapper): '''Callback object passed to TWS, these functions will be called directly by TWS. ''' def __init__(self, port=4001, client_id=12): super(SwigIBClient, self).__init__() self.tws = EPosixClientSocket(self) self.port = port self.client_id = client_id self.got_history = Event() self.got_contract = Event() self.got_err = Event() self.order_filled = Event() self.order_ids = Queue() def execDetails(self, id, contract, execution): pass def managedAccounts(self, openOrderEnd): pass ### Order def nextValidId(self, validOrderId): '''Capture the next order id''' self.order_ids.put(validOrderId) def orderStatus(self, id, status, filled, remaining, avgFillPrice, permId, parentId, lastFilledPrice, clientId, whyHeld): print(("Order #%s - %s (filled %d, remaining %d, avgFillPrice %f," "last fill price %f)") % (id, status, filled, remaining, avgFillPrice, lastFilledPrice)) if remaining <= 0: self.order_filled.set() def openOrder(self, orderID, contract, order, orderState): print("Order opened for %s" % contract.symbol) def openOrderEnd(self): pass def commissionReport(self, commissionReport): print 'Commission %s %s P&L: %s' % (commissionReport.currency, commissionReport.commission, commissionReport.realizedPNL) ### Historical data def historicalData(self, reqId, date, open, high, low, close, volume, barCount, WAP, hasGaps): if date[:8] == 'finished': print("History request complete") self.got_history.set() else: date = datetime.strptime(date, "%Y%m%d").strftime("%d %b %Y") print(("History %s - Open: %s, High: %s, Low: %s, Close: " "%s, Volume: %d") % (date, open, high, low, close, volume)) ### Contract details def contractDetailsEnd(self, reqId): print("Contract details request complete, (request id %i)" % reqId) def contractDetails(self, reqId, contractDetails): print("Contract details received (request id %i):" % reqId) print("callable: %s" % contractDetails.callable) print("category: %s" % contractDetails.category) print("contractMonth: %s" % contractDetails.contractMonth) print("convertible: %s" % contractDetails.convertible) print("coupon: %s" % contractDetails.coupon) print("industry: %s" % contractDetails.industry) print("liquidHours: %s" % contractDetails.liquidHours) print("longName: %s" % contractDetails.longName) print("marketName: %s" % contractDetails.marketName) print("minTick: %s" % contractDetails.minTick) print("nextOptionPartial: %s" % contractDetails.nextOptionPartial) print("orderTypes: %s" % contractDetails.orderTypes) print("priceMagnifier: %s" % contractDetails.priceMagnifier) print("putable: %s" % contractDetails.putable) if contractDetails.secIdList is not None: for secId in contractDetails.secIdList: print("secIdList: %s" % secId) else: print("secIdList: None") print("subcategory: %s" % contractDetails.subcategory) print("tradingHours: %s" % contractDetails.tradingHours) print("timeZoneId: %s" % contractDetails.timeZoneId) print("underConId: %s" % contractDetails.underConId) print("evRule: %s" % contractDetails.evRule) print("evMultiplier: %s" % contractDetails.evMultiplier) contract = contractDetails.summary print("\nContract Summary:") print("exchange: %s" % contract.exchange) print("symbol: %s" % contract.symbol) print("secType: %s" % contract.secType) print("currency: %s" % contract.currency) print("tradingClass: %s" % contract.tradingClass) if contract.comboLegs is not None: for comboLeg in contract.comboLegs: print("comboLegs: %s - %s" % (comboLeg.action, comboLeg.exchange)) else: print("comboLegs: None") print("\nBond Values:") print("bondType: %s" % contractDetails.bondType) print("couponType: %s" % contractDetails.couponType) print("cusip: %s" % contractDetails.cusip) print("descAppend: %s" % contractDetails.descAppend) print("issueDate: %s" % contractDetails.issueDate) print("maturity: %s" % contractDetails.maturity) print("nextOptionDate: %s" % contractDetails.nextOptionDate) print("nextOptionType: %s" % contractDetails.nextOptionType) print("notes: %s" % contractDetails.notes) print("ratings: %s" % contractDetails.ratings) print("validExchanges: %s" % contractDetails.validExchanges) self.got_contract.set() ### Error def error(self, id, errCode, errString): if errCode == 165 or (errCode >= 2100 and errCode <= 2110): print("TWS warns %s" % errString) elif errCode == 502: print('Looks like TWS is not running, ' 'start it up and try again') sys.exit() elif errCode == 501: print("TWS reports error in client: %s" % errString) elif errCode >= 1100 and errCode < 2100: print("TWS reports system error: %s" % errString) elif errCode == 321: print("TWS complaining about bad request: %s" % errString) else: super(SwigIBClient, self).error(id, errCode, errString) self.got_err.set() def winError(self, msg, lastError): print("TWS reports API error: %s" % msg) self.got_err.set() def pyError(self, type, val, tb): sys.print_exception(type, val, tb) ### def connect(self): if not self.tws.eConnect("", self.port, self.client_id): raise RuntimeError('Failed to connect to TWS') def disconnect(self): print("\nDisconnecting...") self.tws.eDisconnect() def create_contract(self): # Simple contract for GOOG contract = Contract() contract.exchange = "SMART" contract.symbol = "GOOG" contract.secType = "STK" contract.currency = "USD" return contract def request_contract_details(self, contract): today = datetime.today() print("Requesting contract details...") # Perform the request self.tws.reqContractDetails( 42, # reqId, contract, # contract, ) print("\n====================================================================") print(" Contract details requested, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") try: self.got_contract.wait(timeout=WAIT_TIME) except KeyboardInterrupt: pass finally: if not self.got_contract.is_set(): print('Failed to get contract within %d seconds' % WAIT_TIME) def request_hist_data(self, contract): today = datetime.today() print("Requesting historical data for %s" % contract.symbol) # Request some historical data. self.tws.reqHistoricalData( 2, # tickerId, contract, # contract, today.strftime("%Y%m%d %H:%M:%S %Z"), # endDateTime, "1 W", # durationStr, "1 day", # barSizeSetting, "TRADES", # whatToShow, 0, # useRTH, 1 # formatDate ) print("\n====================================================================") print(" History requested, waiting %ds for TWS responses" % WAIT_TIME) print(" History requested, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") try: self.got_history.wait(timeout=WAIT_TIME) except KeyboardInterrupt: pass finally: if not self.got_history.is_set(): print('Failed to get history within %d seconds' % WAIT_TIME) def subscribe_market_data(self, contract): pass def unsubscribe_market_data(self, contract): pass def place_order(self, contract): print('Waiting for valid order id') order_id = self.order_ids.get(timeout=WAIT_TIME) if not order_id: raise RuntimeError('Failed to receive order id after %ds' % WAIT_TIME) # Order details algoParams = TagValueList() algoParams.append(TagValue("componentSize", "3")) algoParams.append(TagValue("timeBetweenOrders", "60")) algoParams.append(TagValue("randomizeTime20", "1")) algoParams.append(TagValue("randomizeSize55", "1")) algoParams.append(TagValue("giveUp", "1")) algoParams.append(TagValue("catchUp", "1")) algoParams.append(TagValue("waitForFill", "1")) algoParams.append(TagValue("startTime", "20110302-14:30:00 GMT")) algoParams.append(TagValue("endTime", "20110302-21:00:00 GMT")) order = Order() order.action = 'BUY' order.lmtPrice = 140 order.orderType = 'LMT' order.totalQuantity = 10 order.algoStrategy = "AD" order.tif = 'DAT' order.algoParams = algoParams # order.transmit = False print("Placing order for %d %s's (id: %d)" % (order.totalQuantity, contract.symbol, order_id)) # Place the order self.tws.placeOrder( order_id, # orderId, contract, # contract, order # order ) print("\n====================================================================") print(" Order placed, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") print("Waiting for order to be filled..") try: self.order_filled.wait(WAIT_TIME) except KeyboardInterrupt: pass finally: if not self.order_filled.is_set(): print('Failed to fill order')
class TradeManager(object): def __init__(self): self.accountNumber = '' self.optionExpiry = '20121221' # This needs manual updating! self.maxAskBidRatio = 1.25 self.maxAskLastPriceRatio = 1.02 self.maxOrderQueueLength = 3 # Create a file for TWS logging self.twslog_fh = open('/home/mchan/git/Artemis/twslog.txt', 'a', 0) self.twslog_fh.write("Session Started " + str(datetime.datetime.now()) + "\n") self.callback = ArtemisIBWrapperSilent.ArtemisIBWrapper() self.tws = EPosixClientSocket(self.callback) self.orderIdCount = 1 # This will be updated automatically self.requestIdCount = 1 self.invested = False self.maxLimitPriceFactor = 1.02 # No limit orders above 2% of current ask price # Connect the socket self.socketnum = 30 self.tws.eConnect("", 7496, self.socketnum, poll_interval=1) # Strategy Generic object, has methods for interpreting consensus out/under performance self.Strat = strategy.Strategy() # Queue for orders self.orderQueue = [] # Setup DB connector self.db = dbutil.db(h='127.0.0.1', schema='mchan') # Query Cash Account Balance self.updateBuyingPowerNextId() def updateBuyingPowerNextId(self): self.callback.myNextValidId = None self.callback.buyingPower = None self.tws.reqAccountUpdates(1, self.accountNumber) while (self.callback.buyingPower is None or self.callback.myNextValidId is None): pass self.buyingPower = float(self.callback.buyingPower) self.orderIdCount = int(self.callback.myNextValidId) print "Buying Power recognized: ", self.buyingPower, " Next valid id recognized: ", self.orderIdCount self.tws.reqAccountUpdates(0, self.accountNumber) def calcInvSize(self): ''' Calculates proper investment size ''' # We take the total size of the portfolio, cash plus stock, and we divide by four # The reasoning is that we want to avoid the day pattern trader restriction # Dividing our portfolio size by four ensures that we have enough capital # to trade for the four trading opportunities that will happen until we can # finally sell our positions # This also allows for diversification self.updateBuyingPowerNextId() portfolioList = self.getPortfolio() secMarketPositions = 0 for myContract, myPosition, myMarketValue in portfolioList: secMarketPositions += myMarketValue totalPortfolioSize = secMarketPositions + self.buyingPower investmentSize = min(self.buyingPower, (totalPortfolioSize / 4.0)) print "CALCULATE INVESTMENT SIZE: ", str(investmentSize) return investmentSize def twsReconnect(self): print "Reconnecting TWS" self.twslog_fh.write("Reconnecting TWS" + str(datetime.datetime.now()) + '\n') self.tws.eDisconnect() try: self.tws.eConnect("", 7496, self.socketnum, poll_interval=1) except TWSError, e: print e print "Attempting to reconnect:" for i in range(0, 5): time.sleep(5) print "Try ", i try: self.tws.eConnect("", 7496, self.socketnum, poll_interval=1) break except TWSError, e: print e
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')