mmnode-ticker: display percent change columns in terms of non-USD assets
Any crypto or finance asset may be specified.
Examples:
# Display percentage changes in relation to Bitcoin:
$ mmnode-ticker --widest --pchg-unit=btc
# In relation to Gold:
$ mmnode-ticker --widest --pchg-unit=gc=f
# In relation to Euros:
$ mmnode-ticker --widest --pchg-unit=eurusd=x
# In relation to the Nasdaq Index:
$ mmnode-ticker --widest --pchg-unit=^ixic
This commit is contained in:
parent
2647fa1fe3
commit
84e8ea65d0
5 changed files with 82 additions and 3 deletions
|
|
@ -535,6 +535,10 @@ def gen_data(data):
|
|||
'name': 'US Dollar',
|
||||
'price_usd': Decimal(1),
|
||||
'price_btc': Decimal(1) / btcusd,
|
||||
'percent_change_24h': 0.0,
|
||||
'percent_change_7d': 0.0,
|
||||
'percent_change_30d': 0.0,
|
||||
'percent_change_1y': 0.0,
|
||||
'last_updated': None})
|
||||
|
||||
def cache_data(data_src, no_overwrite=False):
|
||||
|
|
@ -742,7 +746,8 @@ def make_cfg(gcfg_arg):
|
|||
{k: tuple(parse_asset_id(e) for e in v) for k, v in cfg_in.cfg['assets'].items()})
|
||||
for hdr, data in (
|
||||
('user_uniq', get_usr_assets()),
|
||||
('portfolio_uniq', get_portfolio_assets())):
|
||||
('portfolio_uniq', get_portfolio_assets()),
|
||||
('pchg_unit_uniq', [pchg_unit] if pchg_unit else None)):
|
||||
if data:
|
||||
if uniq_data := tuple(gen_uniq(data, 'symbol', preload=rows)):
|
||||
rows[hdr] = uniq_data
|
||||
|
|
@ -791,6 +796,7 @@ def make_cfg(gcfg_arg):
|
|||
'portfolio',
|
||||
'sort',
|
||||
'percent_cols',
|
||||
'pchg_unit',
|
||||
'asset_limit',
|
||||
'cached_data',
|
||||
'elapsed',
|
||||
|
|
@ -833,6 +839,9 @@ def make_cfg(gcfg_arg):
|
|||
if portfolio and asset_range:
|
||||
die(1, '--portfolio not supported in market cap view')
|
||||
|
||||
pchg_unit = (lambda s: parse_asset_id(s, require_label=False) if s else None)(
|
||||
get_cfg_var('pchg_unit'))
|
||||
|
||||
cfg = cfg_tuple(
|
||||
rows = create_rows(),
|
||||
usr_rows = usr_rows,
|
||||
|
|
@ -849,6 +858,7 @@ def make_cfg(gcfg_arg):
|
|||
portfolio = portfolio,
|
||||
sort = get_sort_opt(),
|
||||
percent_cols = parse_percent_cols(get_cfg_var('percent_cols')),
|
||||
pchg_unit = pchg_unit,
|
||||
asset_limit = get_cfg_var('asset_limit'),
|
||||
cached_data = get_cfg_var('cached_data'),
|
||||
elapsed = get_cfg_var('elapsed'),
|
||||
|
|
@ -890,7 +900,7 @@ class Ticker:
|
|||
|
||||
offer = None
|
||||
to_asset = None
|
||||
hidden_groups = ('extra',)
|
||||
hidden_groups = ('extra', 'pchg_unit_uniq')
|
||||
|
||||
def __init__(self, data):
|
||||
|
||||
|
|
@ -925,6 +935,14 @@ class Ticker:
|
|||
cfg = cfg._replace(
|
||||
portfolio = sorted(cfg.portfolio, key=pf_sort_func, reverse=reverse))
|
||||
|
||||
if cfg.pchg_unit:
|
||||
self.pchg_data = self.data[self.get_id(cfg.pchg_unit)]
|
||||
self.pchg_factors = {k: (self.pchg_data[k] / 100) + 1 for k in (
|
||||
'percent_change_24h',
|
||||
'percent_change_7d',
|
||||
'percent_change_30d',
|
||||
'percent_change_1y')}
|
||||
|
||||
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 row.id in data}
|
||||
self.prices['usd-us-dollar'] = self.get_row_prices('usd-us-dollar')
|
||||
|
|
@ -995,6 +1013,11 @@ class Ticker:
|
|||
text = sort_params[cfg.sort[0]].desc + ('' if cfg.sort[1] else ' [reversed]')
|
||||
yield f'Sort order: {pink(text.upper())}'
|
||||
|
||||
if cfg.pchg_unit:
|
||||
yield 'Percent change unit: {}'.format(orange('{} ({})'.format(
|
||||
self.pchg_data['symbol'],
|
||||
self.pchg_data['name'].upper())))
|
||||
|
||||
for asset in self.usr_col_assets:
|
||||
if asset.symbol != 'USD':
|
||||
usdprice = self.data[asset.id]['price_usd']
|
||||
|
|
@ -1085,6 +1108,8 @@ class Ticker:
|
|||
def fmt_pct(d, key, wid=7):
|
||||
if (n := d.get(key)) is None:
|
||||
return gray(' --')
|
||||
if cfg.pchg_unit:
|
||||
n = ((((n / 100) + 1) / self.pchg_factors[key]) - 1) * 100
|
||||
return (red, green)[n>=0](f'{n:+{wid}.2f}')
|
||||
|
||||
p = self.prices[d['id']]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.6.dev8
|
||||
3.6.dev9
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ opts_data = {
|
|||
-t, --testing Print command(s) to be executed to stdout and exit
|
||||
-T, --thousands-comma Use comma as a thousands separator
|
||||
-u, --update-time Include UPDATED (last update time) column
|
||||
-U, --pchg-unit=A Use asset ‘A’ as unit of reference for percentage
|
||||
change columns (default: USD)
|
||||
-v, --verbose Be more verbose
|
||||
-w, --wide Display most optional columns (same as -unT -p d,w)
|
||||
-W, --widest Display all optional columns (same as -unT -p d,w,m,y)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ class CmdTestScripts(CmdTestBase):
|
|||
('ticker27', 'ticker [--sort=rp -r algo,ada]'),
|
||||
('ticker28', 'ticker [--sort=d -r algo,ada]'),
|
||||
('ticker29', 'ticker [--sort=y -r algo,ada]'),
|
||||
('ticker30', 'ticker [--cached-data --wide --pchg-unit=btc --sort=d] (cf with config file)'),
|
||||
('ticker31', 'ticker [--cached-data --wide --pchg-unit=usd] (cf with no USD)'),
|
||||
('ticker32', 'ticker [--cached-data --wide --pchg-unit=gc=f]'),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -438,3 +441,38 @@ class CmdTestScripts(CmdTestBase):
|
|||
[],
|
||||
['ETHEREUM', 'BITCOIN', 'MONERO', 'S&P', 'DOW', 'NASDAQ', 'CARDANO', 'ALGORAND'],
|
||||
add_opts = ['--widest', '-s', 'y', '-r', 'ada,algo'])
|
||||
|
||||
def ticker30(self):
|
||||
self.copy_file('ticker-cfg-sort-pchg.yaml', 'ticker-cfg.yaml')
|
||||
t = self.ticker(add_opts=['--wide'])
|
||||
chk1 = '\n'.join(t.read().splitlines()[5:-2])
|
||||
self.rm_file('ticker-cfg.yaml')
|
||||
|
||||
self.copy_file('ticker-cfg-bad.yaml', 'ticker-cfg.yaml')
|
||||
t = self.ticker(add_opts=['--wide', '--pchg-unit=btc', '--sort=d'], no_msg=True)
|
||||
chk2 = '\n'.join(t.read().splitlines()[5:-2])
|
||||
self.rm_file('ticker-cfg.yaml')
|
||||
|
||||
assert chk1 == chk2, f'\nOUTPUT 1\n{chk1}\n!= OUTPUT 2\n{chk2}\n'
|
||||
return t
|
||||
|
||||
def ticker31(self):
|
||||
t = self.ticker(add_opts=['--wide'])
|
||||
chk1 = '\n'.join(t.read().splitlines()[5:-2])
|
||||
|
||||
t = self.ticker(add_opts=['--wide', '--pchg-unit=usd'], no_msg=True)
|
||||
chk2 = '\n'.join(t.read().splitlines()[6:-2])
|
||||
|
||||
assert chk1 == chk2, f'\nOUTPUT 1\n{chk1}\n!= OUTPUT 2\n{chk2}\n'
|
||||
return t
|
||||
|
||||
def ticker32(self):
|
||||
return self.ticker(
|
||||
[],
|
||||
[
|
||||
'BITCOIN', r'\+10.99', r'\+7.06', '-1.18', r'\+1.05',
|
||||
'ETHEREUM',
|
||||
'GOLD', r'\+0.00', r'\+0.00', r'\+0.00', r'\+0.00',
|
||||
'SILVER'
|
||||
],
|
||||
add_opts = ['--widest', '--pchg-unit=gc=f'])
|
||||
|
|
|
|||
14
test/ref/ticker/ticker-cfg-sort-pchg.yaml
Normal file
14
test/ref/ticker/ticker-cfg-sort-pchg.yaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
sort: d
|
||||
pchg_unit: btc
|
||||
|
||||
assets:
|
||||
coin1:
|
||||
- btc-bitcoin
|
||||
- ltc-litecoin
|
||||
- eth-ethereum
|
||||
- xmr-monero
|
||||
- bad-badcoin
|
||||
commodity:
|
||||
- gc=f
|
||||
- si=f
|
||||
- bz=f
|
||||
Loading…
Add table
Add a link
Reference in a new issue