Reord watchlist cmds into new package
parent
ff843372a1
commit
f798d13038
|
@ -3,7 +3,6 @@ Console interface to broker client/daemons.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import json
|
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ _watchlists_data_path = os.path.join(_config_dir, 'watchlists.json')
|
||||||
@click.argument('kwargs', nargs=-1)
|
@click.argument('kwargs', nargs=-1)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def api(config, meth, kwargs, keys):
|
def api(config, meth, kwargs, keys):
|
||||||
"""client for testing broker API methods with pretty printing of output.
|
"""Make a broker-client API method call
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
broker = config['broker']
|
broker = config['broker']
|
||||||
|
@ -69,8 +68,7 @@ def api(config, meth, kwargs, keys):
|
||||||
@click.argument('tickers', nargs=-1, required=True)
|
@click.argument('tickers', nargs=-1, required=True)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def quote(config, tickers, df_output):
|
def quote(config, tickers, df_output):
|
||||||
"""Retreive symbol quotes on the console in either json or dataframe
|
"""Print symbol quotes to the console
|
||||||
format.
|
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
brokermod = config['brokermod']
|
brokermod = config['brokermod']
|
||||||
|
@ -106,8 +104,7 @@ def quote(config, tickers, df_output):
|
||||||
@click.argument('symbol', required=True)
|
@click.argument('symbol', required=True)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def bars(config, symbol, count, df_output):
|
def bars(config, symbol, count, df_output):
|
||||||
"""Retreive 1m bars for symbol and print on the console in json
|
"""Retreive 1m bars for symbol and print on the console
|
||||||
format.
|
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
brokermod = config['brokermod']
|
brokermod = config['brokermod']
|
||||||
|
@ -142,7 +139,7 @@ def bars(config, symbol, count, df_output):
|
||||||
@click.argument('name', nargs=1, required=True)
|
@click.argument('name', nargs=1, required=True)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def monitor(config, rate, name, dhost, test, tl):
|
def monitor(config, rate, name, dhost, test, tl):
|
||||||
"""Spawn a real-time watchlist.
|
"""Start a real-time watchlist UI
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
brokermod = config['brokermod']
|
brokermod = config['brokermod']
|
||||||
|
@ -186,7 +183,7 @@ def monitor(config, rate, name, dhost, test, tl):
|
||||||
@click.argument('name', nargs=1, required=True)
|
@click.argument('name', nargs=1, required=True)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def record(config, rate, name, dhost, filename):
|
def record(config, rate, name, dhost, filename):
|
||||||
"""Record client side quotes to file
|
"""Record client side quotes to a file on disk
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
brokermod = config['brokermod']
|
brokermod = config['brokermod']
|
||||||
|
@ -215,96 +212,6 @@ def record(config, rate, name, dhost, filename):
|
||||||
click.echo(f"Data feed recording saved to {filename}")
|
click.echo(f"Data feed recording saved to {filename}")
|
||||||
|
|
||||||
|
|
||||||
@cli.group()
|
|
||||||
@click.option('--config_dir', '-d', default=_watchlists_data_path,
|
|
||||||
help='Path to piker configuration directory')
|
|
||||||
@click.pass_context
|
|
||||||
def watchlists(ctx, config_dir):
|
|
||||||
"""Watchlists commands and operations
|
|
||||||
"""
|
|
||||||
loglevel = ctx.parent.params['loglevel']
|
|
||||||
get_console_log(loglevel) # activate console logging
|
|
||||||
|
|
||||||
wl.make_config_dir(_config_dir)
|
|
||||||
ctx.ensure_object(dict)
|
|
||||||
ctx.obj = {'path': config_dir,
|
|
||||||
'watchlist': wl.ensure_watchlists(config_dir)}
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='show watchlist')
|
|
||||||
@click.argument('name', nargs=1, required=False)
|
|
||||||
@click.pass_context
|
|
||||||
def show(ctx, name):
|
|
||||||
watchlist = wl.merge_watchlist(ctx.obj['watchlist'], wl._builtins)
|
|
||||||
click.echo(colorize_json(
|
|
||||||
watchlist if name is None else watchlist[name]))
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='load passed in watchlist')
|
|
||||||
@click.argument('data', nargs=1, required=True)
|
|
||||||
@click.pass_context
|
|
||||||
def load(ctx, data):
|
|
||||||
try:
|
|
||||||
wl.write_to_file(json.loads(data), ctx.obj['path'])
|
|
||||||
except (json.JSONDecodeError, IndexError):
|
|
||||||
click.echo('You have passed an invalid text respresentation of a '
|
|
||||||
'JSON object. Try again.')
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='add ticker to watchlist')
|
|
||||||
@click.argument('name', nargs=1, required=True)
|
|
||||||
@click.argument('ticker_names', nargs=-1, required=True)
|
|
||||||
@click.pass_context
|
|
||||||
def add(ctx, name, ticker_names):
|
|
||||||
for ticker in ticker_names:
|
|
||||||
watchlist = wl.add_ticker(
|
|
||||||
name, ticker, ctx.obj['watchlist'])
|
|
||||||
wl.write_to_file(watchlist, ctx.obj['path'])
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='remove ticker from watchlist')
|
|
||||||
@click.argument('name', nargs=1, required=True)
|
|
||||||
@click.argument('ticker_name', nargs=1, required=True)
|
|
||||||
@click.pass_context
|
|
||||||
def remove(ctx, name, ticker_name):
|
|
||||||
try:
|
|
||||||
watchlist = wl.remove_ticker(name, ticker_name, ctx.obj['watchlist'])
|
|
||||||
except KeyError:
|
|
||||||
log.error(f"No watchlist with name `{name}` could be found?")
|
|
||||||
except ValueError:
|
|
||||||
if name in wl._builtins and ticker_name in wl._builtins[name]:
|
|
||||||
log.error(f"Can not remove ticker `{ticker_name}` from built-in "
|
|
||||||
f"list `{name}`")
|
|
||||||
else:
|
|
||||||
log.error(f"Ticker `{ticker_name}` not found in list `{name}`")
|
|
||||||
else:
|
|
||||||
wl.write_to_file(watchlist, ctx.obj['path'])
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='delete watchlist group')
|
|
||||||
@click.argument('name', nargs=1, required=True)
|
|
||||||
@click.pass_context
|
|
||||||
def delete(ctx, name):
|
|
||||||
watchlist = wl.delete_group(name, ctx.obj['watchlist'])
|
|
||||||
wl.write_to_file(watchlist, ctx.obj['path'])
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='merge a watchlist from another user')
|
|
||||||
@click.argument('watchlist_to_merge', nargs=1, required=True)
|
|
||||||
@click.pass_context
|
|
||||||
def merge(ctx, watchlist_to_merge):
|
|
||||||
merged_watchlist = wl.merge_watchlist(json.loads(watchlist_to_merge),
|
|
||||||
ctx.obj['watchlist'])
|
|
||||||
wl.write_to_file(merged_watchlist, ctx.obj['path'])
|
|
||||||
|
|
||||||
|
|
||||||
@watchlists.command(help='dump text respresentation of a watchlist to console')
|
|
||||||
@click.argument('name', nargs=1, required=False)
|
|
||||||
@click.pass_context
|
|
||||||
def dump(ctx, name):
|
|
||||||
click.echo(json.dumps(ctx.obj['watchlist']))
|
|
||||||
|
|
||||||
|
|
||||||
# options utils
|
# options utils
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
|
@ -315,7 +222,8 @@ def dump(ctx, name):
|
||||||
@click.argument('symbol', required=True)
|
@click.argument('symbol', required=True)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def contracts(ctx, loglevel, broker, symbol, ids):
|
def contracts(ctx, loglevel, broker, symbol, ids):
|
||||||
|
"""Get list of all option contracts for symbol
|
||||||
|
"""
|
||||||
brokermod = get_brokermod(broker)
|
brokermod = get_brokermod(broker)
|
||||||
get_console_log(loglevel)
|
get_console_log(loglevel)
|
||||||
|
|
||||||
|
@ -338,8 +246,7 @@ def contracts(ctx, loglevel, broker, symbol, ids):
|
||||||
@click.argument('symbol', required=True)
|
@click.argument('symbol', required=True)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def optsquote(config, symbol, df_output, date):
|
def optsquote(config, symbol, df_output, date):
|
||||||
"""Retreive symbol quotes on the console in either
|
"""Retreive symbol option quotes on the console
|
||||||
json or dataframe format.
|
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
brokermod = config['brokermod']
|
brokermod = config['brokermod']
|
||||||
|
@ -371,7 +278,7 @@ def optsquote(config, symbol, df_output, date):
|
||||||
@click.argument('symbol', required=True)
|
@click.argument('symbol', required=True)
|
||||||
@click.pass_obj
|
@click.pass_obj
|
||||||
def optschain(config, symbol, date, tl, rate, test):
|
def optschain(config, symbol, date, tl, rate, test):
|
||||||
"""Start the real-time option chain UI.
|
"""Start an option chain UI
|
||||||
"""
|
"""
|
||||||
# global opts
|
# global opts
|
||||||
loglevel = config['loglevel']
|
loglevel = config['loglevel']
|
||||||
|
@ -382,7 +289,7 @@ def optschain(config, symbol, date, tl, rate, test):
|
||||||
async def main(tries):
|
async def main(tries):
|
||||||
async with maybe_spawn_brokerd_as_subactor(
|
async with maybe_spawn_brokerd_as_subactor(
|
||||||
tries=tries, loglevel=loglevel
|
tries=tries, loglevel=loglevel
|
||||||
) as portal:
|
):
|
||||||
# run app "main"
|
# run app "main"
|
||||||
await _async_main(
|
await _async_main(
|
||||||
symbol,
|
symbol,
|
||||||
|
|
|
@ -65,3 +65,4 @@ def cli(ctx, broker, loglevel, configdir):
|
||||||
|
|
||||||
# load downstream cli modules
|
# load downstream cli modules
|
||||||
from ..brokers import cli as _
|
from ..brokers import cli as _
|
||||||
|
from ..watchlists import cli as _
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
import json
|
import json
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from .log import get_logger
|
from ..log import get_logger
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
|
||||||
|
"""
|
||||||
|
Watchlist management commands.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from .. import watchlists as wl
|
||||||
|
from ..cli import cli
|
||||||
|
from ..log import get_console_log, colorize_json, get_logger
|
||||||
|
|
||||||
|
log = get_logger('watchlist-cli')
|
||||||
|
|
||||||
|
_config_dir = click.get_app_dir('piker')
|
||||||
|
_watchlists_data_path = os.path.join(_config_dir, 'watchlists.json')
|
||||||
|
|
||||||
|
|
||||||
|
@cli.group()
|
||||||
|
@click.option('--config_dir', '-d', default=_watchlists_data_path,
|
||||||
|
help='Path to piker configuration directory')
|
||||||
|
@click.pass_context
|
||||||
|
def watchlists(ctx, config_dir):
|
||||||
|
"""Watchlists commands and operations
|
||||||
|
"""
|
||||||
|
loglevel = ctx.parent.params['loglevel']
|
||||||
|
get_console_log(loglevel) # activate console logging
|
||||||
|
|
||||||
|
wl.make_config_dir(_config_dir)
|
||||||
|
ctx.ensure_object(dict)
|
||||||
|
ctx.obj = {'path': config_dir,
|
||||||
|
'watchlist': wl.ensure_watchlists(config_dir)}
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='show watchlist')
|
||||||
|
@click.argument('name', nargs=1, required=False)
|
||||||
|
@click.pass_context
|
||||||
|
def show(ctx, name):
|
||||||
|
watchlist = wl.merge_watchlist(ctx.obj['watchlist'], wl._builtins)
|
||||||
|
click.echo(colorize_json(
|
||||||
|
watchlist if name is None else watchlist[name]))
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='load passed in watchlist')
|
||||||
|
@click.argument('data', nargs=1, required=True)
|
||||||
|
@click.pass_context
|
||||||
|
def load(ctx, data):
|
||||||
|
try:
|
||||||
|
wl.write_to_file(json.loads(data), ctx.obj['path'])
|
||||||
|
except (json.JSONDecodeError, IndexError):
|
||||||
|
click.echo('You have passed an invalid text respresentation of a '
|
||||||
|
'JSON object. Try again.')
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='add ticker to watchlist')
|
||||||
|
@click.argument('name', nargs=1, required=True)
|
||||||
|
@click.argument('ticker_names', nargs=-1, required=True)
|
||||||
|
@click.pass_context
|
||||||
|
def add(ctx, name, ticker_names):
|
||||||
|
for ticker in ticker_names:
|
||||||
|
watchlist = wl.add_ticker(
|
||||||
|
name, ticker, ctx.obj['watchlist'])
|
||||||
|
wl.write_to_file(watchlist, ctx.obj['path'])
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='remove ticker from watchlist')
|
||||||
|
@click.argument('name', nargs=1, required=True)
|
||||||
|
@click.argument('ticker_name', nargs=1, required=True)
|
||||||
|
@click.pass_context
|
||||||
|
def remove(ctx, name, ticker_name):
|
||||||
|
try:
|
||||||
|
watchlist = wl.remove_ticker(name, ticker_name, ctx.obj['watchlist'])
|
||||||
|
except KeyError:
|
||||||
|
log.error(f"No watchlist with name `{name}` could be found?")
|
||||||
|
except ValueError:
|
||||||
|
if name in wl._builtins and ticker_name in wl._builtins[name]:
|
||||||
|
log.error(f"Can not remove ticker `{ticker_name}` from built-in "
|
||||||
|
f"list `{name}`")
|
||||||
|
else:
|
||||||
|
log.error(f"Ticker `{ticker_name}` not found in list `{name}`")
|
||||||
|
else:
|
||||||
|
wl.write_to_file(watchlist, ctx.obj['path'])
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='delete watchlist group')
|
||||||
|
@click.argument('name', nargs=1, required=True)
|
||||||
|
@click.pass_context
|
||||||
|
def delete(ctx, name):
|
||||||
|
watchlist = wl.delete_group(name, ctx.obj['watchlist'])
|
||||||
|
wl.write_to_file(watchlist, ctx.obj['path'])
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='merge a watchlist from another user')
|
||||||
|
@click.argument('watchlist_to_merge', nargs=1, required=True)
|
||||||
|
@click.pass_context
|
||||||
|
def merge(ctx, watchlist_to_merge):
|
||||||
|
merged_watchlist = wl.merge_watchlist(json.loads(watchlist_to_merge),
|
||||||
|
ctx.obj['watchlist'])
|
||||||
|
wl.write_to_file(merged_watchlist, ctx.obj['path'])
|
||||||
|
|
||||||
|
|
||||||
|
@watchlists.command(help='dump text respresentation of a watchlist to console')
|
||||||
|
@click.argument('name', nargs=1, required=False)
|
||||||
|
@click.pass_context
|
||||||
|
def dump(ctx, name):
|
||||||
|
click.echo(json.dumps(ctx.obj['watchlist']))
|
Loading…
Reference in New Issue