Beispiel #1
0
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')
Beispiel #2
0
class TwsClient(object):
    logger = logging.getLogger(__name__)
    """Represents Interactive Broker's TWS."""
    _next_request_id = 0

    def __init__(self, client_id: int):
        """Initialises an instance for the specified client id."""
        self._client_id = client_id
        self._requests_lock = threading.Lock()
        self._requests = {}
        self._wrapper = _MulticastWrapper(self._requests, self._requests_lock)
        self._socket = EPosixClientSocket(self._wrapper)

    @property
    def client_id(self):
        return self._client_id

    def connect(self, host: str = "", port: int = 7496) -> Disconnecting:
        """Connects to TWS."""
        if not self._socket.eConnect(host, port, self.client_id):
            raise RuntimeError("Client[%d] Failed to connect at Host: %s, Port: %d" % \
            (self._client_id, host, port))
        TwsClient.logger.info("Client[%d] connected at Host: %s, Port: %d" %
                              (self._client_id, host, port))
        return Disconnecting(self._socket)

    def reqHistoricalData(self,
                          handler,
                          contract: Contract,
                          end_datetime: str,
                          duration: str = "1 D",
                          bar_size: BarSize = BarSize.Min1,
                          what_to_show: WhatToShow = WhatToShow.Trades,
                          use_rth: UseRth = UseRth.WithinTradingHour,
                          format_date: FormatDate = FormatDate.InString):
        """"""
        request = self._createRequest(RequestType.HistoricalData, handler)
        self._socket.reqHistoricalData(request.request_id, contract,
                                       end_datetime, duration, bar_size.value,
                                       what_to_show.value, use_rth.value,
                                       format_date.value)
        return request

    def reqMarketData(self,
                      handler,
                      contract: Contract,
                      generic_tick: str,
                      snapshot: bool = False):
        """"""
        request = self._createRequest(RequestType.MarketData, handler)
        self._socket.reqMktData(request.request_id, contract, generic_tick,
                                snapshot)
        return request

    def reqOpenOrders(self):
        return self._socket.reqOpenOrders()

    def cancelRequest(self, request: Request):
        """"""
        req_id = request.request_id
        with self._requests_lock:
            if self._requests.get(req_id) != request:
                return False
            del self._requests[req_id]
            try:
                {
                    RequestType.HistoricalData:
                    lambda: self._socket.cancelHistoricalData(req_id),
                    RequestType.MarketData:
                    lambda: self.cancelMktData(req_id)
                }[request.request_type]()
            except KeyError:
                raise LookupError(
                    "Client[%d] Reqest: %d - Unable to cancel unknown request type [%s]."
                    % (self._client_id, req_id, request.request_type.value))

    def cancelMktData(self, req_id):
        TwsClient.logger.info('MarketData request[%d] is cancelled.' % req_id)
        self._socket.cancelMktData(req_id)

    def _createRequest(self, req_type: RequestType, handler) -> Request:
        TwsClient._next_request_id += 1
        req_id = TwsClient._next_request_id
        request = Request(self, req_type, req_id, handler)
        with self._requests_lock:
            self._requests[req_id] = request
        return request
Beispiel #3
0
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')
Beispiel #4
0
#        "1 hour",                                    #barSizeSetting,
#        "BID_ASK",                                   #whatToShow,
#        0,                                          #useRTH,
#        1                                           #formatDate
#    )
#
#while (callback.close is None):
#    pass


#callback.accountEnd = False
#tws.reqAccountUpdates(1, '')
#while not callback.accountEnd:
#    pass

callback.askPrice = None
callback.lastPrice = None
callback.closePrice = None
callback.tickDataEnd = False
tws.reqMktData(2, contract, "", 0)

max_wait = timedelta(seconds=30) + datetime.now()
while callback.askPrice is None:
    time.sleep(0.0001)
    if datetime.now() > max_wait:
       print "max wait giving up"
       break
tws.cancelMktData(2)
print "Here's the ask price: ", callback.askPrice