Add quote polling; pseudo-streaming
Add a ``poll_tickers`` coro which can be used to "stream" quotes at a requested rate. Expose through a cli subcommand `piker stream`. Drop the `pikerd` command for now.kivy_mainline_and_py3.8
parent
42ec8330f1
commit
797efedf6a
|
@ -1,7 +1,6 @@
|
|||
"""
|
||||
Console interface to broker client/daemons.
|
||||
"""
|
||||
import json
|
||||
from functools import partial
|
||||
from importlib import import_module
|
||||
|
||||
|
@ -23,15 +22,6 @@ def run(main, loglevel='info'):
|
|||
log.debug("Exiting piker")
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option('--broker', default='questrade', help='Broker backend to use')
|
||||
@click.option('--loglevel', '-l', default='info', help='Logging level')
|
||||
def pikerd(broker, loglevel):
|
||||
# import broker module daemon entry point
|
||||
brokermod = import_module('.' + broker, 'piker.brokers')
|
||||
run(brokermod.serve_forever, loglevel)
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli():
|
||||
pass
|
||||
|
@ -59,3 +49,18 @@ def api(meth, kwargs, loglevel, broker):
|
|||
data = run(partial(brokermod.api, meth, **_kwargs), loglevel=loglevel)
|
||||
if data:
|
||||
click.echo(colorize_json(data))
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--broker', default='questrade', help='Broker backend to use')
|
||||
@click.option('--loglevel', '-l', default='info', help='Logging level')
|
||||
@click.argument('tickers', nargs=-1)
|
||||
def stream(broker, loglevel, tickers):
|
||||
# import broker module daemon entry point
|
||||
bm = import_module('.' + broker, 'piker.brokers')
|
||||
run(
|
||||
partial(bm.serve_forever, [
|
||||
partial(bm.poll_tickers, tickers=tickers)
|
||||
]),
|
||||
loglevel
|
||||
)
|
||||
|
|
|
@ -140,6 +140,17 @@ class Client:
|
|||
self._prep_sess()
|
||||
return self.access_data
|
||||
|
||||
async def tickers2ids(self, tickers):
|
||||
"""Helper routine that take a sequence of ticker symbols and returns
|
||||
their corresponding QT symbol ids.
|
||||
"""
|
||||
data = await self.api.symbols(names=','.join(tickers))
|
||||
symbols2ids = {}
|
||||
for ticker, symbol in zip(tickers, data['symbols']):
|
||||
symbols2ids[symbol['symbol']] = symbol['symbolId']
|
||||
|
||||
return symbols2ids
|
||||
|
||||
|
||||
class API:
|
||||
"""Questrade API at its finest.
|
||||
|
@ -234,15 +245,34 @@ async def get_client() -> Client:
|
|||
write_conf(client)
|
||||
|
||||
|
||||
async def serve_forever() -> None:
|
||||
async def serve_forever(tasks) -> None:
|
||||
"""Start up a client and serve until terminated.
|
||||
"""
|
||||
async with get_client() as client:
|
||||
# pretty sure this doesn't work
|
||||
# await client._revoke_auth_token()
|
||||
|
||||
async with trio.open_nursery() as nursery:
|
||||
# launch token manager
|
||||
nursery.start_soon(token_refresher, client)
|
||||
|
||||
# launch children
|
||||
for task in tasks:
|
||||
nursery.start_soon(task, client)
|
||||
|
||||
|
||||
async def poll_tickers(client, tickers, rate=2):
|
||||
"""Auto-poll snap quotes for a sequence of tickers at the given ``rate``
|
||||
per second.
|
||||
"""
|
||||
t2ids = await client.tickers2ids(tickers)
|
||||
sleeptime = 1. / rate
|
||||
ids = ','.join(map(str, t2ids.values()))
|
||||
|
||||
while True: # use an event here to trigger exit?
|
||||
quote_data = await client.api.quotes(ids=ids)
|
||||
await trio.sleep(sleeptime)
|
||||
|
||||
|
||||
async def api(methname, **kwargs) -> dict:
|
||||
"""Make (proxy) through an api call by name and return its result.
|
||||
|
|
Loading…
Reference in New Issue