Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/qt_ticker_table.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import PyQt5.QtWidgets as qt
# import PySide6.QtWidgets as qt

# import PySide6.QtWidgets as qt
from ib_async import IB, util
from ib_async.contract import * # noqa

Expand Down
2 changes: 1 addition & 1 deletion ib_async/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from . import util
from .client import Client
from .contract import (
CFD,
Bag,
Bond,
CFD,
ComboLeg,
Commodity,
ContFuture,
Expand Down
15 changes: 7 additions & 8 deletions ib_async/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
import struct
import time
from collections import deque
from typing import Any, Callable, Deque, List, Optional
from collections.abc import Callable
from typing import Any

from eventkit import Event

from .connection import Connection
from .contract import Contract
from .decoder import Decoder
from .objects import ConnectionStats, WshEventData
from .util import dataclassAsTuple, getLoop, run, UNSET_DOUBLE, UNSET_INTEGER
from .util import UNSET_DOUBLE, UNSET_INTEGER, dataclassAsTuple, getLoop, run


class Client:
Expand Down Expand Up @@ -127,8 +128,8 @@ def reset(self):
self._numBytesRecv = 0
self._numMsgRecv = 0
self._isThrottling = False
self._msgQ: Deque[str] = deque()
self._timeQ: Deque[float] = deque()
self._msgQ: deque[str] = deque()
self._timeQ: deque[float] = deque()

def serverVersion(self) -> int:
return self._serverVersion
Expand Down Expand Up @@ -171,7 +172,7 @@ def updateReqId(self, minReqId):
"""Update the next reqId to be at least ``minReqId``."""
self._reqIdSeq = max(self._reqIdSeq, minReqId)

def getAccounts(self) -> List[str]:
def getAccounts(self) -> list[str]:
"""Get the list of account names that are under management."""
if not self.isReady():
raise ConnectionError("Not connected")
Expand All @@ -187,9 +188,7 @@ def setConnectOptions(self, connectOptions: str):
"""
self.connectOptions = connectOptions.encode()

def connect(
self, host: str, port: int, clientId: int, timeout: Optional[float] = 2.0
):
def connect(self, host: str, port: int, clientId: int, timeout: float | None = 2.0):
"""
Connect to a running TWS or IB gateway application.

Expand Down
5 changes: 2 additions & 3 deletions ib_async/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

from eventkit import Event

from ib_async.util import getLoop


class Connection(asyncio.Protocol):
"""
Expand Down Expand Up @@ -35,7 +33,8 @@ async def connectAsync(self, host, port):
self.disconnect()
await self.disconnected
self.reset()
loop = getLoop()
# Use get_running_loop() directly for optimal performance in async context
loop = asyncio.get_running_loop()
self.transport, _ = await loop.create_connection(lambda: self, host, port)

def disconnect(self):
Expand Down
18 changes: 9 additions & 9 deletions ib_async/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import datetime as dt
from dataclasses import dataclass, field
from typing import List, NamedTuple, Optional
from typing import NamedTuple, Optional

import ib_async.util as util

Expand Down Expand Up @@ -100,7 +100,7 @@ class Contract:
description: str = ""
issuerId: str = ""
comboLegsDescrip: str = ""
comboLegs: List["ComboLeg"] = field(default_factory=list)
comboLegs: list["ComboLeg"] = field(default_factory=list)
deltaNeutralContract: Optional["DeltaNeutralContract"] = None

@staticmethod
Expand Down Expand Up @@ -550,7 +550,7 @@ class TradingSession(NamedTuple):

@dataclass
class ContractDetails:
contract: Optional[Contract] = None
contract: Contract | None = None
marketName: str = ""
minTick: float = 0.0
orderTypes: str = ""
Expand All @@ -572,7 +572,7 @@ class ContractDetails:
underSymbol: str = ""
underSecType: str = ""
marketRuleIds: str = ""
secIdList: List[TagValue] = field(default_factory=list)
secIdList: list[TagValue] = field(default_factory=list)
realExpirationDate: str = ""
lastTradeTime: str = ""
stockType: str = ""
Expand All @@ -596,13 +596,13 @@ class ContractDetails:
nextOptionPartial: bool = False
notes: str = ""

def tradingSessions(self) -> List[TradingSession]:
def tradingSessions(self) -> list[TradingSession]:
return self._parseSessions(self.tradingHours)

def liquidSessions(self) -> List[TradingSession]:
def liquidSessions(self) -> list[TradingSession]:
return self._parseSessions(self.liquidHours)

def _parseSessions(self, s: str) -> List[TradingSession]:
def _parseSessions(self, s: str) -> list[TradingSession]:
"""Parse the IBKR session date range text format into native Python objects.

Note: The IBKR date range format looks like:
Expand Down Expand Up @@ -637,8 +637,8 @@ def _parseSessions(self, s: str) -> List[TradingSession]:

@dataclass
class ContractDescription:
contract: Optional[Contract] = None
derivativeSecTypes: List[str] = field(default_factory=list)
contract: Contract | None = None
derivativeSecTypes: list[str] = field(default_factory=list)


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion ib_async/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
TickAttribLast,
)
from .order import Order, OrderComboLeg, OrderCondition, OrderState
from .util import parseIBDatetime, UNSET_DOUBLE, ZoneInfo
from .util import UNSET_DOUBLE, ZoneInfo, parseIBDatetime
from .wrapper import Wrapper


Expand Down
56 changes: 28 additions & 28 deletions ib_async/ib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import datetime
import logging
import time
from enum import auto, Flag
from typing import Any, Awaitable, Iterator, List, Optional, Union
from collections.abc import Awaitable, Iterator
from enum import Flag, auto
from typing import Any

from eventkit import Event

Expand Down Expand Up @@ -48,7 +49,6 @@
LimitOrder,
Order,
OrderState,
OrderStateNumeric,
OrderStatus,
StopOrder,
Trade,
Expand Down Expand Up @@ -623,7 +623,7 @@ def executions(self) -> list[Execution]:
"""List of all executions from this session."""
return list(fill.execution for fill in self.wrapper.fills.values())

def ticker(self, contract: Contract) -> Optional[Ticker]:
def ticker(self, contract: Contract) -> Ticker | None:
"""
Get ticker of the given contract. It must have been requested before
with reqMktData with the same contract object. The ticker may not be
Expand All @@ -642,7 +642,7 @@ def pendingTickers(self) -> list[Ticker]:
"""Get a list of all tickers that have pending ticks or domTicks."""
return list(self.wrapper.pendingTickers)

def realtimeBars(self) -> list[Union[BarDataList, RealTimeBarList]]:
def realtimeBars(self) -> list[BarDataList | RealTimeBarList]:
"""
Get a list of all live updated bars. These can be 5 second realtime
bars or live updated historical bars.
Expand Down Expand Up @@ -815,7 +815,7 @@ def placeOrder(self, contract: Contract, order: Order) -> Trade:

def cancelOrder(
self, order: Order, manualCancelOrderTime: str = ""
) -> Optional[Trade]:
) -> Trade | None:
"""
Cancel the order and return the Trade it belongs to.

Expand Down Expand Up @@ -957,7 +957,7 @@ def reqCompletedOrders(self, apiOnly: bool) -> list[Trade]:
"""
return self._run(self.reqCompletedOrdersAsync(apiOnly))

def reqExecutions(self, execFilter: Optional[ExecutionFilter] = None) -> list[Fill]:
def reqExecutions(self, execFilter: ExecutionFilter | None = None) -> list[Fill]:
"""
It is recommended to use :meth:`.fills` or
:meth:`.executions` instead.
Expand Down Expand Up @@ -1167,7 +1167,7 @@ def cancelRealTimeBars(self, bars: RealTimeBarList):
def reqHistoricalData(
self,
contract: Contract,
endDateTime: Union[datetime.datetime, datetime.date, str, None],
endDateTime: datetime.datetime | datetime.date | str | None,
durationStr: str,
barSizeSetting: str,
whatToShow: str,
Expand Down Expand Up @@ -1250,7 +1250,7 @@ def reqHistoricalSchedule(
self,
contract: Contract,
numDays: int,
endDateTime: Union[datetime.datetime, datetime.date, str, None] = "",
endDateTime: datetime.datetime | datetime.date | str | None = "",
useRTH: bool = True,
) -> HistoricalSchedule:
"""
Expand All @@ -1275,14 +1275,14 @@ def reqHistoricalSchedule(
def reqHistoricalTicks(
self,
contract: Contract,
startDateTime: Union[str, datetime.date],
endDateTime: Union[str, datetime.date],
startDateTime: str | datetime.date,
endDateTime: str | datetime.date,
numberOfTicks: int,
whatToShow: str,
useRth: bool,
ignoreSize: bool = False,
miscOptions: list[TagValue] = [],
) -> List:
) -> list:
"""
Request historical ticks. The time resolution of the ticks
is one second.
Expand Down Expand Up @@ -1837,8 +1837,8 @@ def reqHistoricalNews(
self,
conId: int,
providerCodes: str,
startDateTime: Union[str, datetime.date],
endDateTime: Union[str, datetime.date],
startDateTime: str | datetime.date,
endDateTime: str | datetime.date,
totalResults: int,
historicalNewsOptions: list[TagValue] = [],
) -> HistoricalNews:
Expand Down Expand Up @@ -2029,7 +2029,7 @@ async def connectAsync(
host: str = "127.0.0.1",
port: int = 7497,
clientId: int = 1,
timeout: Optional[float] = 4,
timeout: float | None = 4,
readonly: bool = False,
account: str = "",
raiseSyncErrors: bool = False,
Expand Down Expand Up @@ -2276,7 +2276,7 @@ def reqCompletedOrdersAsync(self, apiOnly: bool) -> Awaitable[list[Trade]]:
return future

def reqExecutionsAsync(
self, execFilter: Optional[ExecutionFilter] = None
self, execFilter: ExecutionFilter | None = None
) -> Awaitable[list[Fill]]:
execFilter = execFilter or ExecutionFilter()
reqId = self.client.getReqId()
Expand All @@ -2299,7 +2299,7 @@ def reqContractDetailsAsync(

async def reqMatchingSymbolsAsync(
self, pattern: str
) -> Optional[list[ContractDescription]]:
) -> list[ContractDescription] | None:
reqId = self.client.getReqId()
future = self.wrapper.startReq(reqId)
self.client.reqMatchingSymbols(reqId, pattern)
Expand All @@ -2312,7 +2312,7 @@ async def reqMatchingSymbolsAsync(

async def reqMarketRuleAsync(
self, marketRuleId: int
) -> Optional[list[PriceIncrement]]:
) -> list[PriceIncrement] | None:
future = self.wrapper.startReq(f"marketRule-{marketRuleId}")
try:
self.client.reqMarketRule(marketRuleId)
Expand All @@ -2325,7 +2325,7 @@ async def reqMarketRuleAsync(
async def reqHistoricalDataAsync(
self,
contract: Contract,
endDateTime: Union[datetime.datetime, datetime.date, str, None],
endDateTime: datetime.datetime | datetime.date | str | None,
durationStr: str,
barSizeSetting: str,
whatToShow: str,
Expand Down Expand Up @@ -2377,7 +2377,7 @@ def reqHistoricalScheduleAsync(
self,
contract: Contract,
numDays: int,
endDateTime: Union[datetime.datetime, datetime.date, str, None] = "",
endDateTime: datetime.datetime | datetime.date | str | None = "",
useRTH: bool = True,
) -> Awaitable[HistoricalSchedule]:
reqId = self.client.getReqId()
Expand All @@ -2401,14 +2401,14 @@ def reqHistoricalScheduleAsync(
def reqHistoricalTicksAsync(
self,
contract: Contract,
startDateTime: Union[str, datetime.date],
endDateTime: Union[str, datetime.date],
startDateTime: str | datetime.date,
endDateTime: str | datetime.date,
numberOfTicks: int,
whatToShow: str,
useRth: bool,
ignoreSize: bool = False,
miscOptions: list[TagValue] = [],
) -> Awaitable[List]:
) -> Awaitable[list]:
reqId = self.client.getReqId()
future = self.wrapper.startReq(reqId, contract)
start = util.formatIBDatetime(startDateTime)
Expand Down Expand Up @@ -2502,7 +2502,7 @@ async def calculateImpliedVolatilityAsync(
optionPrice: float,
underPrice: float,
implVolOptions: list[TagValue] = [],
) -> Optional[OptionComputation]:
) -> OptionComputation | None:
reqId = self.client.getReqId()
future = self.wrapper.startReq(reqId, contract)
self.client.calculateImpliedVolatility(
Expand All @@ -2523,7 +2523,7 @@ async def calculateOptionPriceAsync(
volatility: float,
underPrice: float,
optPrcOptions: list[TagValue] = [],
) -> Optional[OptionComputation]:
) -> OptionComputation | None:
reqId = self.client.getReqId()
future = self.wrapper.startReq(reqId, contract)
self.client.calculateOptionPrice(
Expand Down Expand Up @@ -2571,11 +2571,11 @@ async def reqHistoricalNewsAsync(
self,
conId: int,
providerCodes: str,
startDateTime: Union[str, datetime.date],
endDateTime: Union[str, datetime.date],
startDateTime: str | datetime.date,
endDateTime: str | datetime.date,
totalResults: int,
historicalNewsOptions: list[TagValue] = [],
) -> Optional[HistoricalNews]:
) -> HistoricalNews | None:
reqId = self.client.getReqId()

future = self.wrapper.startReq(reqId)
Expand Down
Loading