ib: fill out contract tables in `.get_mkt_info()`

Since getting a global symcache result from the API is basically
impossible, we ad-hoc fill out the needed client tables on demand per
client code queries to the mkt info EP.

Also, use `unpack_fqme()` in fqme (search) pattern parser instead of
hacky `str.partition()`.
account_tests
Tyler Goodlet 2023-07-25 16:43:08 -04:00
parent 50b221f788
commit b33be86b2f
1 changed files with 32 additions and 17 deletions

View File

@ -37,6 +37,7 @@ import trio
from piker.accounting import (
Asset,
MktPair,
unpack_fqme,
)
from piker._cacheables import (
async_lifo_cache,
@ -49,6 +50,7 @@ from ._util import (
if TYPE_CHECKING:
from .api import (
MethodProxy,
Client,
)
_futes_venues = (
@ -358,24 +360,23 @@ def parse_patt2fqme(
# fqme parsing stage
# ------------------
if '.ib' in pattern:
from piker.accounting import unpack_fqme
_, symbol, venue, expiry = unpack_fqme(pattern)
else:
symbol = pattern
expiry = ''
# another hack for forex pairs lul.
if (
'.idealpro' in symbol
# or '/' in symbol
):
exch = 'IDEALPRO'
symbol = symbol.removesuffix('.idealpro')
if '/' in symbol:
symbol, currency = symbol.split('/')
# # another hack for forex pairs lul.
# if (
# '.idealpro' in symbol
# # or '/' in symbol
# ):
# exch: str = 'IDEALPRO'
# symbol = symbol.removesuffix('.idealpro')
# if '/' in symbol:
# symbol, currency = symbol.split('/')
else:
# else:
# TODO: yes, a cache..
# try:
# # give the cache a go
@ -387,9 +388,9 @@ def parse_patt2fqme(
symbol, _, expiry = symbol.rpartition('.')
# use heuristics to figure out contract "type"
symbol, exch = symbol.upper().rsplit('.', maxsplit=1)
symbol, venue = symbol.upper().rsplit('.', maxsplit=1)
return symbol, currency, exch, expiry
return symbol, currency, venue, expiry
def con2fqme(
@ -406,9 +407,12 @@ def con2fqme(
'''
# should be real volume for this contract by default
calc_price = False
calc_price: bool = False
if con.conId:
try:
# TODO: LOL so apparently IB just changes the contract
# ID (int) on a whim.. so we probably need to use an
# FQME style key after all...
return _cache[con.conId]
except KeyError:
pass
@ -475,8 +479,9 @@ async def get_mkt_info(
) -> tuple[MktPair, ibis.ContractDetails]:
# XXX: we don't need to split off any fqme broker part?
# bs_fqme, _, broker = fqme.partition('.')
if '.ib' not in fqme:
fqme += '.ib'
broker, pair, venue, expiry = unpack_fqme(fqme)
proxy: MethodProxy
if proxy is not None:
@ -492,7 +497,7 @@ async def get_mkt_info(
(
con, # Contract
details, # ContractDetails
) = await proxy.get_sym_details(symbol=fqme)
) = await proxy.get_sym_details(fqme=fqme)
except ConnectionError:
log.exception(f'Proxy is ded {proxy._aio_ns}')
raise
@ -558,4 +563,14 @@ async def get_mkt_info(
_fqme_without_src=(atype != 'fiat'),
)
# if possible register the bs_mktid to the just-built
# mkt so that it can be retreived by order mode tasks later.
# TODO NOTE: this is going to be problematic if/when we split
# out the datatd vs. brokerd actors since the mktmap lookup
# table will now be inaccessible..
if proxy is not None:
client: Client = proxy._aio_ns
client._contracts[mkt.bs_fqme] = con
client._cons2mkts[con] = mkt
return mkt, details