Пример #1
0
class IBProvider(BaseProvider):
    def __init__(self):
        basicConfig()
        # These two variables are initialized in Connect method
        self._connection = None
        self._wrapper = None
        self._request_id = 0

    def connect(self):
        self._wrapper = ReferenceWrapper()
        self._connection = EClientSocket(self._wrapper)
        self._connection.eConnect(IB_HOST, IB_PORT, IB_PROVIDER_CLIENT_ID)

    def disconnect(self):
        if self._connection.isConnected():
            self._connection.eDisconnect()

    def _make_contract(self, symbol):
        contract = Contract()
        contract.m_symbol = symbol
        contract.m_secType = 'STK'
        contract.m_exchange = 'SMART'
        contract.m_primaryExch = 'SMART'
        contract.m_currency = 'USD'
        contract.m_localSymbol = symbol
        return contract

    def _get_next_request_id(self):
        self._request_id += 1
        return self._request_id

    def get_market_depth_L1(self, symbol):
        contract = self._make_contract(symbol)
        request_id = self._get_next_request_id()
        self._connection.reqMktData(request_id, contract, '', True)
        while not self._wrapper.isExecutionRequestFinished(request_id):
            err = self._wrapper.getError(request_id)
            if err is not None:
                raise Exception(err)
            very_short_sleep()
        return self._wrapper.getMarketDepthL1(request_id)
Пример #2
0
class IBBroker(BaseBroker):
    def __init__(self):
        basicConfig()
        # These two variables are initialized in Connect method
        self._connection = None
        self._wrapper = None
        self._request_id = 0

    def _get_next_request_id(self):
        self._request_id += 1
        return self._request_id

    def get_security(self, symbol):
        contract = IBSecurity()
        contract.Symbol = symbol
        contract.symbol_id = 0
        contract.Currency = 'USD'
        return contract

    def _get_next_valid_order_id(self):
        """
        You must assign a unique order ID to each order you place. IB's servers
        keep track of the next available order ID you can use; this function
        requests that value from IB's servers, waits until IB sends a response,
        then returns the ID.
        """
        last_time = self._wrapper._time_received_next_valid_order_id
        self._connection.reqIds(1)
        # Wait until IB sends the next valid ID
        while last_time == self._wrapper._time_received_next_valid_order_id:
            very_short_sleep()
        return self._wrapper._next_valid_order_id

    def _request_current_time(self):
        self._connection.reqCurrentTime()

    def connect(self):
        self._wrapper = ReferenceWrapper()
        self._connection = EClientSocket(self._wrapper)
        self._connection.eConnect(IB_HOST, IB_PORT, IB_CLIENT_ID)

    def disconnect(self):
        if self._connection.isConnected():
            self._connection.eDisconnect()

    def send_pre_trade(self, trade_info): # trade info is fa profile

        self._connection.requestFA(self._connection.PROFILES)
        self._connection.replaceFA(self._connection.PROFILES, trade_info)

    def send_order(self, order):
        order.__class__ = IBOrder # casting to IBOrder
        order.prepare_IB_order()
        order_id = self._get_next_valid_order_id()
        contract = self.get_security(order.Symbol)
        #order.m_transmit = True # forces IB to transmit order straight away
        self._connection.placeOrder(order_id, contract, order) # places order
        order.Status = Order.StatusChoice.Sent.value # order status is set to SENT
        order.Order_Id = order_id # sets broker specific ID
        while not self._wrapper.isOpeningOfOrdersFinished(order_id):
            err = self._wrapper.getError(order_id)
            if err is not None:
                raise Exception(err)
            very_short_sleep()
            #if(self._wrapper.isError(id)):
            #   raise Exception(self.wrapper.isError(id))

    def update_orders(self, orders):
        requestId = self._get_next_request_id()
        exf = ExecutionFilter()
        distribution = {}
        self._connection.reqExecutions(requestId, exf)  #
        while not self._wrapper.isExecutionRequestFinished(requestId):
            err = self._wrapper.getError(requestId)
            if err is not None:
                raise Exception(err)
            very_short_sleep()
        executions = self._wrapper.getExecutions(requestId)
        for order in orders:
            price = 0
            shares = 0
            if executions is not None:
                for execution in executions:
                    if execution.m_shares > 0 and execution.m_orderId == order.Order_Id and not execution.m_acctNumber.startswith('DF'):
                        price = execution.m_price
                        if order.Symbol not in distribution:
                            distribution[order.Symbol] = {}
                        if execution.m_acctNumber not in distribution[order.Symbol]:
                            distribution[order.Symbol][execution.m_acctNumber] = 0
                        distribution[order.Symbol][execution.m_acctNumber] += execution.m_shares
                        shares += execution.m_shares
                if price != 0:
                    order.setFills(price, shares)
        return distribution

    def get_account_info(self, broker_account):
        requestId = self._get_next_request_id()
        self._connection.reqAccountSummary(requestId, 'All', 'AccountType,TotalCashValue')
        while not self._wrapper.isExecutionRequestFinished(requestId):
            err = self._wrapper.getError(requestId)
            max_resp = self._wrapper.getMaxRequestFailureError()
            if err is not None:
                raise Exception(err)
            if max_resp:
                raise Exception("Maximum number of account summary requests exceeded")
            very_short_sleep()
        return self._wrapper.getAccountInfo(broker_account.ib_account)
Пример #3
0
    
    
    
    # Connection and Server ##############################################################
    # EClientSocket
    # eConnect                     
    # eDisconnect          --->   connectionClosed      
    # isConnected
    # setServerLogLevel
    # reqCurrentTime       --->   currentTime           self.current_Time
    # serverVersion
    # TwsConnectionTime
    #                      --->   error
    ###################################################################################'''
    print "Testing Connection and Server Group \n"
    print tws.isConnected()
    tws.setServerLogLevel(5)
    tws.reqCurrentTime()
    print "Server Version " + str(tws.serverVersion())
    print "TWS Connection Time %s " % tws.TwsConnectionTime()

    # Executions #########################################################################
    # reqExecutions        --->   execDetails           self.exec_Details_reqId
    #                                                   self.exec_Details_contract
    #                                                   self.exec_Details_execution
    #                      --->   execDetailsEnd        self.exec_DetailsEnd_flag
    #                      --->   commissionReport      self.commission_Report
    ###################################################################################'''
    print "Testing Executions Group \n"
    order_id = []
    tws.reqIds(1)
Пример #4
0
    
    
    
    # Connection and Server ##############################################################
    # EClientSocket
    # eConnect                     
    # eDisconnect          --->   connectionClosed      
    # isConnected
    # setServerLogLevel
    # reqCurrentTime       --->   currentTime           self.current_Time
    # serverVersion
    # TwsConnectionTime
    #                      --->   error
    ###################################################################################'''
    print("Testing Connection and Server Group \n")
    print(tws.isConnected())
    tws.setServerLogLevel(5)
    tws.reqCurrentTime()
    print("Server Version " + str(tws.serverVersion()))
    print("TWS Connection Time %s " % tws.TwsConnectionTime())

    # Executions #########################################################################
    # reqExecutions        --->   execDetails           self.exec_Details_reqId
    #                                                   self.exec_Details_contract
    #                                                   self.exec_Details_execution
    #                      --->   execDetailsEnd        self.exec_DetailsEnd_flag
    #                      --->   commissionReport      self.commission_Report
    ###################################################################################'''
    print("Testing Executions Group \n")
    order_id = []
    tws.reqIds(1)
Пример #5
0
            print(
                "\n###################### No orders to show #######################\n"
            )

        return df_order_status


# Establish connection ----------------------------------------------------------------------
#accountName = "Your Account Name Here"
callback = IBWrapper()  # Instantiate IBWrapper. callback
tws = EClientSocket(
    callback)  # Instantiate EClientSocket and return data to callback
host = ""
port = 4002
clientId = 8
tws.eConnect(host, port, clientId)  # Connect to TWS
create = contract()  # Instantiate contract class
callback.initiate_variables()
tws.reqAccountUpdates(1, accountName)

# Portfolio Query ------------------------------------------------------------

ib = IB()
df_portfolio = ib.portfolio()
count = len(df_portfolio)

# Disconnect ------------------------------------------------------------------
time.sleep(2)
tws.isConnected()
tws.eDisconnect()
Пример #6
0
            print('low than ratio')
            tws.cancelOrder(order_id)   # preventing double transaction
            
            tws.reqIds(1)   # Need to request next valid order Id
            time.sleep(1)   # change this if next Id is empty
            order_id = data.next_ValidId
            
            contract  = cont.create_contract('TVIX', 'STK', 'SMART', 'SMART', 'USD')
            order = cont.create_order(accountId, 'STP', position, 'SELL' )
            tws.placeOrder(order_id, contract, order)
            
            tws.reqIds(1)   # Need to request next valid order Id
            time.sleep(1)   # change this if next Id is empty
            order_id = data.next_ValidId
            
            contract  = cont.create_contract('UVXY', 'STK', 'SMART', 'SMART', 'USD')
            order = cont.create_order(accountId, 'STP', position, 'SELL' )
            tws.placeOrder(order_id, contract, order)
    '''
    time.sleep(2)
    if(tws.isConnected()):
        tws.eDisconnect() 
    
'''
Message:
while loop??
tws.isConnected() outside while loop, so it disconnect when certain cond satisfied?
scheduler to reconnect and disconnect (set up crontab on unix)
'''

Пример #7
0
    
    
    
    # Connection and Server ##############################################################
    # EClientSocket
    # eConnect                     
    # eDisconnect          --->   connectionClosed      
    # isConnected
    # setServerLogLevel
    # reqCurrentTime       --->   currentTime           self.current_Time
    # serverVersion
    # TwsConnectionTime
    #                      --->   error
    ###################################################################################'''       
    print "Testing Connection and Server Group \n"
    print  tws.isConnected()
    tws.setServerLogLevel(5)
    tws.reqCurrentTime()
    print "Server Version " + str(tws.serverVersion())
    print "TWS Connection Time %s " % tws.TwsConnectionTime()





    # Executions #########################################################################
    # reqExecutions        --->   execDetails           self.exec_Details_reqId
    #                                                   self.exec_Details_contract
    #                                                   self.exec_Details_execution
    #                      --->   execDetailsEnd        self.exec_DetailsEnd_flag
    #                      --->   commissionReport      self.commission_Report
Пример #8
0
class TWS_gateway(threading.Thread):

    # config
    config = None
    # redis connection
    rs = None

    # channel clients' requests to IB/TWS
    cli_request_handler = None

    # manage conID / contracts mapping
    contract_subscription_mgr = None

    connection = None

    # handler to process incoming IB/TWS messages and echo back to clients
    tws_event_handler = None

    # monitor IB connection / heart beat
    ibh = None
    tlock = None
    ib_conn_status = None
    ib_order_transmit = False

    def __init__(self, host, port, clientId, kafka_host, kafka_port, config):
        super(TWS_gateway, self).__init__()
        self.config = config
        self.host = host
        self.port = port
        self.clientId = clientId
        self.ib_order_transmit = config.get("tws_gateway", "tws_gateway.order_transmit").strip('"').strip("'") if \
                                        config.get("tws_gateway", "tws_gateway.order_transmit").strip('"').strip("'") <> None\
                                        else False

        logging.info('starting up TWS_gateway...')
        logging.info('Order straight through (no-touch) flag = %s' %
                     ('True' if self.ib_order_transmit == True else 'False'))

        logging.info('connecting to Redis server...')
        self.initialize_redis(config)

        logging.info('starting up TWS_event_handler...')
        self.tws_event_handler = TWS_event_handler(kafka_host, kafka_port)

        logging.info('starting up IB EClientSocket...')
        self.connection = EClientSocket(self.tws_event_handler)

        logging.info('starting up client request handler - kafkaConsumer...')
        self.cli_request_handler = KafkaConsumer( *[(v,0) for v in list(TWS_Protocol.topicMethods) + list(TWS_Protocol.gatewayMethods) ], \
                                   metadata_broker_list=['%s:%s' % (kafka_host, kafka_port)],\
                                   group_id = 'epc.tws_gateway',\
                                   auto_commit_enable=True,\
                                   auto_commit_interval_ms=30 * 1000,\
                                   auto_offset_reset='largest') # discard old ones

        self.reset_message_offset()

        if not self.eConnect():
            logging.error(
                'TWS_gateway: unable to establish connection to IB %s:%d' %
                (self.host, self.port))
            sys.exit(-1)
        else:
            # start heart beat monitor
            logging.info('starting up IB heart beat monitor...')
            self.tlock = Lock()
            self.ibh = IbHeartBeat(config)
            self.ibh.register_listener([self.on_ib_conn_broken])
            self.ibh.run()

        logging.info('starting up subscription manager...')
        self.initialize_subscription_mgr()

    def initialize_subscription_mgr(self):

        self.contract_subscription_mgr = SubscriptionManager(self)
        self.contract_subscription_mgr.register_persistence_callback(
            self.persist_subscriptions)
        key = self.config.get(
            "tws_gateway",
            "subscription_manager.subscriptions.redis_key").strip('"').strip(
                "'")
        if self.rs.get(key):
            #contracts = map(lambda x: ContractHelper.kvstring2contract(x), json.loads(self.rs.get(key)))

            def is_outstanding(c):

                today = time.strftime('%Y%m%d')
                if c.m_expiry < today:
                    logging.info(
                        'initialize_subscription_mgr: ignoring expired contract %s%s%s'
                        % (c.m_expiry, c.m_strike, c.m_right))
                    return False
                return True

            contracts = filter(
                lambda x: is_outstanding(x),
                map(lambda x: ContractHelper.kvstring2object(x, Contract),
                    json.loads(self.rs.get(key))))

            self.contract_subscription_mgr.load_subscription(contracts)

    def persist_subscriptions(self, contracts):

        key = self.config.get(
            "tws_gateway",
            "subscription_manager.subscriptions.redis_key").strip('"').strip(
                "'")
        #cs = json.dumps(map(lambda x: ContractHelper.contract2kvstring(x) if x <> None else None, contracts))
        cs = json.dumps(
            map(
                lambda x: ContractHelper.object2kvstring(x)
                if x <> None else None, contracts))
        logging.debug(
            'Tws_gateway: updating subscription table to redis store %s' % cs)
        self.rs.set(key, cs)

    def initialize_redis(self, config):
        r_host = config.get("redis", "redis.server").strip('"').strip("'")
        r_port = config.get("redis", "redis.port")
        r_db = config.get("redis", "redis.db")

        self.rs = redis.Redis(r_host, r_port, r_db)
        try:
            self.rs.client_list()
        except redis.ConnectionError:
            logging.error(
                'TWS_gateway: unable to connect to redis server using these settings: %s port:%d db:%d'
                % (r_host, r_port, r_db))
            logging.error('aborting...')
            sys.exit(-1)

    def reset_message_offset(self):
        topic_offsets = map(
            lambda topic: (topic,
                           self.cli_request_handler.get_partition_offsets(
                               topic, 0, -1, 999)),
            TWS_Protocol.topicMethods + TWS_Protocol.gatewayMethods)
        topic_offsets = filter(
            lambda x: x <> None,
            map(lambda x: (x[0], x[1][1], x[1][0])
                if len(x[1]) > 1 else None, topic_offsets))
        logging.info('TWS_gateway set topic offset to the latest point\n%s' %
                     (''.join('%s,%s,%s\n' % (x[0], x[1], x[2])
                              for x in topic_offsets)))

        # the set_topic_partitions method clears out all previous settings when executed
        # therefore it's not possible to call the function multiple times:
        # self.consumer.set_topic_partitions(('gw_subscriptions', 0, 114,)
        # self.consumer.set_topic_partitions(('tickPrice', 0, 27270,))
        # as the second call will wipe out whatever was done previously

        self.cli_request_handler.set_topic_partitions(*topic_offsets)

    def run(self):

        for message in self.cli_request_handler:

            logging.info("%s:%d:%d: key=%s value=%s" %
                         (message.topic, message.partition, message.offset,
                          message.key, message.value))

            #             print ("TWS_gateway: received client request %s:%d:%d: key=%s value=%s" % (message.topic, message.partition,
            #                                          message.offset, message.key,
            #                                          message.value))

            getattr(self, message.topic, None)(message.value)
            #self.cli_request_handler.task_done(message)

    def on_ib_conn_broken(self, msg):
        logging.error('TWS_gateway: detected broken IB connection!')
        self.ib_conn_status = 'ERROR'
        self.tlock.acquire()  # this function may get called multiple times
        try:  # block until another party finishes executing
            if self.ib_conn_status == 'OK':  # check status
                return  # if already fixed up while waiting, return

            self.eDisconnect()
            self.eConnect()
            while not self.connection.isConnected():
                logging.error('TWS_gateway: attempt to reconnect...')
                self.eConnect()
                sleep(2)

            # we arrived here because the connection has been restored
            # resubscribe tickers again!
            logging.info(
                'TWS_gateway: IB connection restored...resubscribe contracts')
            self.contract_subscription_mgr.force_resubscription()

        finally:
            self.tlock.release()

    def eConnect(self):
        logging.info('TWS_gateway - eConnect. Connecting to %s:%s App Id: %s' %
                     (self.host, self.port, self.clientId))
        self.connection.eConnect(self.host, self.port, self.clientId)
        return self.connection.isConnected()

    def reqAccountUpdates(self, value=None):
        logging.info('TWS_gateway - reqAccountUpdates value=%s' % value)
        self.connection.reqAccountUpdates(1, '')

    def reqAccountSummary(self, value):
        logging.info('TWS_gateway - reqAccountSummary value=%s' % value)

        vals = map(
            lambda x: x.encode('ascii') if isinstance(x, unicode) else x,
            json.loads(value))
        self.connection.reqAccountSummary(vals[0], vals[1], vals[2])

    def reqOpenOrders(self, value=None):
        self.connection.reqOpenOrders()

    def reqPositions(self, value=None):
        self.connection.reqPositions()

    def reqExecutions(self, value):
        try:
            filt = ExecutionFilter(
            ) if value == '' else ExecutionFilterHelper.kvstring2object(
                value, ExecutionFilter)
            self.connection.reqExecutions(0, filt)
        except:
            logging.error(traceback.format_exc())

    def reqIds(self, value=None):
        self.connection.reqIds(1)

    def reqNewsBulletins(self):
        self.connection.reqNewsBulletins(1)

    def cancelNewsBulletins(self):
        self.connection.cancelNewsBulletins()

    def setServerLogLevel(self):
        self.connection.setServerLogLevel(3)

    def reqAutoOpenOrders(self):
        self.connection.reqAutoOpenOrders(1)

    def reqAllOpenOrders(self):
        self.connection.reqAllOpenOrders()

    def reqManagedAccts(self):
        self.connection.reqManagedAccts()

    def requestFA(self):
        self.connection.requestFA(1)

    def reqMktData(self, sm_contract):
        logging.info('TWS Gateway received reqMktData request: %s' %
                     sm_contract)
        try:
            #self.contract_subscription_mgr.reqMktData(ContractHelper.kvstring2contract(sm_contract))
            self.contract_subscription_mgr.reqMktData(
                ContractHelper.kvstring2object(sm_contract, Contract))
        except:
            pass

    def reqHistoricalData(self):
        contract = Contract()
        contract.m_symbol = 'QQQQ'
        contract.m_secType = 'STK'
        contract.m_exchange = 'SMART'
        endtime = strftime('%Y%m%d %H:%M:%S')
        self.connection.reqHistoricalData(tickerId=1,
                                          contract=contract,
                                          endDateTime=endtime,
                                          durationStr='1 D',
                                          barSizeSetting='1 min',
                                          whatToShow='TRADES',
                                          useRTH=0,
                                          formatDate=1)

    def placeOrder(self, value=None):
        logging.info('TWS_gateway - placeOrder value=%s' % value)
        try:
            vals = json.loads(value)
        except ValueError:
            logging.error('TWS_gateway - placeOrder Exception %s' %
                          traceback.format_exc())
            return

#        c = ContractHelper.kvstring2contract(vals[1])
        o = OrderHelper.kvstring2object(vals[2], Order)
        o.__dict__['transmit'] = self.ib_order_transmit
        #         print c.__dict__
        #         print o.__dict__
        #         print '---------------------'

        #self.connection.placeOrder(vals[0], ContractHelper.kvstring2contract(vals[1]), OrderHelper.kvstring2object(vals[2], Order))
        self.connection.placeOrder(
            vals[0], ContractHelper.kvstring2object(vals[1], Contract),
            OrderHelper.kvstring2object(vals[2], Order))
#        self.connection.placeOrder(orderId, contract, newOptOrder)

    def eDisconnect(self, value=None):
        sleep(2)
        self.connection.eDisconnect()


####################################################################3
#   Gateway commands

    def gw_req_subscriptions(self, value=None):

        #subm = map(lambda i: ContractHelper.contract2kvstring(self.contract_subscription_mgr.handle[i]), range(len(self.contract_subscription_mgr.handle)))
        #subm = map(lambda i: ContractHelper.object2kvstring(self.contract_subscription_mgr.handle[i]), range(len(self.contract_subscription_mgr.handle)))
        subm = map(
            lambda i: (i,
                       ContractHelper.object2kvstring(
                           self.contract_subscription_mgr.handle[i])),
            range(len(self.contract_subscription_mgr.handle)))

        print subm
        if subm:
            self.tws_event_handler.broadcast_event('gw_subscriptions',
                                                   {'subscriptions': subm},
                                                   source='GW')