from .util import UNSET_DOUBLE, UNSET_INTEGER, dataclassAsTuple, getLoop, run
-[docs]class Client:
+
+
[docs]
+
class Client:
"""
Replacement for ``ibapi.client.EClient`` that uses asyncio.
@@ -159,7 +169,7 @@
Source code for ib_insync.client
RequestsInterval = 1
MinClientVersion = 157
- MaxClientVersion = 177
+ MaxClientVersion = 178
(DISCONNECTED, CONNECTING, CONNECTED) = range(3)
@@ -189,7 +199,9 @@ Source code for ib_insync.client
self.connectOptions = b''
self.reset()
-[docs] def reset(self):
+
+
[docs]
+
def reset(self):
self.connState = Client.DISCONNECTED
self._apiReady = False
self._serverVersion = 0
@@ -204,21 +216,36 @@
Source code for ib_insync.client
self._msgQ: Deque[str] = deque()
self._timeQ: Deque[float] = deque()
-
[docs] def serverVersion(self) -> int:
+
+
+
[docs]
+
def serverVersion(self) -> int:
return self._serverVersion
-
[docs] def run(self):
+
+
+
[docs]
+
def run(self):
loop = getLoop()
loop.run_forever()
-
[docs] def isConnected(self):
+
+
+
[docs]
+
def isConnected(self):
return self.connState == Client.CONNECTED
-
[docs] def isReady(self) -> bool:
+
+
+
[docs]
+
def isReady(self) -> bool:
"""Is the API connection up and running?"""
return self._apiReady
-
[docs] def connectionStats(self) -> ConnectionStats:
+
+
+
[docs]
+
def connectionStats(self) -> ConnectionStats:
"""Get statistics about the connection."""
if not self.isReady():
raise ConnectionError('Not connected')
@@ -228,7 +255,10 @@
Source code for ib_insync.client
self._numBytesRecv, self.conn.numBytesSent,
self._numMsgRecv, self.conn.numMsgSent)
-
[docs] def getReqId(self) -> int:
+
+
+
[docs]
+
def getReqId(self) -> int:
"""Get new request ID."""
if not self.isReady():
raise ConnectionError('Not connected')
@@ -236,17 +266,26 @@
Source code for ib_insync.client
self._reqIdSeq += 1
return newId
-
[docs] def updateReqId(self, minReqId):
+
+
+
[docs]
+
def updateReqId(self, minReqId):
"""Update the next reqId to be at least ``minReqId``."""
self._reqIdSeq = max(self._reqIdSeq, minReqId)
-
[docs] def getAccounts(self) -> List[str]:
+
+
+
[docs]
+
def getAccounts(self) -> List[str]:
"""Get the list of account names that are under management."""
if not self.isReady():
raise ConnectionError('Not connected')
return self._accounts
-
[docs] def setConnectOptions(self, connectOptions: str):
+
+
+
[docs]
+
def setConnectOptions(self, connectOptions: str):
"""
Set additional connect options.
@@ -256,7 +295,10 @@
Source code for ib_insync.client
"""
self.connectOptions = connectOptions.encode()
-
[docs] def connect(
+
+
+
[docs]
+
def connect(
self, host: str, port: int, clientId: int,
timeout: Optional[float] = 2.0):
"""
@@ -273,7 +315,10 @@
Source code for ib_insync.client
"""
run(self.connectAsync(host, port, clientId, timeout))
-
[docs] async def connectAsync(self, host, port, clientId, timeout=2.0):
+
+
+
[docs]
+
async def connectAsync(self, host, port, clientId, timeout=2.0):
try:
self._logger.info(
f'Connecting to {host}:{port} with clientId {clientId}...')
@@ -299,14 +344,20 @@
Source code for ib_insync.client
self._logger.error('Make sure API port on TWS/IBG is open')
raise
-
[docs] def disconnect(self):
+
+
+
[docs]
+
def disconnect(self):
"""Disconnect from IB connection."""
self._logger.info('Disconnecting')
self.connState = Client.DISCONNECTED
self.conn.disconnect()
self.reset()
-
[docs] def send(self, *fields, makeEmpty=True):
+
+
+
[docs]
+
def send(self, *fields, makeEmpty=True):
"""Serialize and send the given fields using the IB socket protocol."""
if not self.isConnected():
raise ConnectionError('Not connected')
@@ -342,7 +393,10 @@
Source code for ib_insync.client
msg.write('\0')
self.sendMsg(msg.getvalue())
-
[docs] def sendMsg(self, msg: str):
+
+
+
[docs]
+
def sendMsg(self, msg: str):
loop = getLoop()
t = loop.time()
times = self._timeQ
@@ -371,6 +425,7 @@
Source code for ib_insync.client
self.throttleEnd.emit()
self._logger.debug('Stopped to throttle requests')
+
def _prefix(self, msg):
# prefix a message with its length
return struct.pack('>I', len(msg)) + msg
@@ -457,7 +512,9 @@
Source code for ib_insync.client
# client request methods
# the message type id is sent first, often followed by a version number
-[docs] def reqMktData(
+
+
[docs]
+
def reqMktData(
self, reqId, contract, genericTickList, snapshot,
regulatorySnapshot, mktDataOptions):
fields = [1, 11, reqId, contract]
@@ -478,10 +535,16 @@
Source code for ib_insync.client
genericTickList, snapshot, regulatorySnapshot, mktDataOptions]
self.send(*fields)
-
[docs] def cancelMktData(self, reqId):
+
+
+
[docs]
+
def cancelMktData(self, reqId):
self.send(2, 2, reqId)
-
[docs] def placeOrder(self, orderId, contract, order):
+
+
+
[docs]
+
def placeOrder(self, orderId, contract, order):
version = self.serverVersion()
fields = [
3, orderId,
@@ -695,19 +758,31 @@
Source code for ib_insync.client
-
[docs] def cancelOrder(self, orderId, manualCancelOrderTime=''):
+
+
+
[docs]
+
def cancelOrder(self, orderId, manualCancelOrderTime=''):
fields = [4, 1, orderId]
if self.serverVersion() >= 169:
fields += [manualCancelOrderTime]
self.send(*fields)
-
[docs] def reqOpenOrders(self):
+
+
+
[docs]
+
def reqOpenOrders(self):
self.send(5, 1)
-
[docs] def reqAccountUpdates(self, subscribe, acctCode):
+
+
+
[docs]
+
def reqAccountUpdates(self, subscribe, acctCode):
self.send(6, 2, subscribe, acctCode)
-
[docs] def reqExecutions(self, reqId, execFilter):
+
+
+
[docs]
+
def reqExecutions(self, reqId, execFilter):
self.send(
7, 3, reqId,
execFilter.clientId,
@@ -718,10 +793,16 @@
Source code for ib_insync.client
execFilter.exchange,
execFilter.side)
-
[docs] def reqIds(self, numIds):
+
+
+
[docs]
+
def reqIds(self, numIds):
self.send(8, 1, numIds)
-
[docs] def reqContractDetails(self, reqId, contract):
+
+
+
[docs]
+
def reqContractDetails(self, reqId, contract):
fields = [
9, 8, reqId,
contract,
@@ -732,7 +813,10 @@
Source code for ib_insync.client
fields += [contract.issuerId]
self.send(*fields)
-
[docs] def reqMktDepth(
+
+
+
[docs]
+
def reqMktDepth(
self, reqId, contract, numRows, isSmartDepth, mktDepthOptions):
self.send(
10, 5, reqId,
@@ -752,34 +836,64 @@
Source code for ib_insync.client
isSmartDepth,
mktDepthOptions)
-
[docs] def cancelMktDepth(self, reqId, isSmartDepth):
+
+
+
[docs]
+
def cancelMktDepth(self, reqId, isSmartDepth):
self.send(11, 1, reqId, isSmartDepth)
-
[docs] def reqNewsBulletins(self, allMsgs):
+
+
+
[docs]
+
def reqNewsBulletins(self, allMsgs):
self.send(12, 1, allMsgs)
-
[docs] def cancelNewsBulletins(self):
+
+
+
[docs]
+
def cancelNewsBulletins(self):
self.send(13, 1)
-
[docs] def setServerLogLevel(self, logLevel):
+
+
+
[docs]
+
def setServerLogLevel(self, logLevel):
self.send(14, 1, logLevel)
-
[docs] def reqAutoOpenOrders(self, bAutoBind):
+
+
+
[docs]
+
def reqAutoOpenOrders(self, bAutoBind):
self.send(15, 1, bAutoBind)
-
[docs] def reqAllOpenOrders(self):
+
+
+
[docs]
+
def reqAllOpenOrders(self):
self.send(16, 1)
-
[docs] def reqManagedAccts(self):
+
+
+
[docs]
+
def reqManagedAccts(self):
self.send(17, 1)
-
[docs] def requestFA(self, faData):
+
+
+
[docs]
+
def requestFA(self, faData):
self.send(18, 1, faData)
-
[docs] def replaceFA(self, reqId, faData, cxml):
+
+
+
[docs]
+
def replaceFA(self, reqId, faData, cxml):
self.send(19, 1, faData, cxml, reqId)
-
[docs] def reqHistoricalData(
+
+
+
[docs]
+
def reqHistoricalData(
self, reqId, contract, endDateTime, durationStr, barSizeSetting,
whatToShow, useRTH, formatDate, keepUpToDate, chartOptions):
fields = [
@@ -796,7 +910,10 @@
Source code for ib_insync.client
fields += [keepUpToDate, chartOptions]
self.send(*fields)
-
[docs] def exerciseOptions(
+
+
+
[docs]
+
def exerciseOptions(
self, reqId, contract, exerciseAction,
exerciseQuantity, account, override):
self.send(
@@ -814,7 +931,10 @@
Source code for ib_insync.client
contract.tradingClass,
exerciseAction, exerciseQuantity, account, override)
-
[docs] def reqScannerSubscription(
+
+
+
[docs]
+
def reqScannerSubscription(
self, reqId, subscription, scannerSubscriptionOptions,
scannerSubscriptionFilterOptions):
sub = subscription
@@ -844,29 +964,50 @@
Source code for ib_insync.client
scannerSubscriptionFilterOptions,
scannerSubscriptionOptions)
-
[docs] def cancelScannerSubscription(self, reqId):
+
+
+
[docs]
+
def cancelScannerSubscription(self, reqId):
self.send(23, 1, reqId)
-
[docs] def reqScannerParameters(self):
+
+
+
[docs]
+
def reqScannerParameters(self):
self.send(24, 1)
-
[docs] def cancelHistoricalData(self, reqId):
+
+
+
[docs]
+
def cancelHistoricalData(self, reqId):
self.send(25, 1, reqId)
-
[docs] def reqCurrentTime(self):
+
+
+
[docs]
+
def reqCurrentTime(self):
self.send(49, 1)
-
[docs] def reqRealTimeBars(
+
+
+
[docs]
+
def reqRealTimeBars(
self, reqId, contract, barSize, whatToShow,
useRTH, realTimeBarsOptions):
self.send(
50, 3, reqId, contract, barSize, whatToShow,
useRTH, realTimeBarsOptions)
-
[docs] def cancelRealTimeBars(self, reqId):
+
+
+
[docs]
+
def cancelRealTimeBars(self, reqId):
self.send(51, 1, reqId)
-
[docs] def reqFundamentalData(
+
+
+
[docs]
+
def reqFundamentalData(
self, reqId, contract, reportType, fundamentalDataOptions):
options = fundamentalDataOptions or []
self.send(
@@ -880,153 +1021,282 @@
Source code for ib_insync.client
contract.localSymbol,
reportType, len(options), options)
-
[docs] def cancelFundamentalData(self, reqId):
+
+
+
[docs]
+
def cancelFundamentalData(self, reqId):
self.send(53, 1, reqId)
-
[docs] def calculateImpliedVolatility(
+
+
+
[docs]
+
def calculateImpliedVolatility(
self, reqId, contract, optionPrice, underPrice, implVolOptions):
self.send(
54, 3, reqId, contract, optionPrice, underPrice,
len(implVolOptions), implVolOptions)
-
[docs] def calculateOptionPrice(
+
+
+
[docs]
+
def calculateOptionPrice(
self, reqId, contract, volatility, underPrice, optPrcOptions):
self.send(
55, 3, reqId, contract, volatility, underPrice,
len(optPrcOptions), optPrcOptions)
-
[docs] def cancelCalculateImpliedVolatility(self, reqId):
+
+
+
[docs]
+
def cancelCalculateImpliedVolatility(self, reqId):
self.send(56, 1, reqId)
-
[docs] def cancelCalculateOptionPrice(self, reqId):
+
+
+
[docs]
+
def cancelCalculateOptionPrice(self, reqId):
self.send(57, 1, reqId)
-
[docs] def reqGlobalCancel(self):
+
+
+
[docs]
+
def reqGlobalCancel(self):
self.send(58, 1)
-
[docs] def reqMarketDataType(self, marketDataType):
+
+
+
[docs]
+
def reqMarketDataType(self, marketDataType):
self.send(59, 1, marketDataType)
-
[docs] def reqPositions(self):
+
+
+
[docs]
+
def reqPositions(self):
self.send(61, 1)
-
[docs] def reqAccountSummary(self, reqId, groupName, tags):
+
+
+
[docs]
+
def reqAccountSummary(self, reqId, groupName, tags):
self.send(62, 1, reqId, groupName, tags)
-
[docs] def cancelAccountSummary(self, reqId):
+
+
+
[docs]
+
def cancelAccountSummary(self, reqId):
self.send(63, 1, reqId)
-
[docs] def cancelPositions(self):
+
+
+
[docs]
+
def cancelPositions(self):
self.send(64, 1)
-
[docs] def verifyRequest(self, apiName, apiVersion):
+
+
+
[docs]
+
def verifyRequest(self, apiName, apiVersion):
self.send(65, 1, apiName, apiVersion)
-
[docs] def verifyMessage(self, apiData):
+
+
+
[docs]
+
def verifyMessage(self, apiData):
self.send(66, 1, apiData)
-
[docs] def queryDisplayGroups(self, reqId):
+
+
+
[docs]
+
def queryDisplayGroups(self, reqId):
self.send(67, 1, reqId)
-
[docs] def subscribeToGroupEvents(self, reqId, groupId):
+
+
+
[docs]
+
def subscribeToGroupEvents(self, reqId, groupId):
self.send(68, 1, reqId, groupId)
-
[docs] def updateDisplayGroup(self, reqId, contractInfo):
+
+
+
[docs]
+
def updateDisplayGroup(self, reqId, contractInfo):
self.send(69, 1, reqId, contractInfo)
-
[docs] def unsubscribeFromGroupEvents(self, reqId):
+
+
+
[docs]
+
def unsubscribeFromGroupEvents(self, reqId):
self.send(70, 1, reqId)
-
[docs] def startApi(self):
+
+
+
[docs]
+
def startApi(self):
self.send(71, 2, self.clientId, self.optCapab)
-
[docs] def verifyAndAuthRequest(self, apiName, apiVersion, opaqueIsvKey):
+
+
+
[docs]
+
def verifyAndAuthRequest(self, apiName, apiVersion, opaqueIsvKey):
self.send(72, 1, apiName, apiVersion, opaqueIsvKey)
-
[docs] def verifyAndAuthMessage(self, apiData, xyzResponse):
+
+
+
[docs]
+
def verifyAndAuthMessage(self, apiData, xyzResponse):
self.send(73, 1, apiData, xyzResponse)
-
[docs] def reqPositionsMulti(self, reqId, account, modelCode):
+
+
+
[docs]
+
def reqPositionsMulti(self, reqId, account, modelCode):
self.send(74, 1, reqId, account, modelCode)
-
[docs] def cancelPositionsMulti(self, reqId):
+
+
+
[docs]
+
def cancelPositionsMulti(self, reqId):
self.send(75, 1, reqId)
-
[docs] def reqAccountUpdatesMulti(self, reqId, account, modelCode, ledgerAndNLV):
+
+
+
[docs]
+
def reqAccountUpdatesMulti(self, reqId, account, modelCode, ledgerAndNLV):
self.send(76, 1, reqId, account, modelCode, ledgerAndNLV)
-
[docs] def cancelAccountUpdatesMulti(self, reqId):
+
+
+
[docs]
+
def cancelAccountUpdatesMulti(self, reqId):
self.send(77, 1, reqId)
-
[docs] def reqSecDefOptParams(
+
+
+
[docs]
+
def reqSecDefOptParams(
self, reqId, underlyingSymbol, futFopExchange,
underlyingSecType, underlyingConId):
self.send(
78, reqId, underlyingSymbol, futFopExchange,
underlyingSecType, underlyingConId)
-
[docs] def reqSoftDollarTiers(self, reqId):
+
+
+
[docs]
+
def reqSoftDollarTiers(self, reqId):
self.send(79, reqId)
-
[docs] def reqFamilyCodes(self):
+
+
+
[docs]
+
def reqFamilyCodes(self):
self.send(80)
-
[docs] def reqMatchingSymbols(self, reqId, pattern):
+
+
+
[docs]
+
def reqMatchingSymbols(self, reqId, pattern):
self.send(81, reqId, pattern)
-
[docs] def reqMktDepthExchanges(self):
+
+
+
[docs]
+
def reqMktDepthExchanges(self):
self.send(82)
-
[docs] def reqSmartComponents(self, reqId, bboExchange):
+
+
+
[docs]
+
def reqSmartComponents(self, reqId, bboExchange):
self.send(83, reqId, bboExchange)
-
[docs] def reqNewsArticle(
+
+
+
[docs]
+
def reqNewsArticle(
self, reqId, providerCode, articleId, newsArticleOptions):
self.send(84, reqId, providerCode, articleId, newsArticleOptions)
-
[docs] def reqNewsProviders(self):
+
+
+
[docs]
+
def reqNewsProviders(self):
self.send(85)
-
[docs] def reqHistoricalNews(
+
+
+
[docs]
+
def reqHistoricalNews(
self, reqId, conId, providerCodes, startDateTime, endDateTime,
totalResults, historicalNewsOptions):
self.send(
86, reqId, conId, providerCodes, startDateTime, endDateTime,
totalResults, historicalNewsOptions)
-
[docs] def reqHeadTimeStamp(
+
+
+
[docs]
+
def reqHeadTimeStamp(
self, reqId, contract, whatToShow, useRTH, formatDate):
self.send(
87, reqId, contract, contract.includeExpired,
useRTH, whatToShow, formatDate)
-
[docs] def reqHistogramData(self, tickerId, contract, useRTH, timePeriod):
+
+
+
[docs]
+
def reqHistogramData(self, tickerId, contract, useRTH, timePeriod):
self.send(
88, tickerId, contract, contract.includeExpired,
useRTH, timePeriod)
-
[docs] def cancelHistogramData(self, tickerId):
+
+
+
[docs]
+
def cancelHistogramData(self, tickerId):
self.send(89, tickerId)
-
[docs] def cancelHeadTimeStamp(self, reqId):
+
+
+
[docs]
+
def cancelHeadTimeStamp(self, reqId):
self.send(90, reqId)
-
[docs] def reqMarketRule(self, marketRuleId):
+
+
+
[docs]
+
def reqMarketRule(self, marketRuleId):
self.send(91, marketRuleId)
-
[docs] def reqPnL(self, reqId, account, modelCode):
+
+
+
[docs]
+
def reqPnL(self, reqId, account, modelCode):
self.send(92, reqId, account, modelCode)
-
[docs] def cancelPnL(self, reqId):
+
+
+
[docs]
+
def cancelPnL(self, reqId):
self.send(93, reqId)
-
[docs] def reqPnLSingle(self, reqId, account, modelCode, conid):
+
+
+
[docs]
+
def reqPnLSingle(self, reqId, account, modelCode, conid):
self.send(94, reqId, account, modelCode, conid)
-
[docs] def cancelPnLSingle(self, reqId):
+
+
+
[docs]
+
def cancelPnLSingle(self, reqId):
self.send(95, reqId)
-
[docs] def reqHistoricalTicks(
+
+
+
[docs]
+
def reqHistoricalTicks(
self, reqId, contract, startDateTime, endDateTime,
numberOfTicks, whatToShow, useRth, ignoreSize, miscOptions):
self.send(
@@ -1034,23 +1304,41 @@
Source code for ib_insync.client
startDateTime, endDateTime, numberOfTicks, whatToShow,
useRth, ignoreSize, miscOptions)
-
[docs] def reqTickByTickData(
+
+
+
[docs]
+
def reqTickByTickData(
self, reqId, contract, tickType, numberOfTicks, ignoreSize):
self.send(97, reqId, contract, tickType, numberOfTicks, ignoreSize)
-
[docs] def cancelTickByTickData(self, reqId):
+
+
+
[docs]
+
def cancelTickByTickData(self, reqId):
self.send(98, reqId)
-
[docs] def reqCompletedOrders(self, apiOnly):
+
+
+
[docs]
+
def reqCompletedOrders(self, apiOnly):
self.send(99, apiOnly)
-