Search code examples
pythoninteractive-brokersib-api

How to get real-time steaming data from IBapi for Python?


I am new to IBapi and Python and now just trying to write a program to get the real-time steaming market data from the IBapi continuosly.

When I run the code, the data tick did come in for a while like few second. Then it will stop itself with exception keyboard Interpreted, system exit.

I am not able to figure out what cause the keyboard interpreted, system exist. Did any expert can help point out the issue why it will sudden exist and how to keep it running? Thank you.

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
import threading
import sys
import queue

i = 0

class MyWrapper(EWrapper):

def nextValidId(self, orderId:int):
    print("setting nextValidOrderId: %d", orderId)
   # self.nextValidOrderId = orderId
    # start program here or use threading
    #app.reqContractDetails(4444, contract)

def contractDetails(self, reqId, contractDetails):
    print(reqId, contractDetails.contract)# my version doesnt use summary

def contractDetailsEnd(self, reqId):
    print("ContractDetailsEnd. ", reqId)
    # this is the logical end of your program

def error(self, reqId, errorCode, errorString):
    print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)


def tickPrice(self, tickerid , tickType, price, attrib):
    ##overriden method

    ## For simplicity I'm ignoring these but they could be useful to you...
    ## See the documentation http://interactivebrokers.github.io/tws-api/md_receive.html#gsc.tab=0
    # attrib.canAutoExecute
    # attrib.pastLimit
    global i
    i += 1
    print(i, " Tick type:", tickType, " Price:", price)



def tickSize(self, tickerid, tickType, size):
    ## overriden method
    global i
    i += 1
    print(i, " Tick type:", tickType, " Size:", size)


def tickString(self, tickerid, tickType, value):
    ## overriden method

    ## value is a string, make it a float, and then in the parent class will be resolved to int if size
    global i
    i += 1
    print(i, " Tick type:", tickType, " Value:", value)


def tickGeneric(self, tickerid, tickType, value):
    ## overriden method       
    global i
    i += 1
    print(i, " Tick type:", tickType, " value:", value)

wrapper = MyWrapper()
app = EClient(wrapper)
app.connect("127.0.0.1", 7497, clientId=1)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(), app.twsConnectionTime()))

from ibapi.contract import Contract
contract = Contract()
contract.symbol = "ES"
contract.secType = "FUT"
contract.currency = "USD"
contract.exchange = "GLOBEX"
contract.localSymbol="ESH9"

app.reqMktData(1, contract, "", False, False, [])
print(app.isConnected())
app.run()

The example result like this:

serverVersion:148 connectionTime:b'20190227 17:05:55 CST'
True
setting nextValidOrderId: %d 1
Error. Id:  -1  Code:  2104  Msg:  Market data farm connection is OK:usfarm.nj
Error. Id:  -1  Code:  2104  Msg:  Market data farm connection is OK:hfarm
Error. Id:  -1  Code:  2104  Msg:  Market data farm connection is OK:usfuture
Error. Id:  -1  Code:  2104  Msg:  Market data farm connection is OK:usfarm
Error. Id:  -1  Code:  2106  Msg:  HMDS data farm connection is OK:hkhmds
Error. Id:  -1  Code:  2106  Msg:  HMDS data farm connection is OK:ushmds
1  Tick type: 45  Value: 1551258356
2  Tick type: 4  Price: 2782.5
3  Tick type: 5  Size: 1
4  Tick type: 5  Size: 1
5  Tick type: 8  Size: 75821
6  Tick type: 6  Price: 2793.25
7  Tick type: 7  Price: 2780.5
8  Tick type: 9  Price: 2791.5
9  Tick type: 14  Price: 2788.0
10  Tick type: 1  Price: 2782.25
11  Tick type: 0  Size: 41
12  Tick type: 2  Price: 2782.5
13  Tick type: 3  Size: 46
14  Tick type: 0  Size: 41
15  Tick type: 3  Size: 46
16  Tick type: 0  Size: 42
17  Tick type: 3  Size: 48
18  Tick type: 0  Size: 29
19  Tick type: 3  Size: 64
20  Tick type: 0  Size: 37
21  Tick type: 3  Size: 56
22  Tick type: 0  Size: 39
23  Tick type: 3  Size: 54
24  Tick type: 45  Value: 1551258361
25  Tick type: 5  Size: 44
26  Tick type: 8  Size: 75865
27  Tick type: 1  Price: 2782.5
28  Tick type: 0  Size: 31
29  Tick type: 2  Price: 2782.75
30  Tick type: 3  Size: 91
31  Tick type: 0  Size: 31
32  Tick type: 3  Size: 91
33  Tick type: 0  Size: 12
34  Tick type: 3  Size: 79
35  Tick type: 45  Value: 1551258362
36  Tick type: 5  Size: 1
37  Tick type: 8  Size: 75866
38  Tick type: 45  Value: 1551258363
39  Tick type: 4  Price: 2782.75
40  Tick type: 5  Size: 1
41  Tick type: 8  Size: 75867
42  Tick type: 0  Size: 11
43  Tick type: 3  Size: 78
44  Tick type: 0  Size: 12
45  Tick type: 3  Size: 79
46  Tick type: 45  Value: 1551258365
47  Tick type: 4  Price: 2782.5
48  Tick type: 5  Size: 1
49  Tick type: 8  Size: 75868
50  Tick type: 0  Size: 13
51  Tick type: 45  Value: 1551258366
52  Tick type: 4  Price: 2782.75
53  Tick type: 5  Size: 5
54  Tick type: 5  Size: 5
55  Tick type: 8  Size: 75873
56  Tick type: 0  Size: 30
57  Tick type: 3  Size: 65
58  Tick type: 45  Value: 1551258367
59  Tick type: 4  Price: 2782.5
60  Tick type: 5  Size: 4
61  Tick type: 5  Size: 4
62  Tick type: 8  Size: 75877
63  Tick type: 0  Size: 13
64  Tick type: 3  Size: 63
65  Tick type: 0  Size: 9
66  Tick type: 3  Size: 70
67  Tick type: 3  Size: 66
68  Tick type: 45  Value: 1551258370
69  Tick type: 4  Price: 2782.75
70  Tick type: 5  Size: 1
71  Tick type: 5  Size: 1
72  Tick type: 8  Size: 75878
73  Tick type: 0  Size: 17
74  Tick type: 3  Size: 65
75  Tick type: 4  Price: 2782.5
76  Tick type: 5  Size: 2
77  Tick type: 5  Size: 2
78  Tick type: 8  Size: 75880
79  Tick type: 0  Size: 4
80  Tick type: 3  Size: 68
81  Tick type: 5  Size: 3
82  Tick type: 8  Size: 75883
83  Tick type: 0  Size: 5
84  Tick type: 3  Size: 72
85  Tick type: 45  Value: 1551258371
86  Tick type: 5  Size: 1
87  Tick type: 8  Size: 75884
88  Tick type: 0  Size: 12
89  Tick type: 3  Size: 67
90  Tick type: 1  Price: 2782.25
91  Tick type: 0  Size: 64
92  Tick type: 2  Price: 2782.5
93  Tick type: 3  Size: 2
94  Tick type: 0  Size: 64
95  Tick type: 3  Size: 2
96  Tick type: 45  Value: 1551258373
97  Tick type: 4  Price: 2782.25
98  Tick type: 5  Size: 5
99  Tick type: 5  Size: 5
100  Tick type: 8  Size: 75897
101  Tick type: 0  Size: 52
102  Tick type: 3  Size: 28
103  Tick type: 0  Size: 48
104  Tick type: 3  Size: 45
105  Tick type: 45  Value: 1551258376
106  Tick type: 5  Size: 12
107  Tick type: 8  Size: 75909
108  Tick type: 0  Size: 29
109  Tick type: 3  Size: 41
An exception has occurred, use %tb to see the full traceback.

SystemExit

Full Traceback as follow:

Traceback (most recent call last):

  File "<ipython-input-9-9e6a0c5dfe6c>", line 1, in <module>
    runfile('C:/readIB_test.py', wdir='C:/Desktop')

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 668, in runfile
    execfile(filename, namespace)

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/readIB_test.py", line 86, in <module>
    app.run()

  File "C:\ProgramData\Anaconda3\lib\site-packages\ibapi-9.73.7-py3.7.egg\ibapi\client.py", line 228, in run
    self.keyboardInterruptHard()

  File "C:\ProgramData\Anaconda3\lib\site-packages\ibapi-9.73.7-py3.7.egg\ibapi\client.py", line 215, in keyboardInterruptHard
    raise SystemExit()

SystemExit

Solution

  • Finally I found the issue was caused by the IBapi itself. The run() inside the client.py has a timer set to 20 inside. Not sure why they release the API like this as refer to the doc, the loop should be run infinite. I just comment out the timeout lines then my code work without any more stop.

    Org client.py:

    def run(self):
            """This is the function that has the message loop."""
            timeStart = time.time()
            timeOut = 20
    
            try:
                while not self.done and (self.isConnected()
                            or not self.msg_queue.empty()):
                    if time.time() - timeStart > timeOut: # stop application after timeout
                        self.keyboardInterrupt()
                        self.keyboardInterruptHard()
    

    I have comment out the timeout lines:

        def run(self):
            """This is the function that has the message loop."""
            #timeStart = time.time()
            #timeOut = 20
    
            try:
                while not self.done and (self.isConnected()
                            or not self.msg_queue.empty()):
                    #if time.time() - timeStart > timeOut: # stop application after timeout
                        #self.keyboardInterrupt()
                        #self.keyboardInterruptHard()