Search code examples
pythoninteractive-brokersibpy

get forex rate from IB api with python


I'm trying to get currency rates from interactive broker using ibpy library and there is code i found on google and i changed a little.

from ib.ext.Contract import Contract
from ib.opt import ibConnection, message
from time import sleep

# print all messages from TWS
def watcher(msg):
    print msg

# show Bid and Ask quotes
def my_BidAsk(msg):

    if msg.field == 1:
        print ('bid: %s' % ( msg.price)) 
        bid=msg.price
    elif msg.field == 2:
        print ('ask: %s' % (msg.price)) 
        ask=msg.price
    elif msg.field==9:
        print ('last close: %s' % msg.price) 
        last=msg.price

def makeStkContract(contractTuple):
    newContract = Contract() 

    newContract.m_symbol = contractTuple[0]
    newContract.m_secType = contractTuple[1]
    newContract.m_exchange = contractTuple[2]
    newContract.m_primaryExch=contractTuple[3]
    newContract.m_currency = contractTuple[4]

    print ('Contract Values:%s,%s,%s,%s,%s:' % contractTuple)
    return newContract

if __name__ == '__main__':
    global bid,ask,last
    bid=None
    ask=None
    last=None
    # con = ibConnection(port='4001',clientId=100)
    con = Connection.create(port=7497, clientId=1006)
    con.registerAll(watcher)
    showBidAskOnly = True  # set False to see the raw messages

    if showBidAskOnly:
        con.unregister(watcher, message.tickSize, message.tickPrice,
                       message.tickString, message.tickOptionComputation)
        con.register(my_BidAsk, message.tickPrice)
    con.connect() 
sleep(1)
tickId = 1 
# Note: Option quotes will give an error if they aren't shown in TWS
#contractTuple = ('GOOGL', 'STK', 'SMART', 'ISLAND','USD')
#contractTuple = ('QQQQ', 'OPT', 'SMART', 'USD', '20170921', 47.0, 'CALL')
#contractTuple = ('ES', 'FUT', 'GLOBEX', 'USD', '200709', 0.0, '')
#contractTuple = ('ES', 'FOP', 'GLOBEX', 'USD', '20070920', 1460.0, 'CALL')
contractTuple = ('CAD', 'CASH', 'IDEALPRO','IDEALPRO','jpy')
stkContract = makeStkContract(contractTuple)
print ('* * * * REQUESTING MARKET DATA * * * *')
con.reqMktData(tickId, stkContract, '', False)
print ('global variables:',bid, ask,last)
sleep(1)
print ('* * * * CANCELING MARKET DATA * * * *')
con.cancelMktData(tickId)

sleep(1)
con.disconnect()
#sleep(1)

the following is result

    Server Version: 76
TWS Time at connection:20170319 05:45:12 EST
<managedAccounts accountsList=DU647841>
<nextValidId orderId=1>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfarm.us>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:cafarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:hfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:cashfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfuture>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:jfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:eufarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfarm>
<error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usopt>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ushmds.us>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ilhmds>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:euhmds>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:cashhmds>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:fundfarm>
<error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ushmds> 
Contract Values:CAD,CASH,IDEALPRO,IDEALPRO,jpy:
* * * * REQUESTING MARKET DATA * * * *
('global variables:', None, None, None)
last close: 85.07
* * * * CANCELING MARKET DATA * * * *

the difficulties i have now are that first i want to eliminate all those unrelated msgs, second, I can't seem to get global variables (bid, ask,last) working.

Any suggestions? thanks in advance


Solution

  • If you don't want all the messages, don't print them.

    You have to make sure the order you do things works asynchronously. Here you make a request and immediately print before it has time to get back from the server. Then you sleep for 1 second and hope it's done.

    con.reqMktData(tickId, stkContract, '', False)
    print ('global variables:',bid, ask,last)
    sleep(1)
    print ('* * * * CANCELING MARKET DATA * * * *')
    con.cancelMktData(tickId)
    

    Here is a way to do everything in order.

    from ib.ext.Contract import Contract
    from ib.opt import ibConnection, message
    
    def nextValidId_handler(msg):
        global id;
        id = msg.orderId
        # start now when you know it's connected
        makeRequest()
    
    def error_handler(msg):
        # only print interesting errors
        if msg.id > 0:
            print(msg)
    
    # show Bid and Ask quotes
    def my_BidAsk(msg):
        global bid,ask    
    
        if msg.field == 1:
            print ('bid: %s' % ( msg.price)) 
            bid=msg.price
        elif msg.field == 2:
            print ('ask: %s' % (msg.price)) 
            ask=msg.price
        # there is no last price in forex, maybe just the last close.
    
        if (bid is not None) and (ask is not None):
            midPoint = (bid + ask)/2
            print ('global variables:',bid, ask, midPoint)
            # disconnect after getting all the data we want
            disconnect()
    
    def makeStkContract(contractTuple):
        newContract = Contract() 
    
        newContract.m_symbol = contractTuple[0]
        newContract.m_secType = contractTuple[1]
        newContract.m_exchange = contractTuple[2]
        newContract.m_primaryExch=contractTuple[3]
        newContract.m_currency = contractTuple[4]
    
        print ('Contract Values:%s,%s,%s,%s,%s:' % contractTuple)
        return newContract
    
    def makeRequest():
        global tickId
        tickId = 1
        contractTuple = ('CAD', 'CASH', 'IDEALPRO','IDEALPRO','jpy')
        stkContract = makeStkContract(contractTuple)
        print ('* * * * REQUESTING MARKET DATA * * * *')
        con.reqMktData(tickId, stkContract, '', False)
    
    def disconnect():
        print ('* * * * CANCELING MARKET DATA * * * *')
        con.cancelMktData(tickId)
        con.disconnect()
    
    bid = None
    ask = None
    
    if __name__ == '__main__':
        con = ibConnection(port=7497, clientId=1006)
        con.register(error_handler, message.Error)
        con.register(nextValidId_handler, message.nextValidId)
        con.register(my_BidAsk, message.tickPrice)
        con.connect()