Change `piker symbol-info` -> `mkt-info`

As part of bringing the brokerd agnostic APIs up to date and modernizing
wrapping CLIs, this adds a new sub-cmd to allow more or less directly
calling the `.get_mkt_info()` broker mod endpoint and dumping the both
the backend specific `Pair`-ish and `.accounting.MktPair` normalized
version to console.

Deatz:
- make the click config's `brokermods` entry a `dict`
- make `.brokers.core.mkt_info()` strip the broker name part from the
  input fqme before calling the backend.
basic_buy_bot
Tyler Goodlet 2023-06-12 20:19:18 -04:00
parent cc3037149c
commit b15e736e3e
3 changed files with 76 additions and 24 deletions

View File

@ -21,6 +21,7 @@ import os
from functools import partial
from operator import attrgetter
from operator import itemgetter
from types import ModuleType
import click
import trio
@ -241,7 +242,7 @@ def quote(config, tickers):
'''
# global opts
brokermod = config['brokermods'][0]
brokermod = list(config['brokermods'].values())[0]
quotes = trio.run(partial(core.stocks_quote, brokermod, tickers))
if not quotes:
@ -268,7 +269,7 @@ def bars(config, symbol, count):
'''
# global opts
brokermod = config['brokermods'][0]
brokermod = list(config['brokermods'].values())[0]
# broker backend should return at the least a
# list of candle dictionaries
@ -303,7 +304,7 @@ def record(config, rate, name, dhost, filename):
'''
# global opts
brokermod = config['brokermods'][0]
brokermod = list(config['brokermods'].values())[0]
loglevel = config['loglevel']
log = config['log']
@ -368,7 +369,7 @@ def optsquote(config, symbol, date):
'''
# global opts
brokermod = config['brokermods'][0]
brokermod = list(config['brokermods'].values())[0]
quotes = trio.run(
partial(
@ -385,26 +386,70 @@ def optsquote(config, symbol, date):
@cli.command()
@click.argument('tickers', nargs=-1, required=True)
@click.pass_obj
def symbol_info(config, tickers):
def mkt_info(
config: dict,
tickers: list[str],
):
'''
Print symbol quotes to the console
'''
# global opts
brokermod = config['brokermods'][0]
from msgspec.json import encode, decode
from ..accounting import MktPair
from ..service import (
open_piker_runtime,
)
quotes = trio.run(partial(core.symbol_info, brokermod, tickers))
if not quotes:
log.error(f"No quotes could be found for {tickers}?")
# global opts
brokermods: dict[str, ModuleType] = config['brokermods']
mkts: list[MktPair] = []
async def main():
async with open_piker_runtime(
name='mkt_info_query',
# loglevel=loglevel,
# debug_mode=True,
) as (_, _):
for fqme in tickers:
bs_fqme, _, broker = fqme.partition('.')
brokermod: ModuleType = brokermods[broker]
mkt, bs_pair = await core.mkt_info(
brokermod,
bs_fqme,
)
mkts.append((mkt, bs_pair))
trio.run(main)
if not mkts:
log.error(
f'No market info could be found for {tickers}'
)
return
if len(quotes) < len(tickers):
syms = tuple(map(itemgetter('symbol'), quotes))
if len(mkts) < len(tickers):
syms = tuple(map(itemgetter('fqme'), mkts))
for ticker in tickers:
if ticker not in syms:
brokermod.log.warn(f"Could not find symbol {ticker}?")
log.warn(f"Could not find symbol {ticker}?")
click.echo(colorize_json(quotes))
# TODO: use ``rich.Table`` intead here!
for mkt, bs_pair in mkts:
click.echo(
'\n'
'----------------------------------------------------\n'
f'{type(bs_pair)}\n'
'----------------------------------------------------\n'
f'{colorize_json(bs_pair.to_dict())}\n'
'----------------------------------------------------\n'
f'as piker `MktPair` with fqme: {mkt.fqme}\n'
'----------------------------------------------------\n'
# NOTE: roundtrip to json codec for console print
f'{colorize_json(decode(encode(mkt)))}'
)
@cli.command()
@ -416,7 +461,7 @@ def search(config, pattern):
'''
# global opts
brokermods = config['brokermods']
brokermods = list(config['brokermods'].values())
# define tractor entrypoint
async def main(func):

View File

@ -30,6 +30,7 @@ from ._util import log
from . import get_brokermod
from ..service import maybe_spawn_brokerd
from .._cacheables import open_cached_client
from ..accounting import MktPair
async def api(brokername: str, methname: str, **kwargs) -> dict:
@ -116,15 +117,19 @@ async def bars(
return await client.bars(symbol, **kwargs)
async def symbol_info(
async def mkt_info(
brokermod: ModuleType,
symbol: str,
fqme: str,
**kwargs,
) -> Dict[str, Dict[str, Dict[str, Any]]]:
"""Return symbol info from broker.
"""
async with brokermod.get_client() as client:
return await client.symbol_info(symbol, **kwargs)
) -> MktPair:
'''
Return MktPair info from broker including src and dst assets.
'''
return await brokermod.get_mkt_info(
fqme.replace(brokermod.name, '')
)
async def search_w_brokerd(name: str, pattern: str) -> dict:

View File

@ -20,6 +20,7 @@ CLI commons.
'''
import os
from contextlib import AsyncExitStack
from types import ModuleType
import click
import trio
@ -100,7 +101,6 @@ def pikerd(
registry_addr=reg_addr,
) as service_mngr, # normally delivers a ``Services`` handle
trio.open_nursery() as n,
AsyncExitStack() as stack,
):
@ -163,7 +163,9 @@ def cli(
from piker.brokers import __brokers__
brokers = __brokers__
brokermods = [get_brokermod(broker) for broker in brokers]
brokermods: dict[str, ModuleType] = {
broker: get_brokermod(broker) for broker in brokers
}
assert brokermods
reg_addr: None | tuple[str, int] = None