Compare commits
3 Commits
2c45f90c5d
...
137aee510b
| Author | SHA1 | Date |
|---|---|---|
|
|
137aee510b | |
|
|
433db3a140 | |
|
|
6fa805b0a4 |
|
|
@ -768,26 +768,48 @@ class Client:
|
|||
expiry: str = '',
|
||||
front: bool = False,
|
||||
|
||||
) -> Contract:
|
||||
) -> Contract|list[Contract]:
|
||||
'''
|
||||
Get an unqualifed contract for the current "continous"
|
||||
future.
|
||||
|
||||
When input params result in a so called "ambiguous contract"
|
||||
situation, we return the list of all matches provided by,
|
||||
|
||||
`IB.qualifyContractsAsync(..., returnAll=True)`
|
||||
|
||||
'''
|
||||
# it's the "front" contract returned here
|
||||
if front:
|
||||
con = (await self.ib.qualifyContractsAsync(
|
||||
ContFuture(symbol, exchange=exchange)
|
||||
))[0]
|
||||
else:
|
||||
cons = (await self.ib.qualifyContractsAsync(
|
||||
Future(
|
||||
symbol,
|
||||
exchange=exchange,
|
||||
lastTradeDateOrContractMonth=expiry,
|
||||
cons = (
|
||||
await self.ib.qualifyContractsAsync(
|
||||
ContFuture(symbol, exchange=exchange),
|
||||
returnAll=True,
|
||||
)
|
||||
))
|
||||
con = cons[0]
|
||||
)
|
||||
else:
|
||||
cons = (
|
||||
await self.ib.qualifyContractsAsync(
|
||||
Future(
|
||||
symbol,
|
||||
exchange=exchange,
|
||||
lastTradeDateOrContractMonth=expiry,
|
||||
),
|
||||
returnAll=True,
|
||||
)
|
||||
)
|
||||
|
||||
con = cons[0]
|
||||
if isinstance(con, list):
|
||||
log.warning(
|
||||
f'{len(con)!r} futes cons matched for input params,\n'
|
||||
f'symbol={symbol!r}\n'
|
||||
f'exchange={exchange!r}\n'
|
||||
f'expiry={expiry!r}\n'
|
||||
f'\n'
|
||||
f'cons:\n'
|
||||
f'{con!r}\n'
|
||||
)
|
||||
|
||||
return con
|
||||
|
||||
|
|
@ -912,11 +934,17 @@ class Client:
|
|||
)
|
||||
exch = 'SMART' if not exch else exch
|
||||
|
||||
contracts: list[Contract] = [con]
|
||||
if isinstance(con, list):
|
||||
contracts: list[Contract] = con
|
||||
else:
|
||||
contracts: list[Contract] = [con]
|
||||
|
||||
if qualify:
|
||||
try:
|
||||
contracts: list[Contract] = (
|
||||
await self.ib.qualifyContractsAsync(con)
|
||||
await self.ib.qualifyContractsAsync(
|
||||
*contracts
|
||||
)
|
||||
)
|
||||
except RequestError as err:
|
||||
msg = err.message
|
||||
|
|
|
|||
|
|
@ -201,6 +201,15 @@ async def open_history_client(
|
|||
fqme,
|
||||
timeframe,
|
||||
end_dt=end_dt,
|
||||
|
||||
# XXX WARNING, we don't actually use this inside
|
||||
# `Client.bars()` since it isn't really supported,
|
||||
# the API instead supports a "duration" of time style
|
||||
# from the `end_dt` (or at least that was the best
|
||||
# way to get it working sanely)..
|
||||
#
|
||||
# SO, with that in mind be aware that any downstream
|
||||
# logic based on this may be mostly futile Xp
|
||||
start_dt=start_dt,
|
||||
)
|
||||
latency = time.time() - query_start
|
||||
|
|
@ -278,19 +287,27 @@ async def open_history_client(
|
|||
trimmed_bars = bars_array[
|
||||
bars_array['time'] >= start_dt.timestamp()
|
||||
]
|
||||
if (
|
||||
trimmed_first_dt := from_timestamp(trimmed_bars['time'][0])
|
||||
!=
|
||||
start_dt
|
||||
):
|
||||
# TODO! rm this once we're more confident it never hits!
|
||||
# breakpoint()
|
||||
raise RuntimeError(
|
||||
f'OHLC-bars array start is gt `start_dt` limit !!\n'
|
||||
f'start_dt: {start_dt}\n'
|
||||
f'first_dt: {first_dt}\n'
|
||||
f'trimmed_first_dt: {trimmed_first_dt}\n'
|
||||
)
|
||||
# XXX, should NEVER get HERE!
|
||||
if trimmed_bars.size:
|
||||
trimmed_first_dt: datetime = from_timestamp(trimmed_bars['time'][0])
|
||||
if (
|
||||
trimmed_first_dt
|
||||
>=
|
||||
start_dt
|
||||
):
|
||||
msg: str = (
|
||||
f'OHLC-bars array start is gt `start_dt` limit !!\n'
|
||||
f'start_dt: {start_dt}\n'
|
||||
f'first_dt: {first_dt}\n'
|
||||
f'trimmed_first_dt: {trimmed_first_dt}\n'
|
||||
f'\n'
|
||||
f'Delivering shorted frame of {trimmed_bars.size!r}\n'
|
||||
)
|
||||
log.warning(msg)
|
||||
# TODO! rm this once we're more confident it
|
||||
# never breaks anything (in the caller)!
|
||||
# breakpoint()
|
||||
# raise RuntimeError(msg)
|
||||
|
||||
# XXX, overwrite with start_dt-limited frame
|
||||
bars_array = trimmed_bars
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ from pendulum import (
|
|||
if TYPE_CHECKING:
|
||||
from ib_async import (
|
||||
TradingSession,
|
||||
Contract,
|
||||
ContractDetails,
|
||||
)
|
||||
from exchange_calendars.exchange_calendars import (
|
||||
|
|
@ -82,7 +83,12 @@ def has_holiday(
|
|||
|
||||
'''
|
||||
tz: str = con_deats.timeZoneId
|
||||
exch: str = con_deats.contract.primaryExchange
|
||||
con: Contract = con_deats.contract
|
||||
exch: str = (
|
||||
con.primaryExchange
|
||||
or
|
||||
con.exchange
|
||||
)
|
||||
|
||||
# XXX, ad-hoc handle any IB exchange which are non-std
|
||||
# via lookup table..
|
||||
|
|
|
|||
Loading…
Reference in New Issue