From fd318909c21d602701c2a219bedb1aafa8ffb0d8 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Mon, 25 Sep 2023 15:53:02 +0000 Subject: [PATCH] mmnode-ticker: retrieve financial data from Yahoo Finance --- mmgen_node_tools/Ticker.py | 96 +++++++++++++++++++++++++-- mmgen_node_tools/data/ticker-cfg.yaml | 23 ++++--- mmgen_node_tools/data/version | 2 +- mmgen_node_tools/main_ticker.py | 65 +++++++++++------- setup.cfg | 3 +- test/ref/ticker/ticker-cfg.yaml | 16 ++--- test/ref/ticker/ticker-finance.json | 1 + test/ref/ticker/ticker.json | 2 +- test/test_py_d/ts_misc.py | 48 ++++++-------- 9 files changed, 179 insertions(+), 77 deletions(-) create mode 100644 test/ref/ticker/ticker-finance.json diff --git a/mmgen_node_tools/Ticker.py b/mmgen_node_tools/Ticker.py index cafd407..e6f0650 100755 --- a/mmgen_node_tools/Ticker.py +++ b/mmgen_node_tools/Ticker.py @@ -46,6 +46,7 @@ class DataSource: sources = { 'cc': 'coinpaprika', + 'fi': 'yahooquery' } class base: @@ -199,6 +200,69 @@ class DataSource: id = (s.lower() if label else None), source = 'cc' ) + class yahooquery(base): + + desc = 'Yahoo Finance' + api_host = 'finance.yahoo.com' + ratelimit = 30 + net_data_type = 'python' + has_verbose = False + asset_id_pat = r'^\^.*|.*=[xf]$' + + @staticmethod + def get_id(sym,data): + return sym.lower() + + @staticmethod + def conv_data(sym,data,btcusd): + price_usd = Decimal( data['regularMarketPrice']['raw'] ) + return { + 'id': sym, + 'name': data['shortName'], + 'symbol': sym.upper(), + 'price_usd': str(price_usd), + 'price_btc': str(price_usd / btcusd), + 'percent_change_7d': None, + 'percent_change_24h': data['regularMarketChangePercent']['raw'] * 100, + 'last_updated': data['regularMarketTime'], + } + + def rate_limit_errmsg(self,elapsed): + return f'Rate limit exceeded! Retry in {self.timeout-elapsed} seconds, or use --cached-data' + + @property + def json_fn(self): + return os.path.join( cfg.cachedir, 'ticker-finance.json' ) + + @property + def timeout(self): + return 5 if gcfg.test_suite else self.ratelimit + + def get_data_from_network(self): + + arg = [r.symbol for r in cfg.rows if isinstance(r,tuple) and r.source == 'fi'] + + kwargs = { 'formatted': True, 'proxies': { 'https': cfg.proxy2 } } + + if gcfg.test_suite: + kwargs.update({ 'timeout': 1, 'retry': 0 }) + + if gcfg.testing: + Msg('\nyahooquery.Ticker(\n {},\n {}\n)'.format( + arg, + fmt_dict(kwargs,fmt='kwargs') )) + return + + from yahooquery import Ticker + return Ticker(arg,**kwargs).price + + @staticmethod + def parse_asset_id(s,require_label): + return asset_tuple( + symbol = s.upper(), + id = s.lower(), + source = 'fi' ) + def assets_list_gen(cfg_in): for k,v in cfg_in.cfg['assets'].items(): yield('') @@ -271,6 +335,23 @@ def gen_data(data): btcusd = Decimal(d['price_usd']) break + get_id = src_cls['fi'].get_id + conv_func = src_cls['fi'].conv_data + + for k,v in data['fi'].items(): + id = get_id(k,v) + if wants['id']: + if id in wants['id']: + if id in found['id']: + die(1,dup_sym_errmsg(id)) + yield ( id, conv_func(id,v,btcusd) ) + found['id'].add(id) + wants['id'].remove(id) + if id in usr_rate_assets_want['id']: + rate_assets[k] = conv_func(id,v,btcusd) # NB: using symbol instead of ID for key + else: + break + for k in ('id','symbol'): for d in data['cc']: if wants[k]: @@ -379,7 +460,7 @@ def make_cfg(): return tuple(gen()) def parse_asset_id(s,require_label=False): - return src_cls['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 parse_usr_asset_arg(key,use_cf_file=False): """ @@ -489,11 +570,13 @@ def make_cfg(): 'add_prec', 'cachedir', 'proxy', + 'proxy2', 'portfolio' ]) global cfg_in,src_cls,cfg src_cls = { k: getattr(DataSource,v) for k,v in DataSource.sources.items() } + fi_pat = src_cls['fi'].asset_id_pat cmd_args = gcfg._args cfg_in = get_cfg_in() @@ -514,6 +597,7 @@ def make_cfg(): proxy = get_proxy('proxy') proxy = None if proxy == 'none' else proxy + proxy2 = get_proxy('proxy2') cfg = cfg_tuple( rows = create_rows(), @@ -526,6 +610,7 @@ def make_cfg(): add_prec = parse_add_precision(gcfg.add_precision), cachedir = gcfg.cachedir or cfg_in.cfg.get('cachedir') or dfl_cachedir, proxy = proxy, + proxy2 = None if proxy2 == 'none' else '' if proxy2 == '' else (proxy2 or proxy), portfolio = get_portfolio() if cfg_in.portfolio and gcfg.portfolio and not query else None ) @@ -541,9 +626,12 @@ def get_cfg_in(): cfg = cfg_data or { 'assets': { 'coin': [ 'btc-bitcoin', 'eth-ethereum', 'xmr-monero' ], - 'commodity': [ 'xau-gold-spot-token', 'xag-silver-spot-token', 'xbr-brent-crude-oil-spot' ], - 'fiat': [ 'gbp-pound-sterling-token', 'eur-euro-token' ], - 'index': [ 'dj30-dow-jones-30-token', 'spx-sp-500', 'ndx-nasdaq-100-token' ], + # gold futures, silver futures, Brent futures + 'commodity': [ 'gc=f', 'si=f', 'bz=f' ], + # Pound Sterling, Euro, Swiss Franc + 'fiat': [ 'gbpusd=x', 'eurusd=x', 'chfusd=x' ], + # Dow Jones Industrials, Nasdaq 100, S&P 500 + 'index': [ '^dji', '^ixic', '^gspc' ], }, 'proxy': 'http://vpn-gw:8118' }, diff --git a/mmgen_node_tools/data/ticker-cfg.yaml b/mmgen_node_tools/data/ticker-cfg.yaml index 6589bfc..6344445 100644 --- a/mmgen_node_tools/data/ticker-cfg.yaml +++ b/mmgen_node_tools/data/ticker-cfg.yaml @@ -3,10 +3,16 @@ ### See the curl manpage for supported --proxy parameters ### For a direct connection, leave the right-hand side blank proxy: http://vpn-gw:8118 +# proxy2: http://gw2:8118 ### Override the default cache directory (~/.cache/mmgen-node-tools): cachedir: +### Additional asset columns: +# add_columns: +# - cnhusd=x # Yuan +# - 6j=f # Yen futures + ### Asset rows ### Asset labels are arbitrary strings. Use as many or few as you wish. ### Invoke ‘mmnode-ticker --list-ids’ for a full list of supported asset IDs. @@ -19,13 +25,14 @@ assets: - ada-cardano - bnb-binance-coin commodity: - - xau-gold-spot-token - - xag-silver-spot-token - - xbr-brent-crude-oil-spot + - gc=f # gold futures + - si=f # silver futures + - bz=f # Brent futures fiat: - - gbp-pound-sterling-token - - eur-euro-token + - gbpusd=x # Pound Sterling + - eurusd=x # Euro + - chfusd=x # Swiss Franc index: - - dj30-dow-jones-30-token - - spx-sp-500 - - ndx-nasdaq-100-token + - ^dji # Dow Jones Industrials + - ^ixic # Nasdaq 100 + - ^gspc # S&P 500 diff --git a/mmgen_node_tools/data/version b/mmgen_node_tools/data/version index b473ce1..0c84a84 100644 --- a/mmgen_node_tools/data/version +++ b/mmgen_node_tools/data/version @@ -1 +1 @@ -3.2.dev0 +3.2.dev1 diff --git a/mmgen_node_tools/main_ticker.py b/mmgen_node_tools/main_ticker.py index 6553d2a..f329e03 100755 --- a/mmgen_node_tools/main_ticker.py +++ b/mmgen_node_tools/main_ticker.py @@ -47,7 +47,7 @@ opts_data = { -r, --add-rows=LIST Add rows for asset specifiers in LIST (comma-separated, see ASSET SPECIFIERS below). Can also be used to supply a USD exchange rate for missing assets. --t, --testing Print command to be executed to stdout and exit +-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 -v, --verbose Be more verbose @@ -55,6 +55,8 @@ opts_data = { -x, --proxy=P Connect via proxy ‘P’. Set to the empty string to completely disable or ‘none’ to allow override from environment. Consult the curl manpage for --proxy usage. +-X, --proxy2=P Alternate proxy for non-crypto financial data. Defaults + to value of --proxy """, 'notes': """ @@ -69,10 +71,15 @@ price to the spot price. 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: +symbol is ambiguous, the full ID must be used. For Yahoo Finance assets +the symbol and ID are identical: - chf - specify asset by symbol - chf-swiss-franc-token - same as above, but use full ID instead of symbol +Examples: + + ltc - specify asset by symbol + ltc-litecoin - same as above, but use full ID instead of symbol + ^dji - Dow Jones Industrial Average (Yahoo) + gc=f - gold futures (Yahoo) ASSET SPECIFIERS have the following format: @@ -89,7 +96,8 @@ postfixed with the letter ‘r’, its meaning is reversed, i.e. interpreted as 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 - bgn-bg-lev:0.5113r:eur - Bulgarian Lev is pegged to the Euro at 0.5113 EUR + bgn-bulgarian-lev:0.5113r:eurusd=x + - Bulgarian Lev is pegged to the Euro at 0.5113 EUR A TRADE_SPECIFIER is a single argument in the format: @@ -99,8 +107,8 @@ A TRADE_SPECIFIER is a single argument in the format: xmr:17.34 - price of 17.34 XMR in all configured assets xmr-monero:17.34 - same as above, but with full ID - xmr:17.34:eur - price of 17.34 XMR in EUR only - xmr:17.34:eur:2800 - commission on an offer of 17.34 XMR for 2800 EUR + xmr:17.34:eurusd=x - price of 17.34 XMR in EUR only + xmr:17.34:eurusd=x:2800 - commission on an offer of 17.34 XMR for 2800 EUR TO_AMOUNT, if included, is used to calculate the percentage difference or commission on an offer compared to the spot price. @@ -112,28 +120,34 @@ A TRADE_SPECIFIER is a single argument in the format: PROXY NOTE -The remote server used to obtain the price data, {cc.api_host!r}, blocks -Tor behind a Captcha wall, so a Tor proxy cannot be used directly. If you’re -concerned about privacy, connect via a VPN, or better yet, VPN over Tor. Then -set up an HTTP proxy (e.g. Privoxy) on the VPN’ed host and set the ‘proxy’ -option in the config file or --proxy on the command line accordingly. Or run -the script directly on the VPN’ed host with ’proxy’ or --proxy set to the -null string. +The remote server used to obtain the crypto price data, {cc.api_host}, +blocks Tor behind a Captcha wall, so a Tor proxy cannot be used directly. +If you’re concerned about privacy, connect via a VPN, or better yet, VPN over +Tor. Then set up an HTTP proxy (e.g. Privoxy) on the VPN’ed host and set the +‘proxy’ option in the config file or --proxy on the command line accordingly. +Or run the script directly on the VPN’ed host with ’proxy’ or --proxy set to +the null string. Alternatively, you may download the JSON source data in a Tor-proxied browser -from ‘{cc.api_url}’, save it as ‘ticker.json’ in your -configured cache directory, and run the script with the --cached-data option. +from {cc.api_url}, save it as ‘ticker.json’ in your +configured cache directory and run the script with the --cached-data option. + +Financial data is obtained from {fi.desc}, which currently allows Tor. RATE LIMITING NOTE -To protect user privacy, all filtering and processing of data is performed -client side so that the remote server does not know which assets are being -examined. This means that data for ALL available assets (currently over 4000) -is fetched with each invocation of the script. A rate limit of {cc.ratelimit} seconds -between calls is thus imposed to prevent abuse of the remote server. When the ---btc option is in effect, this limit is reduced to {cc.btc_ratelimit} seconds. To bypass the -rate limit entirely, use --cached-data. +To protect user privacy, all filtering and processing of cryptocurrency data +is performed client side so that the remote server does not know which assets +are being examined. This means that data for ALL available crypto assets +(currently over 8000) is fetched with each invocation of the script. A rate +limit of {cc.ratelimit} seconds between calls is thus imposed to prevent abuse of the +remote server. When the --btc option is in effect, this limit is reduced to +{cc.btc_ratelimit} seconds. To bypass the rate limit entirely, use --cached-data. + +Note that financial data obtained from {fi.api_host} is filtered in the +request, which has privacy implications. The rate limit for financial data +is {fi.ratelimit} seconds. EXAMPLES @@ -146,10 +160,10 @@ $ mmnode-ticker --btc # Wide display, add EUR and OMR columns, OMR/USD rate, extra precision and # proxy: -$ mmnode-ticker -w -c eur,omr-omani-rial:2.59r -e2 -x http://vpnhost:8118 +$ mmnode-ticker -w -c eurusd=x,omr-omani-rial:2.59r -e2 -x http://vpnhost:8118 # Wide display, elapsed update time, add EUR, BGN columns and BGN/EUR rate: -$ mmnode-ticker -wE -c eur,bgn-bulgarian-lev:0.5113r:eur +$ mmnode-ticker -wE -c eurusd=x,bgn-bulgarian-lev:0.5113r:eurusd=x # Wide display, use cached data from previous network query, show portfolio # (see above), pipe output to pager, add DOGE row: @@ -193,6 +207,7 @@ To add a portfolio, edit the file cfg = os.path.relpath(cfg_in.cfg_file,start=homedir), pf_cfg = os.path.relpath(cfg_in.portfolio_file,start=homedir), cc = src_cls['cc'](), + fi = src_cls['fi'](), ) } } diff --git a/setup.cfg b/setup.cfg index 0cdbed1..9539a29 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,7 +23,8 @@ python_requires = >=3.7 include_package_data = True install_requires = - mmgen>=13.3.dev44 + mmgen>=14.0.dev2 + yahooquery packages = mmgen_node_tools diff --git a/test/ref/ticker/ticker-cfg.yaml b/test/ref/ticker/ticker-cfg.yaml index 504a7fb..4b40a43 100644 --- a/test/ref/ticker/ticker-cfg.yaml +++ b/test/ref/ticker/ticker-cfg.yaml @@ -12,13 +12,13 @@ assets: - ada-cardano - algo-algorand commodity: - - xau-gold-spot-token - - xag-silver-spot-token - - xbr-brent-crude-oil-spot + - gc=f # gold futures + - si=f # silver futures + - bz=f # Brent futures fiat: - - chf-swiss-franc-token - - eur-euro-token + - chfusd=x # Swiss Franc + - eurusd=x # Euro index: - - dj30-dow-jones-30-token - - spx-sp-500 - - ndx-nasdaq-100-token + - ^dji # Dow Jones Industrials + - ^ixic # Nasdaq 100 + - ^gspc # S&P 500 diff --git a/test/ref/ticker/ticker-finance.json b/test/ref/ticker/ticker-finance.json new file mode 100644 index 0000000..ac0af29 --- /dev/null +++ b/test/ref/ticker/ticker-finance.json @@ -0,0 +1 @@ +{"GC=F":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.0015419408,"fmt":"-0.15%"},"regularMarketChange":{"raw":-3,"fmt":"-3.00"},"regularMarketTime":1659385900,"priceHint":{"raw":2,"fmt":"2","longFmt":"2"},"regularMarketPrice":{"raw":1942.6,"fmt":"1,942.60"},"regularMarketDayHigh":{"raw":1946.8,"fmt":"1,946.80"},"regularMarketDayLow":{"raw":1940.1,"fmt":"1,940.10"},"regularMarketVolume":{"raw":39539,"fmt":"39.54k","longFmt":"39,539.00"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":1945.6,"fmt":"1,945.60"},"regularMarketSource":"DELAYED","regularMarketOpen":{"raw":1944.7,"fmt":"1,944.70"},"strikePrice":{},"openInterest":{},"exchange":"CMX","exchangeName":"COMEX","exchangeDataDelayedBy":10,"marketState":"REGULAR","quoteType":"FUTURE","symbol":"GC=F","underlyingSymbol":null,"shortName":"Gold Dec 23","longName":null,"currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"SI=F":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.0014259518,"fmt":"-0.14%"},"regularMarketChange":{"raw":-0.034000397,"fmt":"-0.03"},"regularMarketTime":1659385900,"priceHint":{"raw":2,"fmt":"2","longFmt":"2"},"regularMarketPrice":{"raw":23.81,"fmt":"23.81"},"regularMarketDayHigh":{"raw":23.925,"fmt":"23.92"},"regularMarketDayLow":{"raw":23.67,"fmt":"23.67"},"regularMarketVolume":{"raw":11819,"fmt":"11.82k","longFmt":"11,819.00"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":23.844,"fmt":"23.84"},"regularMarketSource":"DELAYED","regularMarketOpen":{"raw":23.81,"fmt":"23.81"},"strikePrice":{},"openInterest":{},"exchange":"CMX","exchangeName":"COMEX","exchangeDataDelayedBy":10,"marketState":"REGULAR","quoteType":"FUTURE","symbol":"SI=F","underlyingSymbol":null,"shortName":"Silver Dec 23","longName":null,"currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"BZ=F":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":0.004610275,"fmt":"0.46%"},"regularMarketChange":{"raw":0.4300003,"fmt":"0.43"},"regularMarketTime":1659385900,"priceHint":{"raw":2,"fmt":"2","longFmt":"2"},"regularMarketPrice":{"raw":93.7,"fmt":"93.70"},"regularMarketDayHigh":{"raw":94.25,"fmt":"94.25"},"regularMarketDayLow":{"raw":93.24,"fmt":"93.24"},"regularMarketVolume":{"raw":2853,"fmt":"2.85k","longFmt":"2,853.00"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":93.27,"fmt":"93.27"},"regularMarketSource":"DELAYED","regularMarketOpen":{"raw":93.75,"fmt":"93.75"},"strikePrice":{},"openInterest":{},"exchange":"NYM","exchangeName":"NY Mercantile","exchangeDataDelayedBy":10,"marketState":"REGULAR","quoteType":"FUTURE","symbol":"BZ=F","underlyingSymbol":null,"shortName":"Brent Crude Oil Last Day Financ","longName":null,"currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"GBPUSD=X":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.00045271934,"fmt":"-0.0453%"},"regularMarketChange":{"raw":-0.0005540848,"fmt":"-0.0006"},"regularMarketTime":1659385900,"priceHint":{"raw":4,"fmt":"4","longFmt":"4"},"regularMarketPrice":{"raw":1.223481,"fmt":"1.2235"},"regularMarketDayHigh":{"raw":1.2263919,"fmt":"1.2264"},"regularMarketDayLow":{"raw":1.2213293,"fmt":"1.2213"},"regularMarketVolume":{"raw":0,"fmt":null,"longFmt":"0.0000"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":1.2240351,"fmt":"1.2240"},"regularMarketSource":"DELAYED","regularMarketOpen":{"raw":1.2240951,"fmt":"1.2241"},"strikePrice":{},"openInterest":{},"exchange":"CCY","exchangeName":"CCY","exchangeDataDelayedBy":0,"marketState":"REGULAR","quoteType":"CURRENCY","symbol":"GBPUSD=X","underlyingSymbol":null,"shortName":"GBP/USD","longName":"GBP/USD","currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"EURUSD=X":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.0005321096,"fmt":"-0.0532%"},"regularMarketChange":{"raw":-0.00056660175,"fmt":"-0.0006"},"regularMarketTime":1659385900,"priceHint":{"raw":4,"fmt":"4","longFmt":"4"},"regularMarketPrice":{"raw":1.0641694,"fmt":"1.0642"},"regularMarketDayHigh":{"raw":1.0658708,"fmt":"1.0659"},"regularMarketDayLow":{"raw":1.0626993,"fmt":"1.0627"},"regularMarketVolume":{"raw":0,"fmt":null,"longFmt":"0.0000"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":1.064736,"fmt":"1.0647"},"regularMarketSource":"DELAYED","regularMarketOpen":{"raw":1.064736,"fmt":"1.0647"},"strikePrice":{},"openInterest":{},"exchange":"CCY","exchangeName":"CCY","exchangeDataDelayedBy":0,"marketState":"REGULAR","quoteType":"CURRENCY","symbol":"EURUSD=X","underlyingSymbol":null,"shortName":"EUR/USD","longName":"EUR/USD","currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"CHFUSD=X":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.0028495365,"fmt":"-0.2850%"},"regularMarketChange":{"raw":-0.0031440258,"fmt":"-0.0031"},"regularMarketTime":1659385900,"priceHint":{"raw":4,"fmt":"4","longFmt":"4"},"regularMarketPrice":{"raw":1.1002069,"fmt":"1.1002"},"regularMarketDayHigh":{"raw":1.1046062,"fmt":"1.1046"},"regularMarketDayLow":{"raw":1.0982735,"fmt":"1.0983"},"regularMarketVolume":{"raw":0,"fmt":null,"longFmt":"0.0000"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":1.1033509,"fmt":"1.1034"},"regularMarketSource":"DELAYED","regularMarketOpen":{"raw":1.1043622,"fmt":"1.1044"},"strikePrice":{},"openInterest":{},"exchange":"CCY","exchangeName":"CCY","exchangeDataDelayedBy":0,"marketState":"REGULAR","quoteType":"CURRENCY","symbol":"CHFUSD=X","underlyingSymbol":null,"shortName":"CHF/USD","longName":"CHF/USD","currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"^DJI":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.0031276005,"fmt":"-0.31%"},"regularMarketChange":{"raw":-106.55859,"fmt":"-106.56"},"regularMarketTime":1659385900,"priceHint":{"raw":2,"fmt":"2","longFmt":"2"},"regularMarketPrice":{"raw":33963.84,"fmt":"33,963.84"},"regularMarketDayHigh":{"raw":34156.15,"fmt":"34,156.15"},"regularMarketDayLow":{"raw":33947.24,"fmt":"33,947.24"},"regularMarketVolume":{"raw":271273859,"fmt":"271.27M","longFmt":"271,273,859.00"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":34070.4,"fmt":"34,070.40"},"regularMarketSource":"FREE_REALTIME","regularMarketOpen":{"raw":34077.08,"fmt":"34,077.08"},"strikePrice":{},"openInterest":{},"exchange":"DJI","exchangeName":"DJI","exchangeDataDelayedBy":0,"marketState":"PRE","quoteType":"INDEX","symbol":"^DJI","underlyingSymbol":null,"shortName":"Dow Jones Industrial Average","longName":"Dow Jones Industrial Average","currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"^IXIC":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.00092206284,"fmt":"-0.09%"},"regularMarketChange":{"raw":-12.193359,"fmt":"-12.19"},"regularMarketTime":1659385900,"priceHint":{"raw":2,"fmt":"2","longFmt":"2"},"regularMarketPrice":{"raw":13211.807,"fmt":"13,211.81"},"regularMarketDayHigh":{"raw":13353.22,"fmt":"13,353.22"},"regularMarketDayLow":{"raw":13200.639,"fmt":"13,200.64"},"regularMarketVolume":{"raw":3887623000,"fmt":"3.89B","longFmt":"3,887,623,000.00"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":13224,"fmt":"13,224.00"},"regularMarketSource":"FREE_REALTIME","regularMarketOpen":{"raw":13287.171,"fmt":"13,287.17"},"strikePrice":{},"openInterest":{},"exchange":"NIM","exchangeName":"Nasdaq GIDS","exchangeDataDelayedBy":0,"marketState":"PRE","quoteType":"INDEX","symbol":"^IXIC","underlyingSymbol":null,"shortName":"NASDAQ Composite","longName":"NASDAQ Composite","currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}},"^GSPC":{"maxAge":1,"preMarketChange":{},"preMarketPrice":{},"postMarketChange":{},"postMarketPrice":{},"regularMarketChangePercent":{"raw":-0.0022955984,"fmt":"-0.23%"},"regularMarketChange":{"raw":-9.939941,"fmt":"-9.94"},"regularMarketTime":1659385900,"priceHint":{"raw":2,"fmt":"2","longFmt":"2"},"regularMarketPrice":{"raw":4320.06,"fmt":"4,320.06"},"regularMarketDayHigh":{"raw":4357.4,"fmt":"4,357.40"},"regularMarketDayLow":{"raw":4316.49,"fmt":"4,316.49"},"regularMarketVolume":{"raw":2135953000,"fmt":"2.14B","longFmt":"2,135,953,000.00"},"averageDailyVolume10Day":{},"averageDailyVolume3Month":{},"regularMarketPreviousClose":{"raw":4330,"fmt":"4,330.00"},"regularMarketSource":"FREE_REALTIME","regularMarketOpen":{"raw":4341.74,"fmt":"4,341.74"},"strikePrice":{},"openInterest":{},"exchange":"SNP","exchangeName":"SNP","exchangeDataDelayedBy":0,"marketState":"PRE","quoteType":"INDEX","symbol":"^GSPC","underlyingSymbol":null,"shortName":"S&P 500","longName":"S&P 500","currency":"USD","quoteSourceName":"Delayed Quote","currencySymbol":"$","fromCurrency":null,"toCurrency":null,"lastMarket":null,"volume24Hr":{},"volumeAllCurrencies":{},"circulatingSupply":{},"marketCap":{}}} diff --git a/test/ref/ticker/ticker.json b/test/ref/ticker/ticker.json index 2484e6d..880a666 100644 --- a/test/ref/ticker/ticker.json +++ b/test/ref/ticker/ticker.json @@ -1 +1 @@ -[{"id":"btc-bitcoin","name":"Bitcoin","symbol":"BTC","rank":"1","price_usd":"23250.774053363122","price_btc":"1","volume_24h_usd":"28307579008.4866","market_cap_usd":"444336521633","circulating_supply":"19110612","total_supply":"19110619","max_supply":"21000000","percent_change_1h":"-0.27","percent_change_24h":"0.89","percent_change_7d":"11.15","last_updated":"1659464759"},{"id":"eth-ethereum","name":"Ethereum","symbol":"ETH","rank":"2","price_usd":"1659.6621665887371","price_btc":"0.07146396683507168","volume_24h_usd":"18216561308.363518","market_cap_usd":"202151289827","circulating_supply":"121802674","total_supply":"121802721","max_supply":"","percent_change_1h":"-0.03","percent_change_24h":"1.82","percent_change_7d":"21.42","last_updated":"1659464759"},{"id":"ltc-litecoin","name":"Litecoin","symbol":"LTC","rank":"23","price_usd":"59.013589192027936","price_btc":"0.002541086532993605","volume_24h_usd":"510336800.72056556","market_cap_usd":"4181502638","circulating_supply":"70856606","total_supply":"70856631","max_supply":"84000000","percent_change_1h":"-0.43","percent_change_24h":"0.4","percent_change_7d":"12.79","last_updated":"1659464759"},{"id":"xmr-monero","name":"Monero","symbol":"XMR","rank":"30","price_usd":"158.97302629813817","price_btc":"0.006845274482813666","volume_24h_usd":"78159392.30003875","market_cap_usd":"2886277702","circulating_supply":"18155770","total_supply":"18155768","max_supply":"","percent_change_1h":"0.21","percent_change_24h":"1.21","percent_change_7d":"7.28","last_updated":"1659464759"},{"id":"ada-cardano","name":"Cardano","symbol":"ADA","rank":"8","price_usd":"0.5069722536476557","price_btc":"0.00002182989348696495","volume_24h_usd":"507973898.04662097","market_cap_usd":"17111613980","circulating_supply":"33752565071","total_supply":"34277702082","max_supply":"45000000000","percent_change_1h":"0.05","percent_change_24h":"-0.11","percent_change_7d":"11.68","last_updated":"1659464759"},{"id":"algo-algorand","name":"Algorand","symbol":"ALGO","rank":"33","price_usd":"0.33196893931152616","price_btc":"0.00001429436529121747","volume_24h_usd":"62207779.35759487","market_cap_usd":"2306909784","circulating_supply":"6949173585","total_supply":"7350412337","max_supply":"","percent_change_1h":"-0.06","percent_change_24h":"-0.82","percent_change_7d":"9.69","last_updated":"1659464759"},{"id":"xau-gold-spot-token","name":"Gold Spot Token","symbol":"XAU","rank":"2634","price_usd":"1767.0700000000002","price_btc":"0.07608887785567188","volume_24h_usd":"11881071.852000002","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.33","percent_change_24h":"-0.19","percent_change_7d":"2.89","last_updated":"1659464759"},{"id":"xag-silver-spot-token","name":"Silver Spot Token","symbol":"XAG","rank":"4753","price_usd":"20.0265","price_btc":"0.0008623279849562342","volume_24h_usd":"445379.34674999997","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.61","percent_change_24h":"-1.54","percent_change_7d":"7.49","last_updated":"1659464759"},{"id":"xbr-brent-crude-oil-spot","name":"Brent Crude Oil Spot","symbol":"XBR","rank":"2616","price_usd":"100.39000000000001","price_btc":"0.0043227277062770015","volume_24h_usd":"4527788.105237802","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.89","percent_change_24h":"0.87","percent_change_7d":"1.02","last_updated":"1659464759"},{"id":"chf-swiss-franc-token","name":"Swiss Franc Token","symbol":"CHF","rank":"3234","price_usd":"1.0453383927173951","price_btc":"0.00004501158713651311","volume_24h_usd":"360978.80080814153","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.08","percent_change_24h":"-0.66","percent_change_7d":"0.65","last_updated":"1659464759"},{"id":"eur-euro-token","name":"Euro Token","symbol":"EUR","rank":"5116","price_usd":"1.0185784743417672","price_btc":"0.00004385932256255119","volume_24h_usd":"40587878.087926075","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"0.05","percent_change_24h":"-0.82","percent_change_7d":"0.6","last_updated":"1659464759"},{"id":"gbp-pound-sterling-token","name":"Pound Sterling Token","symbol":"GBP","rank":"3424","price_usd":"1.2181792934946465","price_btc":"0.00005245400321946659","volume_24h_usd":"5428622.322314565","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.06","percent_change_24h":"-0.61","percent_change_7d":"1.29","last_updated":"1659464759"},{"id":"dj30-dow-jones-30-token","name":"Dow Jones 30 Token","symbol":"DJ30","rank":"3192","price_usd":"32546","price_btc":"1.401409462381624","volume_24h_usd":"293564.92","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.1","percent_change_24h":"-0.91","percent_change_7d":"2.5","last_updated":"1659464759"},{"id":"spx-sp-500","name":"S&P 500 Token","symbol":"SPX","rank":"3342","price_usd":"4110.6","price_btc":"0.17699974608449287","volume_24h_usd":"780397.41","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"-0.03","percent_change_24h":"-0.27","percent_change_7d":"4.87","last_updated":"1659464759"},{"id":"ndx-nasdaq-100-token","name":"NASDAQ 100 Token","symbol":"NDX","rank":"5097","price_usd":"12948.199999999999","price_btc":"0.5575410188904857","volume_24h_usd":"11221816.494","market_cap_usd":"","circulating_supply":"","total_supply":"","max_supply":"","percent_change_1h":"0.08","percent_change_24h":"0.04","percent_change_7d":"7.21","last_updated":"1659464759"}] +[{"id":"btc-bitcoin","name":"Bitcoin","symbol":"BTC","rank":"1","price_usd":"23250.774053363122","price_btc":"1","volume_24h_usd":"28307579008.4866","market_cap_usd":"444336521633","circulating_supply":"19110612","total_supply":"19110619","max_supply":"21000000","percent_change_1h":"-0.27","percent_change_24h":"0.89","percent_change_7d":"11.15","last_updated":"1659464759"},{"id":"eth-ethereum","name":"Ethereum","symbol":"ETH","rank":"2","price_usd":"1659.6621665887371","price_btc":"0.07146396683507168","volume_24h_usd":"18216561308.363518","market_cap_usd":"202151289827","circulating_supply":"121802674","total_supply":"121802721","max_supply":"","percent_change_1h":"-0.03","percent_change_24h":"1.82","percent_change_7d":"21.42","last_updated":"1659464759"},{"id":"ltc-litecoin","name":"Litecoin","symbol":"LTC","rank":"23","price_usd":"59.013589192027936","price_btc":"0.002541086532993605","volume_24h_usd":"510336800.72056556","market_cap_usd":"4181502638","circulating_supply":"70856606","total_supply":"70856631","max_supply":"84000000","percent_change_1h":"-0.43","percent_change_24h":"0.4","percent_change_7d":"12.79","last_updated":"1659464759"},{"id":"xmr-monero","name":"Monero","symbol":"XMR","rank":"30","price_usd":"158.97302629813817","price_btc":"0.006845274482813666","volume_24h_usd":"78159392.30003875","market_cap_usd":"2886277702","circulating_supply":"18155770","total_supply":"18155768","max_supply":"","percent_change_1h":"0.21","percent_change_24h":"1.21","percent_change_7d":"7.28","last_updated":"1659464759"},{"id":"ada-cardano","name":"Cardano","symbol":"ADA","rank":"8","price_usd":"0.5069722536476557","price_btc":"0.00002182989348696495","volume_24h_usd":"507973898.04662097","market_cap_usd":"17111613980","circulating_supply":"33752565071","total_supply":"34277702082","max_supply":"45000000000","percent_change_1h":"0.05","percent_change_24h":"-0.11","percent_change_7d":"11.68","last_updated":"1659464759"},{"id":"algo-algorand","name":"Algorand","symbol":"ALGO","rank":"33","price_usd":"0.33196893931152616","price_btc":"0.00001429436529121747","volume_24h_usd":"62207779.35759487","market_cap_usd":"2306909784","circulating_supply":"6949173585","total_supply":"7350412337","max_supply":"","percent_change_1h":"-0.06","percent_change_24h":"-0.82","percent_change_7d":"9.69","last_updated":"1659464759"}] diff --git a/test/test_py_d/ts_misc.py b/test/test_py_d/ts_misc.py index c1e925d..28a9e8d 100755 --- a/test/test_py_d/ts_misc.py +++ b/test/test_py_d/ts_misc.py @@ -87,7 +87,6 @@ class TestSuiteScripts(TestSuiteBase): ('ticker15', 'ticker [--cached-data --wide --btc btc:2:usd:45000]'), ('ticker16', 'ticker [--cached-data --wide --elapsed -c eur,omr-omani-rial:2.59r'), ('ticker17', 'ticker [--cached-data --wide --elapsed -c bgn-bulgarian-lev:0.5113r:eur'), - ('ticker18', 'ticker [--cached-data --wide --elapsed -c eur,bgn-bulgarian-lev:0.5113r:eur-euro-token'), ) } @@ -102,6 +101,7 @@ class TestSuiteScripts(TestSuiteBase): def ticker_setup(self): self.spawn('',msg_only=True) shutil.copy2(os.path.join(refdir,'ticker.json'),self.tmpdir) + shutil.copy2(os.path.join(refdir,'ticker-finance.json'),self.tmpdir) shutil.copy2(os.path.join(refdir,'ticker-btc.json'),self.tmpdir) return 'ok' @@ -123,8 +123,8 @@ class TestSuiteScripts(TestSuiteBase): if not cfg.skipping_deps: t.expect('Creating') t.expect('Creating') - t.expect('proxy host could not be resolved') - t.req_exit_val = 3 + ret = t.expect(['proxy host could not be resolved','ProxyError']) + t.req_exit_val = 3 if ret == 0 else 1 return t def ticker3(self): @@ -138,15 +138,15 @@ class TestSuiteScripts(TestSuiteBase): def ticker4(self): return self.ticker( - ['--wide','--add-columns=eur,inr-indian-rupee:79.5'], + ['--wide','--add-columns=eurusd=x,inr-indian-rupee:79.5'], [ - r'EUR \(EURO TOKEN\) = 1.0186 USD ' + + r'EURUSD=X \(EUR/USD\) = 1.0642 USD ' + r'INR \(INDIAN RUPEE\) = 0.012579 USD', - 'USD EUR INR BTC CHG_7d CHG_24h UPDATED', + 'USD EURUSD=X INR BTC CHG_7d CHG_24h UPDATED', 'BITCOIN', - r'ETHEREUM 1,659.66 1,629.3906 131,943.14 0.07146397 \+21.42 \+1.82', - r'MONERO 158.97 156.0734 12,638.36 0.00684527 \+7.28 \+1.21 2022-08-02 18:25:59', - r'INDIAN RUPEE 0.01 0.0123 1.00 0.00000054 -- --', + r'ETHEREUM 1,659.66 1,559.5846 131,943.14 0.07146397 \+21.42 \+1.82', + r'MONERO 158.97 149.3870 12,638.36 0.00684527 \+7.28 \+1.21 2022-08-02 18:25:59', + r'INDIAN RUPEE 0.01 0.0118 1.00 0.00000054 -- --', ]) def ticker5(self): @@ -213,7 +213,7 @@ class TestSuiteScripts(TestSuiteBase): 'SPOT PRICE', 'BTC 0.11783441', 'XMR 17.23400000', - 'XAU','NDX', + 'GC=F',r'\^IXIC', ]) def ticker11(self): @@ -277,32 +277,22 @@ class TestSuiteScripts(TestSuiteBase): def ticker16(self): return self.ticker( - ['--wide','--elapsed','-c','eur,omr-omani-rial:2.59r'], + ['--wide','--elapsed','-c','eurusd=x,omr-omani-rial:2.59r'], [ - r'EUR \(EURO TOKEN\) = 1.0186 USD ' + + r'EURUSD=X \(EUR/USD\) = 1.0642 USD ' + r'OMR \(OMANI RIAL\) = 2.5900 USD', - 'USD EUR OMR BTC CHG_7d CHG_24h UPDATED', - 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 -- -- --' + 'USD EURUSD=X OMR BTC CHG_7d CHG_24h UPDATED', + r'BITCOIN 23,250.77 21,848.7527 8,977.1328 1.00000000 \+11.15 \+0.89 10 minutes ago', + 'OMANI RIAL 2.59 2.4338 1.0000 0.00011139 -- -- --' ]) def ticker17(self): # BGN pegged at 0.5113 EUR return self.ticker( - ['--wide','--elapsed','-c','bgn-bulgarian-lev:0.5113r:eur'], + ['--wide','--elapsed','-c','bgn-bulgarian-lev:0.5113r:eurusd=x'], [ - r'BGN \(BULGARIAN LEV\) = 0.52080 USD', + r'BGN \(BULGARIAN LEV\) = 0.54411 USD', 'USD BGN BTC CHG_7d CHG_24h UPDATED', - 'BITCOIN 23,250.77 44,644.414 1.00000000', - 'BULGARIAN LEV 0.52 1.000 0.00002240', - ]) - - def ticker18(self): - return self.ticker( - ['--wide','--elapsed','-c','eur,bgn-bulgarian-lev:0.5113r:eur-euro-token'], - [ - r'BGN \(BULGARIAN LEV\) = 0.52080 USD', - 'USD EUR BGN BTC CHG_7d CHG_24h UPDATED', - 'BITCOIN 23,250.77 22,826.6890 44,644.414 1.00000000', - 'BULGARIAN LEV 0.52 0.5113 1.000 0.00002240', + 'BITCOIN 23,250.77 42,731.767 1.00000000', + 'BULGARIAN LEV 0.54 1.000 0.00002340', ])