ibapi-stable 10.37.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. ibapi/__init__.py +16 -0
  2. ibapi/account_summary_tags.py +70 -0
  3. ibapi/client.py +4891 -0
  4. ibapi/client_utils.py +412 -0
  5. ibapi/comm.py +100 -0
  6. ibapi/commission_and_fees_report.py +31 -0
  7. ibapi/common.py +315 -0
  8. ibapi/connection.py +126 -0
  9. ibapi/const.py +12 -0
  10. ibapi/contract.py +265 -0
  11. ibapi/decoder.py +1711 -0
  12. ibapi/decoder_utils.py +420 -0
  13. ibapi/enum_implem.py +20 -0
  14. ibapi/errors.py +43 -0
  15. ibapi/execution.py +95 -0
  16. ibapi/ineligibility_reason.py +18 -0
  17. ibapi/message.py +186 -0
  18. ibapi/news.py +13 -0
  19. ibapi/object_implem.py +12 -0
  20. ibapi/order.py +263 -0
  21. ibapi/order_cancel.py +21 -0
  22. ibapi/order_condition.py +289 -0
  23. ibapi/order_state.py +117 -0
  24. ibapi/orderdecoder.py +539 -0
  25. ibapi/protobuf/CancelOrderRequest_pb2.py +38 -0
  26. ibapi/protobuf/ComboLeg_pb2.py +37 -0
  27. ibapi/protobuf/Contract_pb2.py +39 -0
  28. ibapi/protobuf/DeltaNeutralContract_pb2.py +37 -0
  29. ibapi/protobuf/ErrorMessage_pb2.py +37 -0
  30. ibapi/protobuf/ExecutionDetailsEnd_pb2.py +37 -0
  31. ibapi/protobuf/ExecutionDetails_pb2.py +39 -0
  32. ibapi/protobuf/ExecutionFilter_pb2.py +37 -0
  33. ibapi/protobuf/ExecutionRequest_pb2.py +38 -0
  34. ibapi/protobuf/Execution_pb2.py +37 -0
  35. ibapi/protobuf/GlobalCancelRequest_pb2.py +38 -0
  36. ibapi/protobuf/OpenOrder_pb2.py +40 -0
  37. ibapi/protobuf/OpenOrdersEnd_pb2.py +37 -0
  38. ibapi/protobuf/OrderAllocation_pb2.py +37 -0
  39. ibapi/protobuf/OrderCancel_pb2.py +37 -0
  40. ibapi/protobuf/OrderCondition_pb2.py +37 -0
  41. ibapi/protobuf/OrderState_pb2.py +38 -0
  42. ibapi/protobuf/OrderStatus_pb2.py +37 -0
  43. ibapi/protobuf/Order_pb2.py +51 -0
  44. ibapi/protobuf/PlaceOrderRequest_pb2.py +39 -0
  45. ibapi/protobuf/SoftDollarTier_pb2.py +37 -0
  46. ibapi/reader.py +49 -0
  47. ibapi/scanner.py +77 -0
  48. ibapi/server_versions.py +159 -0
  49. ibapi/softdollartier.py +16 -0
  50. ibapi/tag_value.py +22 -0
  51. ibapi/ticktype.py +117 -0
  52. ibapi/utils.py +233 -0
  53. ibapi/wrapper.py +885 -0
  54. ibapi_stable-10.37.2.dist-info/METADATA +136 -0
  55. ibapi_stable-10.37.2.dist-info/RECORD +57 -0
  56. ibapi_stable-10.37.2.dist-info/WHEEL +5 -0
  57. ibapi_stable-10.37.2.dist-info/top_level.txt +1 -0
ibapi/common.py ADDED
@@ -0,0 +1,315 @@
1
+ """
2
+ Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
3
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
4
+ """
5
+
6
+
7
+ from ibapi.const import UNSET_INTEGER, UNSET_DECIMAL
8
+ from ibapi.enum_implem import Enum
9
+ from ibapi.object_implem import Object
10
+ from ibapi.utils import floatMaxString, decimalMaxString, intMaxString
11
+ from ibapi.message import OUT
12
+ from ibapi.server_versions import (
13
+ MIN_SERVER_VER_PROTOBUF,
14
+ MIN_SERVER_VER_PROTOBUF_PLACE_ORDER
15
+ )
16
+
17
+ TickerId = int
18
+ OrderId = int
19
+ TagValueList = list
20
+
21
+ FaDataType = int
22
+ FaDataTypeEnum = Enum("N/A", "GROUPS", "N/A", "ALIASES")
23
+
24
+ MarketDataType = int
25
+ MarketDataTypeEnum = Enum("N/A", "REALTIME", "FROZEN", "DELAYED", "DELAYED_FROZEN")
26
+
27
+ Liquidities = int
28
+ LiquiditiesEnum = Enum("None", "Added", "Remove", "RoudedOut")
29
+
30
+ SetOfString = set
31
+ SetOfFloat = set
32
+ ListOfOrder = list
33
+ ListOfFamilyCode = list
34
+ ListOfContractDescription = list
35
+ ListOfDepthExchanges = list
36
+ ListOfNewsProviders = list
37
+ SmartComponentMap = dict
38
+ HistogramDataList = list
39
+ ListOfPriceIncrements = list
40
+ ListOfHistoricalTick = list
41
+ ListOfHistoricalTickBidAsk = list
42
+ ListOfHistoricalTickLast = list
43
+ ListOfHistoricalSessions = list
44
+
45
+ PROTOBUF_MSG_ID = 200
46
+ PROTOBUF_MSG_IDS = {
47
+ OUT.REQ_EXECUTIONS : MIN_SERVER_VER_PROTOBUF,
48
+ OUT.PLACE_ORDER : MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
49
+ OUT.CANCEL_ORDER : MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
50
+ OUT.REQ_GLOBAL_CANCEL : MIN_SERVER_VER_PROTOBUF_PLACE_ORDER
51
+ }
52
+
53
+ class BarData(Object):
54
+ def __init__(self):
55
+ self.date = ""
56
+ self.open = 0.0
57
+ self.high = 0.0
58
+ self.low = 0.0
59
+ self.close = 0.0
60
+ self.volume = UNSET_DECIMAL
61
+ self.wap = UNSET_DECIMAL
62
+ self.barCount = 0
63
+
64
+ def __str__(self):
65
+ return (
66
+ f"Date: {self.date}, "
67
+ f"Open: {floatMaxString(self.open)}, "
68
+ f"High: {floatMaxString(self.high)}, "
69
+ f"Low: {floatMaxString(self.low)}, "
70
+ f"Close: {floatMaxString(self.close)}, "
71
+ f"Volume: {decimalMaxString(self.volume)}, "
72
+ f"WAP: {decimalMaxString(self.wap)}, "
73
+ f"BarCount: {intMaxString(self.barCount)}"
74
+ )
75
+
76
+
77
+ class RealTimeBar(Object):
78
+ def __init__(
79
+ self,
80
+ time=0,
81
+ endTime=-1,
82
+ open_=0.0,
83
+ high=0.0,
84
+ low=0.0,
85
+ close=0.0,
86
+ volume=UNSET_DECIMAL,
87
+ wap=UNSET_DECIMAL,
88
+ count=0,
89
+ ):
90
+ self.time = time
91
+ self.endTime = endTime
92
+ self.open_ = open_
93
+ self.high = high
94
+ self.low = low
95
+ self.close = close
96
+ self.volume = volume
97
+ self.wap = wap
98
+ self.count = count
99
+
100
+ def __str__(self):
101
+ return (
102
+ "Time: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, WAP: %s, Count: %s"
103
+ % (
104
+ intMaxString(self.time),
105
+ floatMaxString(self.open_),
106
+ floatMaxString(self.high),
107
+ floatMaxString(self.low),
108
+ floatMaxString(self.close),
109
+ decimalMaxString(self.volume),
110
+ decimalMaxString(self.wap),
111
+ intMaxString(self.count),
112
+ )
113
+ )
114
+
115
+
116
+ class HistogramData(Object):
117
+ def __init__(self):
118
+ self.price = 0.0
119
+ self.size = UNSET_DECIMAL
120
+
121
+ def __str__(self):
122
+ return "Price: %s, Size: %s" % (
123
+ floatMaxString(self.price),
124
+ decimalMaxString(self.size),
125
+ )
126
+
127
+
128
+ class NewsProvider(Object):
129
+ def __init__(self):
130
+ self.code = ""
131
+ self.name = ""
132
+
133
+ def __str__(self):
134
+ return f"Code: {self.code}, Name: {self.name}"
135
+
136
+
137
+ class DepthMktDataDescription(Object):
138
+ def __init__(self):
139
+ self.exchange = ""
140
+ self.secType = ""
141
+ self.listingExch = ""
142
+ self.serviceDataType = ""
143
+ self.aggGroup = UNSET_INTEGER
144
+
145
+ def __str__(self):
146
+ if self.aggGroup != UNSET_INTEGER:
147
+ aggGroup = self.aggGroup
148
+ else:
149
+ aggGroup = ""
150
+ return (
151
+ "Exchange: %s, SecType: %s, ListingExchange: %s, ServiceDataType: %s, AggGroup: %s, "
152
+ % (
153
+ self.exchange,
154
+ self.secType,
155
+ self.listingExch,
156
+ self.serviceDataType,
157
+ intMaxString(aggGroup),
158
+ )
159
+ )
160
+
161
+
162
+ class SmartComponent(Object):
163
+ def __init__(self):
164
+ self.bitNumber = 0
165
+ self.exchange = ""
166
+ self.exchangeLetter = ""
167
+
168
+ def __str__(self):
169
+ return "BitNumber: %d, Exchange: %s, ExchangeLetter: %s" % (
170
+ self.bitNumber,
171
+ self.exchange,
172
+ self.exchangeLetter,
173
+ )
174
+
175
+
176
+ class TickAttrib(Object):
177
+ def __init__(self):
178
+ self.canAutoExecute = False
179
+ self.pastLimit = False
180
+ self.preOpen = False
181
+
182
+ def __str__(self):
183
+ return "CanAutoExecute: %d, PastLimit: %d, PreOpen: %d" % (
184
+ self.canAutoExecute,
185
+ self.pastLimit,
186
+ self.preOpen,
187
+ )
188
+
189
+
190
+ class TickAttribBidAsk(Object):
191
+ def __init__(self):
192
+ self.bidPastLow = False
193
+ self.askPastHigh = False
194
+
195
+ def __str__(self):
196
+ return "BidPastLow: %d, AskPastHigh: %d" % (self.bidPastLow, self.askPastHigh)
197
+
198
+
199
+ class TickAttribLast(Object):
200
+ def __init__(self):
201
+ self.pastLimit = False
202
+ self.unreported = False
203
+
204
+ def __str__(self):
205
+ return "PastLimit: %d, Unreported: %d" % (self.pastLimit, self.unreported)
206
+
207
+
208
+ class FamilyCode(Object):
209
+ def __init__(self):
210
+ self.accountID = ""
211
+ self.familyCodeStr = ""
212
+
213
+ def __str__(self):
214
+ return f"AccountId: {self.accountID}, FamilyCodeStr: {self.familyCodeStr}"
215
+
216
+
217
+ class PriceIncrement(Object):
218
+ def __init__(self):
219
+ self.lowEdge = 0.0
220
+ self.increment = 0.0
221
+
222
+ def __str__(self):
223
+ return "LowEdge: %s, Increment: %s" % (
224
+ floatMaxString(self.lowEdge),
225
+ floatMaxString(self.increment),
226
+ )
227
+
228
+
229
+ class HistoricalTick(Object):
230
+ def __init__(self):
231
+ self.time = 0
232
+ self.price = 0.0
233
+ self.size = UNSET_DECIMAL
234
+
235
+ def __str__(self):
236
+ return "Time: %s, Price: %s, Size: %s" % (
237
+ intMaxString(self.time),
238
+ floatMaxString(self.price),
239
+ decimalMaxString(self.size),
240
+ )
241
+
242
+
243
+ class HistoricalTickBidAsk(Object):
244
+ def __init__(self):
245
+ self.time = 0
246
+ self.tickAttribBidAsk = TickAttribBidAsk()
247
+ self.priceBid = 0.0
248
+ self.priceAsk = 0.0
249
+ self.sizeBid = UNSET_DECIMAL
250
+ self.sizeAsk = UNSET_DECIMAL
251
+
252
+ def __str__(self):
253
+ return (
254
+ f"Time: {intMaxString(self.time)}, "
255
+ f"TickAttriBidAsk: {self.tickAttribBidAsk}, "
256
+ f"PriceBid: {floatMaxString(self.priceBid)}, "
257
+ f"PriceAsk: {floatMaxString(self.priceAsk)}, "
258
+ f"SizeBid: {decimalMaxString(self.sizeBid)}, "
259
+ f"SizeAsk: {decimalMaxString(self.sizeAsk)}"
260
+ )
261
+
262
+
263
+ class HistoricalTickLast(Object):
264
+ def __init__(self):
265
+ self.time = 0
266
+ self.tickAttribLast = TickAttribLast()
267
+ self.price = 0.0
268
+ self.size = UNSET_DECIMAL
269
+ self.exchange = ""
270
+ self.specialConditions = ""
271
+
272
+ def __str__(self):
273
+ return (
274
+ f"Time: {intMaxString(self.time)}, "
275
+ f"TickAttribLast: {self.tickAttribLast}, "
276
+ f"Price: {floatMaxString(self.price)}, "
277
+ f"Size: {decimalMaxString(self.size)}, "
278
+ f"Exchange: {self.exchange}, "
279
+ f"SpecialConditions: {self.specialConditions}"
280
+ )
281
+
282
+
283
+ class HistoricalSession(Object):
284
+ def __init__(self):
285
+ self.startDateTime = ""
286
+ self.endDateTime = ""
287
+ self.refDate = ""
288
+
289
+ def __str__(self):
290
+ return "Start: %s, End: %s, Ref Date: %s" % (
291
+ self.startDateTime,
292
+ self.endDateTime,
293
+ self.refDate,
294
+ )
295
+
296
+
297
+ class WshEventData(Object):
298
+ def __init__(self):
299
+ self.conId = UNSET_INTEGER
300
+ self.filter = ""
301
+ self.fillWatchlist = False
302
+ self.fillPortfolio = False
303
+ self.fillCompetitors = False
304
+ self.startDate = ""
305
+ self.endDate = ""
306
+ self.totalLimit = UNSET_INTEGER
307
+
308
+ def __str__(self):
309
+ return (
310
+ f"WshEventData. ConId: {intMaxString(self.conId)}, "
311
+ f"Filter: {self.filter}, "
312
+ f"Fill Watchlist: {self.fillWatchlist:d}, "
313
+ f"Fill Portfolio: {self.fillPortfolio:d}, "
314
+ f"Fill Competitors: {self.fillCompetitors:d}"
315
+ )
ibapi/connection.py ADDED
@@ -0,0 +1,126 @@
1
+ """
2
+ Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
3
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
4
+ """
5
+
6
+ """
7
+ Just a thin wrapper around a socket.
8
+ It allows us to keep some other info along with it.
9
+ """
10
+
11
+ import socket
12
+ import threading
13
+ import logging
14
+ import sys
15
+ from ibapi.errors import FAIL_CREATE_SOCK
16
+ from ibapi.errors import CONNECT_FAIL
17
+ from ibapi.const import NO_VALID_ID
18
+ from ibapi.utils import currentTimeMillis
19
+
20
+ # TODO: support SSL !!
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class Connection:
26
+ def __init__(self, host, port):
27
+ self.host = host
28
+ self.port = port
29
+ self.socket = None
30
+ self.wrapper = None
31
+ self.lock = threading.Lock()
32
+
33
+ def connect(self):
34
+ try:
35
+ self.socket = socket.socket()
36
+ # TODO: list the exceptions you want to catch
37
+ except socket.error:
38
+ if self.wrapper:
39
+ self.wrapper.error(
40
+ NO_VALID_ID, currentTimeMillis(), FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()
41
+ )
42
+
43
+ try:
44
+ self.socket.connect((self.host, self.port))
45
+ except socket.error:
46
+ if self.wrapper:
47
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), CONNECT_FAIL.code(), CONNECT_FAIL.msg())
48
+
49
+ self.socket.settimeout(1) # non-blocking
50
+
51
+ def disconnect(self):
52
+ self.lock.acquire()
53
+ try:
54
+ if self.socket is not None:
55
+ logger.debug("disconnecting")
56
+ self.socket.close()
57
+ self.socket = None
58
+ logger.debug("disconnected")
59
+ if self.wrapper:
60
+ self.wrapper.connectionClosed()
61
+ finally:
62
+ self.lock.release()
63
+
64
+ def isConnected(self):
65
+ return self.socket is not None
66
+
67
+ def sendMsg(self, msg):
68
+ logger.debug("acquiring lock")
69
+ self.lock.acquire()
70
+ logger.debug("acquired lock")
71
+ if not self.isConnected():
72
+ logger.debug("sendMsg attempted while not connected, releasing lock")
73
+ self.lock.release()
74
+ return 0
75
+ try:
76
+ nSent = self.socket.send(msg)
77
+ except socket.error:
78
+ logger.debug("exception from sendMsg %s", sys.exc_info())
79
+ raise
80
+ finally:
81
+ logger.debug("releasing lock")
82
+ self.lock.release()
83
+ logger.debug("release lock")
84
+
85
+ logger.debug("sendMsg: sent: %d", nSent)
86
+
87
+ return nSent
88
+
89
+ def recvMsg(self):
90
+ if not self.isConnected():
91
+ logger.debug("recvMsg attempted while not connected, releasing lock")
92
+ return b""
93
+ try:
94
+ buf = self._recvAllMsg()
95
+ # receiving 0 bytes outside a timeout means the connection is either
96
+ # closed or broken
97
+ if len(buf) == 0:
98
+ logger.debug("socket either closed or broken, disconnecting")
99
+ self.disconnect()
100
+ except socket.timeout:
101
+ logger.debug("socket timeout from recvMsg %s", sys.exc_info())
102
+ buf = b""
103
+ except socket.error:
104
+ logger.debug("socket broken, disconnecting")
105
+ self.disconnect()
106
+ buf = b""
107
+ except OSError:
108
+ # Thrown if the socket was closed (ex: disconnected at end of script)
109
+ # while waiting for self.socket.recv() to timeout.
110
+ logger.debug("Socket is broken or closed.")
111
+
112
+ return buf
113
+
114
+ def _recvAllMsg(self):
115
+ cont = True
116
+ allbuf = b""
117
+
118
+ while cont and self.isConnected():
119
+ buf = self.socket.recv(4096)
120
+ allbuf += buf
121
+ logger.debug("len %d raw:%s|", len(buf), buf)
122
+
123
+ if len(buf) < 4096:
124
+ cont = False
125
+
126
+ return allbuf
ibapi/const.py ADDED
@@ -0,0 +1,12 @@
1
+ import math
2
+ import sys
3
+ from _decimal import Decimal
4
+
5
+ NO_VALID_ID = -1
6
+ MAX_MSG_LEN = 0xFFFFFF # 16Mb - 1byte
7
+ UNSET_INTEGER = 2**31 - 1
8
+ UNSET_DOUBLE = float(sys.float_info.max)
9
+ UNSET_LONG = 2**63 - 1
10
+ UNSET_DECIMAL = Decimal(2**127 - 1)
11
+ DOUBLE_INFINITY = math.inf
12
+ INFINITY_STR = "Infinity"