Compare commits
3 Commits
2c45f90c5d
...
137aee510b
| Author | SHA1 | Date |
|---|---|---|
|
|
137aee510b | |
|
|
433db3a140 | |
|
|
6fa805b0a4 |
|
|
@ -768,26 +768,48 @@ class Client:
|
||||||
expiry: str = '',
|
expiry: str = '',
|
||||||
front: bool = False,
|
front: bool = False,
|
||||||
|
|
||||||
) -> Contract:
|
) -> Contract|list[Contract]:
|
||||||
'''
|
'''
|
||||||
Get an unqualifed contract for the current "continous"
|
Get an unqualifed contract for the current "continous"
|
||||||
future.
|
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
|
# it's the "front" contract returned here
|
||||||
if front:
|
if front:
|
||||||
con = (await self.ib.qualifyContractsAsync(
|
cons = (
|
||||||
ContFuture(symbol, exchange=exchange)
|
await self.ib.qualifyContractsAsync(
|
||||||
))[0]
|
ContFuture(symbol, exchange=exchange),
|
||||||
else:
|
returnAll=True,
|
||||||
cons = (await self.ib.qualifyContractsAsync(
|
|
||||||
Future(
|
|
||||||
symbol,
|
|
||||||
exchange=exchange,
|
|
||||||
lastTradeDateOrContractMonth=expiry,
|
|
||||||
)
|
)
|
||||||
))
|
)
|
||||||
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
|
return con
|
||||||
|
|
||||||
|
|
@ -912,11 +934,17 @@ class Client:
|
||||||
)
|
)
|
||||||
exch = 'SMART' if not exch else exch
|
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:
|
if qualify:
|
||||||
try:
|
try:
|
||||||
contracts: list[Contract] = (
|
contracts: list[Contract] = (
|
||||||
await self.ib.qualifyContractsAsync(con)
|
await self.ib.qualifyContractsAsync(
|
||||||
|
*contracts
|
||||||
|
)
|
||||||
)
|
)
|
||||||
except RequestError as err:
|
except RequestError as err:
|
||||||
msg = err.message
|
msg = err.message
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,15 @@ async def open_history_client(
|
||||||
fqme,
|
fqme,
|
||||||
timeframe,
|
timeframe,
|
||||||
end_dt=end_dt,
|
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,
|
start_dt=start_dt,
|
||||||
)
|
)
|
||||||
latency = time.time() - query_start
|
latency = time.time() - query_start
|
||||||
|
|
@ -278,19 +287,27 @@ async def open_history_client(
|
||||||
trimmed_bars = bars_array[
|
trimmed_bars = bars_array[
|
||||||
bars_array['time'] >= start_dt.timestamp()
|
bars_array['time'] >= start_dt.timestamp()
|
||||||
]
|
]
|
||||||
if (
|
# XXX, should NEVER get HERE!
|
||||||
trimmed_first_dt := from_timestamp(trimmed_bars['time'][0])
|
if trimmed_bars.size:
|
||||||
!=
|
trimmed_first_dt: datetime = from_timestamp(trimmed_bars['time'][0])
|
||||||
start_dt
|
if (
|
||||||
):
|
trimmed_first_dt
|
||||||
# TODO! rm this once we're more confident it never hits!
|
>=
|
||||||
# breakpoint()
|
start_dt
|
||||||
raise RuntimeError(
|
):
|
||||||
f'OHLC-bars array start is gt `start_dt` limit !!\n'
|
msg: str = (
|
||||||
f'start_dt: {start_dt}\n'
|
f'OHLC-bars array start is gt `start_dt` limit !!\n'
|
||||||
f'first_dt: {first_dt}\n'
|
f'start_dt: {start_dt}\n'
|
||||||
f'trimmed_first_dt: {trimmed_first_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
|
# XXX, overwrite with start_dt-limited frame
|
||||||
bars_array = trimmed_bars
|
bars_array = trimmed_bars
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ from pendulum import (
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ib_async import (
|
from ib_async import (
|
||||||
TradingSession,
|
TradingSession,
|
||||||
|
Contract,
|
||||||
ContractDetails,
|
ContractDetails,
|
||||||
)
|
)
|
||||||
from exchange_calendars.exchange_calendars import (
|
from exchange_calendars.exchange_calendars import (
|
||||||
|
|
@ -82,7 +83,12 @@ def has_holiday(
|
||||||
|
|
||||||
'''
|
'''
|
||||||
tz: str = con_deats.timeZoneId
|
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
|
# XXX, ad-hoc handle any IB exchange which are non-std
|
||||||
# via lookup table..
|
# via lookup table..
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue