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
piker/brokers
|
@ -1,7 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Console interface to broker client/daemons.
|
Console interface to broker client/daemons.
|
||||||
"""
|
"""
|
||||||
import json
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
|
@ -23,15 +22,6 @@ def run(main, loglevel='info'):
|
||||||
log.debug("Exiting piker")
|
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()
|
@click.group()
|
||||||
def cli():
|
def cli():
|
||||||
pass
|
pass
|
||||||
|
@ -59,3 +49,18 @@ def api(meth, kwargs, loglevel, broker):
|
||||||
data = run(partial(brokermod.api, meth, **_kwargs), loglevel=loglevel)
|
data = run(partial(brokermod.api, meth, **_kwargs), loglevel=loglevel)
|
||||||
if data:
|
if data:
|
||||||
click.echo(colorize_json(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()
|
self._prep_sess()
|
||||||
return self.access_data
|
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:
|
class API:
|
||||||
"""Questrade API at its finest.
|
"""Questrade API at its finest.
|
||||||
|
@ -234,15 +245,34 @@ async def get_client() -> Client:
|
||||||
write_conf(client)
|
write_conf(client)
|
||||||
|
|
||||||
|
|
||||||
async def serve_forever() -> None:
|
async def serve_forever(tasks) -> None:
|
||||||
"""Start up a client and serve until terminated.
|
"""Start up a client and serve until terminated.
|
||||||
"""
|
"""
|
||||||
async with get_client() as client:
|
async with get_client() as client:
|
||||||
# pretty sure this doesn't work
|
# pretty sure this doesn't work
|
||||||
# await client._revoke_auth_token()
|
# await client._revoke_auth_token()
|
||||||
|
|
||||||
async with trio.open_nursery() as nursery:
|
async with trio.open_nursery() as nursery:
|
||||||
|
# launch token manager
|
||||||
nursery.start_soon(token_refresher, client)
|
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:
|
async def api(methname, **kwargs) -> dict:
|
||||||
"""Make (proxy) through an api call by name and return its result.
|
"""Make (proxy) through an api call by name and return its result.
|
||||||
|
|
Loading…
Reference in New Issue