|
@@ -42,6 +42,11 @@ percent_cols = {
|
|
|
'y': 'year',
|
|
'y': 'year',
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+class RowDict(dict):
|
|
|
|
|
+
|
|
|
|
|
+ def __iter__(self):
|
|
|
|
|
+ return (e for v in self.values() for e in v)
|
|
|
|
|
+
|
|
|
class DataSource:
|
|
class DataSource:
|
|
|
|
|
|
|
|
source_groups = [
|
|
source_groups = [
|
|
@@ -233,7 +238,7 @@ class DataSource:
|
|
|
return [data] if cfg.btc_only else data
|
|
return [data] if cfg.btc_only else data
|
|
|
|
|
|
|
|
@staticmethod
|
|
@staticmethod
|
|
|
- def parse_asset_id(s, require_label):
|
|
|
|
|
|
|
+ def parse_asset_id(s, require_label=True):
|
|
|
sym, label = (*s.split('-', 1), None)[:2]
|
|
sym, label = (*s.split('-', 1), None)[:2]
|
|
|
if require_label and not label:
|
|
if require_label and not label:
|
|
|
die(1, f'{s!r}: asset label is missing')
|
|
die(1, f'{s!r}: asset label is missing')
|
|
@@ -286,7 +291,7 @@ class DataSource:
|
|
|
|
|
|
|
|
@property
|
|
@property
|
|
|
def symbols(self):
|
|
def symbols(self):
|
|
|
- return [r.symbol for r in cfg.rows if isinstance(r, tuple) and r.source == 'fi']
|
|
|
|
|
|
|
+ return [r.symbol for r in cfg.rows if r.source == 'fi']
|
|
|
|
|
|
|
|
def get_data_from_network(self):
|
|
def get_data_from_network(self):
|
|
|
|
|
|
|
@@ -314,7 +319,7 @@ class DataSource:
|
|
|
return ticker.price
|
|
return ticker.price
|
|
|
|
|
|
|
|
@staticmethod
|
|
@staticmethod
|
|
|
- def parse_asset_id(s, require_label):
|
|
|
|
|
|
|
+ def parse_asset_id(s, require_label=True):
|
|
|
return asset_tuple(
|
|
return asset_tuple(
|
|
|
symbol = s.upper(),
|
|
symbol = s.upper(),
|
|
|
id = s.lower(),
|
|
id = s.lower(),
|
|
@@ -411,6 +416,7 @@ def gen_data(data):
|
|
|
d['percent_change_7d'] = d['quotes']['USD']['percent_change_7d']
|
|
d['percent_change_7d'] = d['quotes']['USD']['percent_change_7d']
|
|
|
d['percent_change_30d'] = d['quotes']['USD']['percent_change_30d']
|
|
d['percent_change_30d'] = d['quotes']['USD']['percent_change_30d']
|
|
|
d['percent_change_1y'] = d['quotes']['USD']['percent_change_1y']
|
|
d['percent_change_1y'] = d['quotes']['USD']['percent_change_1y']
|
|
|
|
|
+ d['market_cap'] = d['quotes']['USD']['market_cap']
|
|
|
d['last_updated'] = int(datetime.datetime.fromisoformat(
|
|
d['last_updated'] = int(datetime.datetime.fromisoformat(
|
|
|
d['last_updated']).timestamp())
|
|
d['last_updated']).timestamp())
|
|
|
yield (d['id'], d)
|
|
yield (d['id'], d)
|
|
@@ -456,8 +462,8 @@ def gen_data(data):
|
|
|
return ()
|
|
return ()
|
|
|
|
|
|
|
|
rows_want = {
|
|
rows_want = {
|
|
|
- 'id': {r.id for r in cfg.rows if isinstance(r, tuple) and r.id} - {'usd-us-dollar'},
|
|
|
|
|
- 'symbol': {r.symbol for r in cfg.rows if isinstance(r, tuple) and r.id is None} - {'USD'}}
|
|
|
|
|
|
|
+ 'id': {r.id for r in cfg.rows if r.id} - {'usd-us-dollar'},
|
|
|
|
|
+ 'symbol': {r.symbol for r in cfg.rows if r.id is None} - {'USD'}}
|
|
|
usr_rate_assets = tuple(u.rate_asset for u in cfg.usr_rows + cfg.usr_columns if u.rate_asset)
|
|
usr_rate_assets = tuple(u.rate_asset for u in cfg.usr_rows + cfg.usr_columns if u.rate_asset)
|
|
|
usr_rate_assets_want = {
|
|
usr_rate_assets_want = {
|
|
|
'id': {a.id for a in usr_rate_assets if a.id},
|
|
'id': {a.id for a in usr_rate_assets if a.id},
|
|
@@ -580,13 +586,16 @@ def main():
|
|
|
global cfg
|
|
global cfg
|
|
|
|
|
|
|
|
if cfg.asset_range:
|
|
if cfg.asset_range:
|
|
|
- func = DataSource.coinpaprika.parse_asset_id
|
|
|
|
|
n, m = cfg.asset_range
|
|
n, m = cfg.asset_range
|
|
|
- cfg = cfg._replace(rows =
|
|
|
|
|
- tuple(func(e['id'], require_label=False) for e in src_data['cc'].data[n-1:m])
|
|
|
|
|
- + tuple(['-'])
|
|
|
|
|
- + tuple([func('btc-bitcoin', require_label=True)])
|
|
|
|
|
- + tuple(r for r in cfg.rows if isinstance(r, tuple) and r.source == 'fi'))
|
|
|
|
|
|
|
+ cfg = cfg._replace(rows = RowDict({
|
|
|
|
|
+ 'asset_list':
|
|
|
|
|
+ tuple(
|
|
|
|
|
+ asset_tuple(e['symbol'], e['id'], source='cc')
|
|
|
|
|
+ for e in src_data['cc'].data[n-1:m]),
|
|
|
|
|
+ 'extra':
|
|
|
|
|
+ tuple(
|
|
|
|
|
+ [asset_tuple('BTC', 'btc-bitcoin', source='cc')]
|
|
|
|
|
+ + [r for r in cfg.rows if r.source == 'fi'])}))
|
|
|
|
|
|
|
|
global now
|
|
global now
|
|
|
now = 1659465400 if gcfg.test_suite else time.time() # 1659524400 1659445900
|
|
now = 1659465400 if gcfg.test_suite else time.time() # 1659524400 1659445900
|
|
@@ -604,19 +613,9 @@ def make_cfg(gcfg_arg):
|
|
|
query_tuple = namedtuple('query', ['asset', 'to_asset'])
|
|
query_tuple = namedtuple('query', ['asset', 'to_asset'])
|
|
|
asset_data = namedtuple('asset_data', ['symbol', 'id', 'amount', 'rate', 'rate_asset', 'source'])
|
|
asset_data = namedtuple('asset_data', ['symbol', 'id', 'amount', 'rate', 'rate_asset', 'source'])
|
|
|
|
|
|
|
|
- def parse_asset_id(s, require_label=False):
|
|
|
|
|
|
|
+ def parse_asset_id(s, require_label=True):
|
|
|
return src_cls['fi' if re.match(fi_pat, s) else 'cc'].parse_asset_id(s, require_label)
|
|
return src_cls['fi' if re.match(fi_pat, s) else 'cc'].parse_asset_id(s, require_label)
|
|
|
|
|
|
|
|
- def get_rows_from_cfg(add_data=None):
|
|
|
|
|
- def gen():
|
|
|
|
|
- for n, (k, v) in enumerate(cfg_in.cfg['assets'].items()):
|
|
|
|
|
- yield k
|
|
|
|
|
- if add_data and k in add_data:
|
|
|
|
|
- v += tuple(add_data[k])
|
|
|
|
|
- for e in v:
|
|
|
|
|
- yield parse_asset_id(e, require_label=True)
|
|
|
|
|
- return tuple(gen())
|
|
|
|
|
-
|
|
|
|
|
def parse_percent_cols(arg):
|
|
def parse_percent_cols(arg):
|
|
|
if arg is None or arg.lower() in ('none', ''):
|
|
if arg is None or arg.lower() in ('none', ''):
|
|
|
return []
|
|
return []
|
|
@@ -636,7 +635,7 @@ def make_cfg(gcfg_arg):
|
|
|
ss = s.split(':')
|
|
ss = s.split(':')
|
|
|
assert len(ss) in (1, 2, 3), f'{s}: malformed argument'
|
|
assert len(ss) in (1, 2, 3), f'{s}: malformed argument'
|
|
|
asset_id, rate, rate_asset = (*ss, None, None)[:3]
|
|
asset_id, rate, rate_asset = (*ss, None, None)[:3]
|
|
|
- parsed_id = parse_asset_id(asset_id)
|
|
|
|
|
|
|
+ parsed_id = parse_asset_id(asset_id, require_label=False)
|
|
|
|
|
|
|
|
return asset_data(
|
|
return asset_data(
|
|
|
symbol = parsed_id.symbol,
|
|
symbol = parsed_id.symbol,
|
|
@@ -646,11 +645,11 @@ def make_cfg(gcfg_arg):
|
|
|
None if rate is None else
|
|
None if rate is None else
|
|
|
1 / Decimal(rate[:-1]) if rate.lower().endswith('r') else
|
|
1 / Decimal(rate[:-1]) if rate.lower().endswith('r') else
|
|
|
Decimal(rate)),
|
|
Decimal(rate)),
|
|
|
- rate_asset = parse_asset_id(rate_asset) if rate_asset else None,
|
|
|
|
|
|
|
+ rate_asset = parse_asset_id(rate_asset, require_label=False) if rate_asset else None,
|
|
|
source = parsed_id.source)
|
|
source = parsed_id.source)
|
|
|
|
|
|
|
|
cl_opt = getattr(gcfg, key)
|
|
cl_opt = getattr(gcfg, key)
|
|
|
- if (cl_opt or '').lower() in ('', 'none'):
|
|
|
|
|
|
|
+ if cl_opt is None or cl_opt.lower() in ('none', ''):
|
|
|
return ()
|
|
return ()
|
|
|
cf_opt = cfg_in.cfg.get(key,[]) if use_cf_file else []
|
|
cf_opt = cfg_in.cfg.get(key,[]) if use_cf_file else []
|
|
|
return tuple(parse_parm(s) for s in (cl_opt.split(',') if cl_opt else cf_opt))
|
|
return tuple(parse_parm(s) for s in (cl_opt.split(',') if cl_opt else cf_opt))
|
|
@@ -675,7 +674,7 @@ def make_cfg(gcfg_arg):
|
|
|
asset_id:amount[:to_asset_id[:to_amount]]
|
|
asset_id:amount[:to_asset_id[:to_amount]]
|
|
|
"""
|
|
"""
|
|
|
def parse_query_asset(asset_id, amount):
|
|
def parse_query_asset(asset_id, amount):
|
|
|
- parsed_id = parse_asset_id(asset_id)
|
|
|
|
|
|
|
+ parsed_id = parse_asset_id(asset_id, require_label=False)
|
|
|
return asset_data(
|
|
return asset_data(
|
|
|
symbol = parsed_id.symbol,
|
|
symbol = parsed_id.symbol,
|
|
|
id = parsed_id.id,
|
|
id = parsed_id.id,
|
|
@@ -702,15 +701,16 @@ def make_cfg(gcfg_arg):
|
|
|
|
|
|
|
|
def get_usr_assets():
|
|
def get_usr_assets():
|
|
|
return (
|
|
return (
|
|
|
- 'user_added',
|
|
|
|
|
- usr_rows +
|
|
|
|
|
- (tuple(asset for asset in query if asset) if query else ()) +
|
|
|
|
|
- usr_columns)
|
|
|
|
|
|
|
+ usr_rows
|
|
|
|
|
+ + (tuple(asset for asset in query if asset) if query else ())
|
|
|
|
|
+ + usr_columns)
|
|
|
|
|
|
|
|
- def get_portfolio_assets(ret=()):
|
|
|
|
|
|
|
+ def get_portfolio_assets():
|
|
|
if cfg_in.portfolio and gcfg.portfolio:
|
|
if cfg_in.portfolio and gcfg.portfolio:
|
|
|
- ret = (parse_asset_id(e, require_label=True) for e in cfg_in.portfolio)
|
|
|
|
|
- return ('portfolio', tuple(e for e in ret if (not gcfg.btc) or e.symbol == 'BTC'))
|
|
|
|
|
|
|
+ ret = (parse_asset_id(e) for e in cfg_in.portfolio)
|
|
|
|
|
+ return tuple(e for e in ret if (not gcfg.btc) or e.symbol == 'BTC')
|
|
|
|
|
+ else:
|
|
|
|
|
+ return ()
|
|
|
|
|
|
|
|
def get_portfolio():
|
|
def get_portfolio():
|
|
|
return {k: Decimal(v) for k, v in cfg_in.portfolio.items()
|
|
return {k: Decimal(v) for k, v in cfg_in.portfolio.items()
|
|
@@ -727,18 +727,18 @@ def make_cfg(gcfg_arg):
|
|
|
return int(s)
|
|
return int(s)
|
|
|
|
|
|
|
|
def create_rows():
|
|
def create_rows():
|
|
|
- rows = (
|
|
|
|
|
- ('trade_pair',) + query if (query and query.to_asset) else
|
|
|
|
|
- ('bitcoin', parse_asset_id('btc-bitcoin')) if gcfg.btc else
|
|
|
|
|
- get_rows_from_cfg(add_data={'fiat':['usd-us-dollar']} if gcfg.add_columns else None))
|
|
|
|
|
-
|
|
|
|
|
|
|
+ rows = RowDict(
|
|
|
|
|
+ {'trade_pair': query} if (query and query.to_asset) else
|
|
|
|
|
+ {'bitcoin': [parse_asset_id('btc-bitcoin')]} if gcfg.btc else
|
|
|
|
|
+ {k: tuple(parse_asset_id(e) for e in v) for k, v in cfg_in.cfg['assets'].items()})
|
|
|
for hdr, data in (
|
|
for hdr, data in (
|
|
|
- (get_usr_assets(),) if query else
|
|
|
|
|
- (get_usr_assets(), get_portfolio_assets())):
|
|
|
|
|
|
|
+ ('user_uniq', get_usr_assets()),
|
|
|
|
|
+ ('portfolio_uniq', get_portfolio_assets())):
|
|
|
if data:
|
|
if data:
|
|
|
- uniq_data = tuple(gen_uniq(data, 'symbol', preload=rows))
|
|
|
|
|
- if uniq_data:
|
|
|
|
|
- rows += (hdr,) + uniq_data
|
|
|
|
|
|
|
+ if uniq_data := tuple(gen_uniq(data, 'symbol', preload=rows)):
|
|
|
|
|
+ rows[hdr] = uniq_data
|
|
|
|
|
+ else:
|
|
|
|
|
+ rows[hdr] = ()
|
|
|
return rows
|
|
return rows
|
|
|
|
|
|
|
|
def get_cfg_var(name):
|
|
def get_cfg_var(name):
|
|
@@ -787,11 +787,6 @@ def make_cfg(gcfg_arg):
|
|
|
|
|
|
|
|
cfg_in = get_cfg_in()
|
|
cfg_in = get_cfg_in()
|
|
|
|
|
|
|
|
- if gcfg.test_suite: # required for testing with overlay
|
|
|
|
|
- from . import Ticker as this_mod
|
|
|
|
|
- this_mod.src_cls = src_cls
|
|
|
|
|
- this_mod.cfg_in = cfg_in
|
|
|
|
|
-
|
|
|
|
|
if cmd_args := gcfg._args:
|
|
if cmd_args := gcfg._args:
|
|
|
if len(cmd_args) > 1:
|
|
if len(cmd_args) > 1:
|
|
|
die(1, 'Only one command-line argument is allowed')
|
|
die(1, 'Only one command-line argument is allowed')
|
|
@@ -808,6 +803,13 @@ def make_cfg(gcfg_arg):
|
|
|
proxy = None if proxy == 'none' else proxy
|
|
proxy = None if proxy == 'none' else proxy
|
|
|
proxy2 = get_proxy('proxy2')
|
|
proxy2 = get_proxy('proxy2')
|
|
|
|
|
|
|
|
|
|
+ portfolio = (
|
|
|
|
|
+ get_portfolio() if cfg_in.portfolio and get_cfg_var('portfolio') and not query
|
|
|
|
|
+ else None)
|
|
|
|
|
+
|
|
|
|
|
+ if portfolio and asset_range:
|
|
|
|
|
+ die(1, '--portfolio not supported in market cap view')
|
|
|
|
|
+
|
|
|
cfg = cfg_tuple(
|
|
cfg = cfg_tuple(
|
|
|
rows = create_rows(),
|
|
rows = create_rows(),
|
|
|
usr_rows = usr_rows,
|
|
usr_rows = usr_rows,
|
|
@@ -821,9 +823,7 @@ def make_cfg(gcfg_arg):
|
|
|
cachedir = get_cfg_var('cachedir') or dfl_cachedir,
|
|
cachedir = get_cfg_var('cachedir') or dfl_cachedir,
|
|
|
proxy = proxy,
|
|
proxy = proxy,
|
|
|
proxy2 = None if proxy2 == 'none' else '' if proxy2 == '' else (proxy2 or proxy),
|
|
proxy2 = None if proxy2 == 'none' else '' if proxy2 == '' else (proxy2 or proxy),
|
|
|
- portfolio =
|
|
|
|
|
- get_portfolio() if cfg_in.portfolio and get_cfg_var('portfolio') and not query
|
|
|
|
|
- else None,
|
|
|
|
|
|
|
+ portfolio = portfolio,
|
|
|
percent_cols = parse_percent_cols(get_cfg_var('percent_cols')),
|
|
percent_cols = parse_percent_cols(get_cfg_var('percent_cols')),
|
|
|
asset_limit = get_cfg_var('asset_limit'),
|
|
asset_limit = get_cfg_var('asset_limit'),
|
|
|
cached_data = get_cfg_var('cached_data'),
|
|
cached_data = get_cfg_var('cached_data'),
|
|
@@ -835,6 +835,8 @@ def make_cfg(gcfg_arg):
|
|
|
quiet = get_cfg_var('quiet'),
|
|
quiet = get_cfg_var('quiet'),
|
|
|
verbose = get_cfg_var('verbose'))
|
|
verbose = get_cfg_var('verbose'))
|
|
|
|
|
|
|
|
|
|
+ return (src_cls, cfg_in)
|
|
|
|
|
+
|
|
|
def get_cfg_in():
|
|
def get_cfg_in():
|
|
|
ret = namedtuple('cfg_in_data', ['cfg', 'portfolio', 'cfg_file', 'portfolio_file'])
|
|
ret = namedtuple('cfg_in_data', ['cfg', 'portfolio', 'cfg_file', 'portfolio_file'])
|
|
|
cfg_file, portfolio_file = (
|
|
cfg_file, portfolio_file = (
|
|
@@ -871,17 +873,15 @@ class Ticker:
|
|
|
|
|
|
|
|
self.col1_wid = max(len('TOTAL'), (
|
|
self.col1_wid = max(len('TOTAL'), (
|
|
|
max(len(self.create_label(d['id'])) for d in data.values()) if cfg.name_labels else
|
|
max(len(self.create_label(d['id'])) for d in data.values()) if cfg.name_labels else
|
|
|
- max(len(d['symbol']) for d in data.values()))) + 1
|
|
|
|
|
|
|
+ max(len(d['symbol']) for d in data.values())))
|
|
|
|
|
|
|
|
- self.rows = [row._replace(id=self.get_id(row)) if isinstance(row, tuple) else row
|
|
|
|
|
- for row in cfg.rows]
|
|
|
|
|
|
|
+ self.rows = RowDict(
|
|
|
|
|
+ {k: tuple(row._replace(id=self.get_id(row)) for row in v) for k, v in cfg.rows.items()})
|
|
|
self.col_usd_prices = {k: self.data[k]['price_usd'] for k in self.col_ids}
|
|
self.col_usd_prices = {k: self.data[k]['price_usd'] for k in self.col_ids}
|
|
|
-
|
|
|
|
|
- self.prices = {row.id: self.get_row_prices(row.id)
|
|
|
|
|
- for row in self.rows if isinstance(row, tuple) and row.id in data}
|
|
|
|
|
|
|
+ self.prices = {row.id: self.get_row_prices(row.id) for row in self.rows if row.id in data}
|
|
|
self.prices['usd-us-dollar'] = self.get_row_prices('usd-us-dollar')
|
|
self.prices['usd-us-dollar'] = self.get_row_prices('usd-us-dollar')
|
|
|
|
|
|
|
|
- def format_last_update_col(self, cross_assets=()):
|
|
|
|
|
|
|
+ def format_last_updated_col(self, cross_assets=()):
|
|
|
|
|
|
|
|
if cfg.elapsed:
|
|
if cfg.elapsed:
|
|
|
from mmgen.util2 import format_elapsed_hr
|
|
from mmgen.util2 import format_elapsed_hr
|
|
@@ -899,19 +899,18 @@ class Ticker:
|
|
|
min_t = None
|
|
min_t = None
|
|
|
|
|
|
|
|
for row in self.rows:
|
|
for row in self.rows:
|
|
|
- if isinstance(row, tuple):
|
|
|
|
|
- try:
|
|
|
|
|
- t = int(d[row.id]['last_updated'])
|
|
|
|
|
- except TypeError as e:
|
|
|
|
|
- d[row.id]['last_updated_fmt'] = gray('--' if 'NoneType' in str(e) else str(e))
|
|
|
|
|
- except KeyError as e:
|
|
|
|
|
- msg(str(e))
|
|
|
|
|
- pass
|
|
|
|
|
- else:
|
|
|
|
|
- t_fmt = d[row.id]['last_updated_fmt'] = fmt_func(
|
|
|
|
|
- (min(t, min_t) if min_t else t),
|
|
|
|
|
- now = now)
|
|
|
|
|
- max_w = max(len(t_fmt), max_w)
|
|
|
|
|
|
|
+ try:
|
|
|
|
|
+ t = int(d[row.id]['last_updated'])
|
|
|
|
|
+ except TypeError as e:
|
|
|
|
|
+ d[row.id]['last_updated_fmt'] = gray('--' if 'NoneType' in str(e) else str(e))
|
|
|
|
|
+ except KeyError as e:
|
|
|
|
|
+ msg(str(e))
|
|
|
|
|
+ pass
|
|
|
|
|
+ else:
|
|
|
|
|
+ t_fmt = d[row.id]['last_updated_fmt'] = fmt_func(
|
|
|
|
|
+ (min(t, min_t) if min_t else t),
|
|
|
|
|
+ now = now)
|
|
|
|
|
+ max_w = max(len(t_fmt), max_w)
|
|
|
|
|
|
|
|
self.upd_w = max_w
|
|
self.upd_w = max_w
|
|
|
|
|
|
|
@@ -924,8 +923,9 @@ class Ticker:
|
|
|
if asset.id:
|
|
if asset.id:
|
|
|
return asset.id
|
|
return asset.id
|
|
|
else:
|
|
else:
|
|
|
|
|
+ m = asset.symbol
|
|
|
for d in self.data.values():
|
|
for d in self.data.values():
|
|
|
- if d['symbol'] == asset.symbol:
|
|
|
|
|
|
|
+ if m == d['symbol']:
|
|
|
return d['id']
|
|
return d['id']
|
|
|
|
|
|
|
|
def create_label(self, id):
|
|
def create_label(self, id):
|
|
@@ -961,16 +961,22 @@ class Ticker:
|
|
|
if self.table_hdr:
|
|
if self.table_hdr:
|
|
|
yield self.table_hdr
|
|
yield self.table_hdr
|
|
|
|
|
|
|
|
- for n, row in enumerate(self.rows, cfg.asset_range[0] if cfg.asset_range else 1):
|
|
|
|
|
- if isinstance(row, str):
|
|
|
|
|
- if cfg.asset_range:
|
|
|
|
|
- return
|
|
|
|
|
- yield ('-' * self.hl_wid)
|
|
|
|
|
- else:
|
|
|
|
|
|
|
+ if cfg.asset_range:
|
|
|
|
|
+ yield '-' * self.hl_wid
|
|
|
|
|
+ for n, row in enumerate(self.rows['asset_list'], cfg.asset_range[0]):
|
|
|
try:
|
|
try:
|
|
|
yield self.fmt_row(self.data[row.id], idx=n)
|
|
yield self.fmt_row(self.data[row.id], idx=n)
|
|
|
except KeyError:
|
|
except KeyError:
|
|
|
yield gray(f'(no data for {row.id})')
|
|
yield gray(f'(no data for {row.id})')
|
|
|
|
|
+ else:
|
|
|
|
|
+ for rows in self.rows.values():
|
|
|
|
|
+ if rows:
|
|
|
|
|
+ yield '-' * self.hl_wid
|
|
|
|
|
+ for row in rows:
|
|
|
|
|
+ try:
|
|
|
|
|
+ yield self.fmt_row(self.data[row.id])
|
|
|
|
|
+ except KeyError:
|
|
|
|
|
+ yield gray(f'(no data for {row.id})')
|
|
|
|
|
|
|
|
yield '-' * self.hl_wid
|
|
yield '-' * self.hl_wid
|
|
|
|
|
|
|
@@ -1003,12 +1009,12 @@ class Ticker:
|
|
|
|
|
|
|
|
super().__init__(data)
|
|
super().__init__(data)
|
|
|
|
|
|
|
|
- self.format_last_update_col()
|
|
|
|
|
|
|
+ self.format_last_updated_col()
|
|
|
|
|
|
|
|
if cfg.portfolio:
|
|
if cfg.portfolio:
|
|
|
self.prices['total'] = {col_id: sum(self.prices[row.id][col_id] * cfg.portfolio[row.id]
|
|
self.prices['total'] = {col_id: sum(self.prices[row.id][col_id] * cfg.portfolio[row.id]
|
|
|
for row in self.rows
|
|
for row in self.rows
|
|
|
- if isinstance(row, tuple) and row.id in cfg.portfolio and row.id in data)
|
|
|
|
|
|
|
+ if row.id in cfg.portfolio and row.id in data)
|
|
|
for col_id in self.col_ids}
|
|
for col_id in self.col_ids}
|
|
|
|
|
|
|
|
self.init_prec()
|
|
self.init_prec()
|
|
@@ -1036,6 +1042,7 @@ class Ticker:
|
|
|
|
|
|
|
|
return self.fs_num.format(
|
|
return self.fs_num.format(
|
|
|
idx = idx,
|
|
idx = idx,
|
|
|
|
|
+ mcap = d.get('market_cap') / 1_000_000_000 if cfg.asset_range else None,
|
|
|
lbl = self.create_label(d['id']) if cfg.name_labels else d['symbol'],
|
|
lbl = self.create_label(d['id']) if cfg.name_labels else d['symbol'],
|
|
|
pc1 = fmt_pct(d.get('percent_change_7d')),
|
|
pc1 = fmt_pct(d.get('percent_change_7d')),
|
|
|
pc2 = fmt_pct(d.get('percent_change_24h')),
|
|
pc2 = fmt_pct(d.get('percent_change_24h')),
|
|
@@ -1072,9 +1079,9 @@ class Ticker:
|
|
|
) for k in self.col_ids}
|
|
) for k in self.col_ids}
|
|
|
|
|
|
|
|
cols = (
|
|
cols = (
|
|
|
- ['label', 'usd-us-dollar'] +
|
|
|
|
|
- [asset.id for asset in self.usr_col_assets] +
|
|
|
|
|
- [a for a, b in (
|
|
|
|
|
|
|
+ ['label', 'usd-us-dollar']
|
|
|
|
|
+ + [asset.id for asset in self.usr_col_assets]
|
|
|
|
|
+ + [a for a, b in (
|
|
|
('btc-bitcoin', not cfg.btc_only),
|
|
('btc-bitcoin', not cfg.btc_only),
|
|
|
('pct1y', 'y' in cfg.percent_cols),
|
|
('pct1y', 'y' in cfg.percent_cols),
|
|
|
('pct1m', 'm' in cfg.percent_cols),
|
|
('pct1m', 'm' in cfg.percent_cols),
|
|
@@ -1082,6 +1089,14 @@ class Ticker:
|
|
|
('pct1d', 'd' in cfg.percent_cols),
|
|
('pct1d', 'd' in cfg.percent_cols),
|
|
|
('update_time', cfg.update_time))
|
|
('update_time', cfg.update_time))
|
|
|
if b])
|
|
if b])
|
|
|
|
|
+
|
|
|
|
|
+ if cfg.asset_range:
|
|
|
|
|
+ num_w = len(str(len(cfg.rows['asset_list'])))
|
|
|
|
|
+ col_fs_data.update({
|
|
|
|
|
+ 'idx': fd(' ' * (num_w + 2), f'{{idx:{num_w}}}) ', num_w + 2),
|
|
|
|
|
+ 'mcap': fd('{mcap:>12}', '{mcap:12.5f}', 12)})
|
|
|
|
|
+ cols = ['idx', 'label', 'mcap'] + cols[1:]
|
|
|
|
|
+
|
|
|
cols2 = list(cols)
|
|
cols2 = list(cols)
|
|
|
if cfg.update_time:
|
|
if cfg.update_time:
|
|
|
cols2.pop()
|
|
cols2.pop()
|
|
@@ -1095,19 +1110,11 @@ class Ticker:
|
|
|
self.fs_num2 = ''.join(col_fs_data[c].fs_num for c in cols2)
|
|
self.fs_num2 = ''.join(col_fs_data[c].fs_num for c in cols2)
|
|
|
self.hl_wid2 = sum(col_fs_data[c].wid for c in cols2)
|
|
self.hl_wid2 = sum(col_fs_data[c].wid for c in cols2)
|
|
|
|
|
|
|
|
- if cfg.asset_range:
|
|
|
|
|
- def get_col1_w():
|
|
|
|
|
- for n, r in enumerate(cfg.rows):
|
|
|
|
|
- if isinstance(r, str):
|
|
|
|
|
- return len(str(n))
|
|
|
|
|
- col1_w = get_col1_w()
|
|
|
|
|
- self.fs_str = ' ' * (col1_w + 2) + self.fs_str
|
|
|
|
|
- self.fs_num = f'{{idx:{col1_w}}}) ' + self.fs_num
|
|
|
|
|
-
|
|
|
|
|
@property
|
|
@property
|
|
|
def table_hdr(self):
|
|
def table_hdr(self):
|
|
|
return self.fs_str.format(
|
|
return self.fs_str.format(
|
|
|
lbl = '',
|
|
lbl = '',
|
|
|
|
|
+ mcap = 'MarketCap(B)',
|
|
|
pc1 = ' CHG_7d',
|
|
pc1 = ' CHG_7d',
|
|
|
pc2 = 'CHG_24h',
|
|
pc2 = 'CHG_24h',
|
|
|
pc3 = 'CHG_1y',
|
|
pc3 = 'CHG_1y',
|
|
@@ -1152,7 +1159,7 @@ class Ticker:
|
|
|
for a in self.usr_col_assets:
|
|
for a in self.usr_col_assets:
|
|
|
self.prices[a.id]['usd-us-dollar'] = data[a.id]['price_usd']
|
|
self.prices[a.id]['usd-us-dollar'] = data[a.id]['price_usd']
|
|
|
|
|
|
|
|
- self.format_last_update_col(cross_assets=self.usr_col_assets)
|
|
|
|
|
|
|
+ self.format_last_updated_col(cross_assets=self.usr_col_assets)
|
|
|
|
|
|
|
|
self.init_prec()
|
|
self.init_prec()
|
|
|
self.init_fs()
|
|
self.init_fs()
|