Source code for golosscripts.functions

import asyncio
import logging
from datetime import date, timedelta
from typing import Any, Dict, Optional, Union

import aiohttp
import ccxt.async_support as ccxt
from defusedxml.minidom import parseString

[docs]log = logging.getLogger('golosscripts')
[docs]def price_troyounce_to_price_1mg(price_troyounce: float) -> float: """Convert price per troy ounce to price per milligramm.""" gram_in_troyounce = 31.1034768 price = price_troyounce / gram_in_troyounce / 1000 return price
[docs]async def get_price_rub_gold_cbr( timeout: Union[int, float] = 12, session: Optional[aiohttp.ClientSession] = None ) -> float: """Get price of 1 mg Gold from Russian Central Bank; return value is RUB.""" if not session: session = aiohttp.ClientSession(raise_for_status=True) # cbr metall codes: (1 - gold, 2 - silver, 3 - platinum, 4 - palladium) # cbr may return an empty value on Monday, so request 2 days history today = date.today() date1 = (today - timedelta(days=7)).strftime('%d/%m/%Y') date2 = today.strftime('%d/%m/%Y') # date_req1 — date_req2 = Date range payload = {'date_req1': date1, 'date_req2': date2} async with session.get('http://www.cbr.ru/scripts/xml_metall.asp', params=payload, timeout=timeout) as result: dom = parseString(await result.text()) price = [] for element in dom.getElementsByTagName('Record'): if element.getAttribute('Code') == '1': price.append(element.getElementsByTagName('Buy')[0].childNodes[0].data.split(',')[0]) # return value is grams, so divide to 1000 return float(price[0]) / 1000
[docs]async def get_price_usd_rub_cbr( timeout: Union[int, float] = 12, session: Optional[aiohttp.ClientSession] = None ) -> float: """Get USD/RUB price from Russian Central Bank API mirror.""" if not session: session = aiohttp.ClientSession(raise_for_status=True) async with session.get('https://www.cbr-xml-daily.ru/daily_json.js', timeout=timeout) as result: js = await result.json(content_type='application/javascript') return js['Valute']['USD']['Value']
[docs]async def get_price_usd_gold_cbr() -> float: """Calculate price of 1 mg GOLD in USD based on cbr.ru rates.""" session = aiohttp.ClientSession(raise_for_status=True) try: rub_gold_price, rub_usd_price = await asyncio.gather( get_price_rub_gold_cbr(session=session), get_price_usd_rub_cbr(session=session) ) except Exception: raise finally: await session.close() usd_gold_price = rub_gold_price / rub_usd_price return usd_gold_price
[docs]async def fetch_ticker(exchange: str, market: str) -> Dict[str, Any]: """ Fetch ticker data from exchange. :param exchange: exchnage name, see `Supported exchanges <https://ccxt.readthedocs.io/en/latest/exchanges.html>`_ :param market: market like 'BTC/USD' :return: ticker :rtype: dict """ _exchange = getattr(ccxt, exchange)() try: ticker = await _exchange.fetch_ticker(market) log.debug('got ticker from %s', exchange) except Exception: raise finally: await _exchange.close() return ticker
[docs]async def get_price_btc_usd_exchanges() -> float: """Returns average BTC/USD price across several pre-defined exchanges.""" exchanges = {'binance': 'usdt', 'bittrex': 'usdt', 'coinbase': 'usd', 'gemini': 'usd'} tasks = [ asyncio.create_task(fetch_ticker(exchange, f'BTC/{usd_symbol.upper()}')) for exchange, usd_symbol in exchanges.items() ] results = None # Wait for results from all tasks try: results = await asyncio.gather(*tasks) except ccxt.NetworkError: pass if not results: raise ccxt.NetworkError('Failed to obtain ticker from any source') prices = [i['last'] for i in results] return sum(prices) / len(prices)