Browse Source

minor cleanups

The MMGen Project 2 years ago
parent
commit
3fd9c971bf
4 changed files with 86 additions and 56 deletions
  1. 16 7
      README.md
  2. 51 36
      mmgen_node_tools/Ticker.py
  3. 18 12
      mmgen_node_tools/main_ticker.py
  4. 1 1
      test/test_py_d/ts_misc.py

+ 16 - 7
README.md

@@ -12,10 +12,10 @@ First, install [MMGen][6].
 
 
 Then,
 Then,
 
 
-    $ git clone https://github.com/mmgen/mmgen-node-tools
-    $ cd mmgen-node-tools
-    $ python3 -m build --no-isolation
-    $ python3 -m pip install --user dist/*.whl
+	$ git clone https://github.com/mmgen/mmgen-node-tools
+	$ cd mmgen-node-tools
+	$ python3 -m build --no-isolation
+	$ python3 -m pip install --user dist/*.whl
 
 
 Also make sure that `~/.local/bin` is in `PATH`.
 Also make sure that `~/.local/bin` is in `PATH`.
 
 
@@ -24,9 +24,18 @@ Also make sure that `~/.local/bin` is in `PATH`.
 *NOTE: the tests require that the MMGen and MMGen Node Tools repositories be
 *NOTE: the tests require that the MMGen and MMGen Node Tools repositories be
 located in the same directory.*
 located in the same directory.*
 
 
-    $ test/init.sh
-    $ test/test-release.sh -A  # BTC-only testing
-    $ test/test-release.sh     # Full testing
+Initialize the test framework (must be run at least once after cloning, and
+possibly again after a pull if tests have been updated):
+
+	$ test/init.sh
+
+BTC-only testing:
+
+	$ test/test-release.sh -A
+
+Full testing:
+
+	$ test/test-release.sh
 
 
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 

+ 51 - 36
mmgen_node_tools/Ticker.py

@@ -87,11 +87,11 @@ def gen_data(data):
 	usr_wants = {
 	usr_wants = {
 		'id': (
 		'id': (
 			{a.id for a in usr_assets if a.id} -
 			{a.id for a in usr_assets if a.id} -
-			{a.id for a in usr_assets if a.amount and a.id} - {'usd-us-dollar'} )
+			{a.id for a in usr_assets if a.rate and a.id} - {'usd-us-dollar'} )
 		,
 		,
 		'symbol': (
 		'symbol': (
 			{a.symbol for a in usr_assets if not a.id} -
 			{a.symbol for a in usr_assets if not a.id} -
-			{a.symbol for a in usr_assets if a.amount} - {'USD'} ),
+			{a.symbol for a in usr_assets if a.rate} - {'USD'} ),
 	}
 	}
 
 
 	found = { 'id': set(), 'symbol': set() }
 	found = { 'id': set(), 'symbol': set() }
@@ -114,7 +114,7 @@ def gen_data(data):
 			break
 			break
 
 
 	for asset in (cfg.usr_rows + cfg.usr_columns):
 	for asset in (cfg.usr_rows + cfg.usr_columns):
-		if asset.amount:
+		if asset.rate:
 			"""
 			"""
 			User-supplied rate overrides rate from source data.
 			User-supplied rate overrides rate from source data.
 			"""
 			"""
@@ -122,8 +122,8 @@ def gen_data(data):
 			yield ( _id, {
 			yield ( _id, {
 				'symbol': asset.symbol,
 				'symbol': asset.symbol,
 				'id': _id,
 				'id': _id,
-				'price_usd': str(Decimal(1/asset.amount)),
-				'price_btc': str(Decimal(1/asset.amount/btcusd)),
+				'price_usd': str(Decimal(1/asset.rate)),
+				'price_btc': str(Decimal(1/asset.rate/btcusd)),
 				'last_updated': int(now),
 				'last_updated': int(now),
 			})
 			})
 
 
@@ -280,47 +280,62 @@ def main(cfg_parm,cfg_in_parm):
 def make_cfg(cmd_args,cfg_in):
 def make_cfg(cmd_args,cfg_in):
 
 
 	def get_rows_from_cfg(add_data=None):
 	def get_rows_from_cfg(add_data=None):
-		def create_row(e):
-			return asset_tuple(e.split('-')[0].upper(),e)
 		def gen():
 		def gen():
 			for n,(k,v) in enumerate(cfg_in.cfg['assets'].items()):
 			for n,(k,v) in enumerate(cfg_in.cfg['assets'].items()):
 				yield(k)
 				yield(k)
 				if add_data and k in add_data:
 				if add_data and k in add_data:
 					v += tuple(add_data[k])
 					v += tuple(add_data[k])
 				for e in v:
 				for e in v:
-					yield(create_row(e))
+					yield parse_asset_id(e,True)
 		return tuple(gen())
 		return tuple(gen())
 
 
-	def parse_asset_tuple(s):
-		sym,id = (s.split('-')[0],s) if '-' in s else (s,None)
-		return asset_tuple( sym.upper(), id.lower() if id else None )
-
-	def parse_asset_triplet(s,reverse_ok=False):
-		ss = s.split(':')
-		return asset_triplet(
-			*parse_asset_tuple(s if len(ss) == 1 else ss[0]),
-			(
-				None if len(ss) == 1 else
-				1 / Decimal(ss[1][:-1]) if reverse_ok and ss[1].lower().endswith('r') else
-				Decimal(ss[1])
-			))
+	def parse_asset_id(s,require_label=False):
+		sym,label = (*s.split('-',1),None)[:2]
+		if require_label and not label:
+			die(1,f'{s!r}: asset label is missing')
+		return asset_tuple( sym.upper(), (s.lower() if label else None) )
 
 
 	def parse_usr_asset_arg(s):
 	def parse_usr_asset_arg(s):
-		return tuple(parse_asset_triplet(ss,reverse_ok=True) for ss in s.split(',')) if s else ()
+		"""
+		asset_id[:rate]
+		"""
+		def parse_parm(s):
+			ss = s.split(':')
+			assert len(ss) in (1,2), f'{s}: malformed argument'
+			asset_id,rate = (*ss,None)[:2]
+			parsed_id = parse_asset_id(asset_id)
+
+			return asset_data(
+				symbol = parsed_id.symbol,
+				id     = parsed_id.id,
+				amount = None,
+				rate   = (
+					None if rate is None else
+					1 / Decimal(rate[:-1]) if rate.lower().endswith('r') else
+					Decimal(rate) ))
+
+		return tuple(parse_parm(s2) for s2 in s.split(',')) if s else ()
 
 
 	def parse_query_arg(s):
 	def parse_query_arg(s):
+		"""
+		asset_id:amount[:to_asset_id[:to_amount]]
+		"""
+		def parse_query_asset(asset_id,amount):
+			parsed_id = parse_asset_id(asset_id)
+			return asset_data(
+				symbol = parsed_id.symbol,
+				id     = parsed_id.id,
+				amount = None if amount is None else Decimal(amount),
+				rate   = None )
+
 		ss = s.split(':')
 		ss = s.split(':')
-		if len(ss) == 2:
-			return query_tuple(
-				asset    = parse_asset_triplet(s),
-				to_asset = None )
-		elif len(ss) in (3,4):
-			return query_tuple(
-				asset    = parse_asset_triplet(':'.join(ss[:2])),
-				to_asset = parse_asset_triplet(':'.join(ss[2:])),
-			)
-		else:
-			die(1,f'{s}: malformed argument')
+		assert len(ss) in (2,3,4), f'{s}: malformed argument'
+		asset_id,amount,to_asset_id,to_amount = (*ss,None,None)[:4]
+
+		return query_tuple(
+			asset = parse_query_asset(asset_id,amount),
+			to_asset = parse_query_asset(to_asset_id,to_amount) if to_asset_id else None
+		)
 
 
 	def gen_uniq(obj_list,key,preload=None):
 	def gen_uniq(obj_list,key,preload=None):
 		found = set([getattr(obj,key) for obj in preload if hasattr(obj,key)] if preload else ())
 		found = set([getattr(obj,key) for obj in preload if hasattr(obj,key)] if preload else ())
@@ -339,7 +354,7 @@ def make_cfg(cmd_args,cfg_in):
 
 
 	def get_portfolio_assets(ret=()):
 	def get_portfolio_assets(ret=()):
 		if cfg_in.portfolio and opt.portfolio:
 		if cfg_in.portfolio and opt.portfolio:
-			ret = tuple( asset_tuple(e.split('-')[0].upper(),e) for e in cfg_in.portfolio )
+			ret = (parse_asset_id(e,True) for e in cfg_in.portfolio)
 		return ( 'portfolio', tuple(e for e in ret if (not opt.btc) or e.symbol == 'BTC') )
 		return ( 'portfolio', tuple(e for e in ret if (not opt.btc) or e.symbol == 'BTC') )
 
 
 	def get_portfolio():
 	def get_portfolio():
@@ -357,7 +372,7 @@ def make_cfg(cmd_args,cfg_in):
 	def create_rows():
 	def create_rows():
 		rows = (
 		rows = (
 			('trade_pair',) + query if (query and query.to_asset) else
 			('trade_pair',) + query if (query and query.to_asset) else
-			('bitcoin',parse_asset_tuple('btc-bitcoin')) if opt.btc else
+			('bitcoin',parse_asset_id('btc-bitcoin')) if opt.btc else
 			get_rows_from_cfg( add_data={'fiat':['usd-us-dollar']} if opt.add_columns else None )
 			get_rows_from_cfg( add_data={'fiat':['usd-us-dollar']} if opt.add_columns else None )
 		)
 		)
 
 
@@ -385,7 +400,7 @@ def make_cfg(cmd_args,cfg_in):
 		'portfolio' ])
 		'portfolio' ])
 
 
 	query_tuple   = namedtuple('query',['asset','to_asset'])
 	query_tuple   = namedtuple('query',['asset','to_asset'])
-	asset_triplet = namedtuple('asset_triplet',['symbol','id','amount'])
+	asset_data    = namedtuple('asset_data',['symbol','id','amount','rate'])
 	asset_tuple   = namedtuple('asset_tuple',['symbol','id'])
 	asset_tuple   = namedtuple('asset_tuple',['symbol','id'])
 
 
 	usr_rows    = parse_usr_asset_arg(opt.add_rows)
 	usr_rows    = parse_usr_asset_arg(opt.add_rows)

+ 18 - 12
mmgen_node_tools/main_ticker.py

@@ -67,22 +67,28 @@ user’s portfolio, while trading mode displays the price of a given quantity
 of an asset in relation to other assets, optionally comparing an offered
 of an asset in relation to other assets, optionally comparing an offered
 price to the spot price.
 price to the spot price.
 
 
-ASSETS consist of either a symbol (e.g. ‘xmr’) or full ID consisting of
-symbol plus label (e.g. ‘xmr-monero’).  In cases where the symbol is
-ambiguous, the full ID must be used.  Examples:
+ASSETS consist of either a symbol (e.g. ‘xmr’) or full ID (see --list-ids)
+consisting of symbol plus label (e.g. ‘xmr-monero’).  In cases where the
+symbol is ambiguous, the full ID must be used.  Examples:
 
 
   chf                   - specify asset by symbol
   chf                   - specify asset by symbol
   chf-swiss-franc-token - same as above, but use full ID instead of symbol
   chf-swiss-franc-token - same as above, but use full ID instead of symbol
 
 
-ASSET SPECIFIERS consist of an ASSET followed by an optional colon and USD
-rate.  If the asset is not in the source data (see --list-ids), the label
-part of the ID may be arbitrarily chosen by the user.  When the letter ‘r’
-is appended to the USD rate, the rate is reversed, i.e. treated as ‘USD per
-asset’ instead of ‘asset per USD’.  Asset specifier examples:
+ASSET SPECIFIERS have the following format:
 
 
-  inr:79.5              - INR is not in the source data, so supply USD rate
-  inr-indian-rupee:79.5 - same as above, but add an arbitrary label
-  omr-omani-rial:2.59r  - OMR is pegged to USD with fixed value of 2.59 USD
+  ASSET[:RATE]
+
+If the asset referred to by ASSET is not in the source data (see --list-ids),
+an arbitrarily chosen label may be used.  RATE is the USD exchange rate of
+the asset.  When RATE is postfixed with the letter ‘r’, its meaning is
+reversed, i.e. interpreted as ‘ASSET/USD’ instead of ‘USD/ASSET’.  Asset
+specifier examples:
+
+  inr:79.5               - INR is not in the source data, so supply rate of
+                           79.5 INR to the Dollar (USD/INR)
+  inr:0.01257r           - same as above, but use reverse rate (INR/USD)
+  inr-indian-rupee:79.5  - same as first example, but add an arbitrary label
+  omr-omani-rial:2.59r   - Omani Rial is pegged to the Dollar at 2.59 USD
 
 
 A TRADE_SPECIFIER is a single argument in the format:
 A TRADE_SPECIFIER is a single argument in the format:
 
 
@@ -137,7 +143,7 @@ $ mmnode-ticker
 # Display BTC price only:
 # Display BTC price only:
 $ mmnode-ticker --btc
 $ mmnode-ticker --btc
 
 
-# Wide display, add EUR and OMR columns, OMRUSD rate, extra precision and
+# Wide display, add EUR and OMR columns, OMR/USD rate, extra precision and
 # proxy:
 # proxy:
 $ mmnode-ticker -w -c eur,omr-omani-rial:2.59r -e2 -x http://vpnhost:8118
 $ mmnode-ticker -w -c eur,omr-omani-rial:2.59r -e2 -x http://vpnhost:8118
 
 

+ 1 - 1
test/test_py_d/ts_misc.py

@@ -280,6 +280,6 @@ class TestSuiteScripts(TestSuiteBase):
 				r'EUR \(EURO TOKEN\) = 1.0186 USD ' +
 				r'EUR \(EURO TOKEN\) = 1.0186 USD ' +
 				r'OMR \(OMANI RIAL\) = 2.5900 USD',
 				r'OMR \(OMANI RIAL\) = 2.5900 USD',
 				'USD EUR OMR BTC CHG_7d CHG_24h UPDATED',
 				'USD EUR OMR BTC CHG_7d CHG_24h UPDATED',
-				'BITCOIN',
+				r'BITCOIN 23,250.77 22,826.6890 8,977.1328 1.00000000 \+11.15 \+0.89 10 minutes ago',
 				'OMANI RIAL 2.59 2.5428 1.0000 0.00011139 -- -- just now'
 				'OMANI RIAL 2.59 2.5428 1.0000 0.00011139 -- -- just now'
 			])
 			])