def query_endpoint_price( self, from_asset: Asset, to_asset: Asset, handling_special_case: bool = False, ) -> Dict[str, Any]: """Returns the current price of an asset compared to another asset - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server - May raise PriceQueryUnsupportedAsset if from/to assets are not known to cryptocompare """ special_asset = (from_asset in CRYPTOCOMPARE_SPECIAL_CASES or to_asset in CRYPTOCOMPARE_SPECIAL_CASES) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_endpoint_price', from_asset=from_asset, to_asset=to_asset, ) try: cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() except UnsupportedAsset as e: raise PriceQueryUnsupportedAsset(e.asset_name) query_path = f'price?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' result = self._api_query(path=query_path) return result
def query_endpoint_price( self, from_asset: Asset, to_asset: Asset, handling_special_case: bool = False, ) -> Dict[str, Any]: """Returns the current price of an asset compared to another asset - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server """ special_asset = ( from_asset in CRYPTOCOMPARE_SPECIAL_CASES or to_asset in CRYPTOCOMPARE_SPECIAL_CASES ) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_endpoint_price', from_asset=from_asset, to_asset=to_asset, ) # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = f'price?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' result = self._api_query(path=query_path) return result
def query_endpoint_pricehistorical( self, from_asset: Asset, to_asset: Asset, timestamp: Timestamp, ) -> Price: """Queries the historical daily price of from_asset to to_asset for timestamp - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server """ log.debug( 'Querying cryptocompare for daily historical price', from_asset=from_asset, to_asset=to_asset, timestamp=timestamp, ) # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = ( f'pricehistorical?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' f'&ts={timestamp}' ) if to_asset == 'BTC': query_path += '&tryConversion=false' result = self._api_query(query_path) return Price(FVal(result[cc_from_asset_symbol][cc_to_asset_symbol]))
def query_current_price( self, from_asset: Asset, to_asset: Asset, handling_special_case: bool = False, ) -> Price: """Returns the current price of an asset compared to another asset - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server - May raise PriceQueryUnsupportedAsset if from/to assets are not known to cryptocompare """ special_asset = (from_asset.identifier in CRYPTOCOMPARE_SPECIAL_CASES or to_asset.identifier in CRYPTOCOMPARE_SPECIAL_CASES) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_current_price', from_asset=from_asset, to_asset=to_asset, ) try: cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() except UnsupportedAsset as e: raise PriceQueryUnsupportedAsset(e.asset_name) from e query_path = f'price?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' result = self._api_query(path=query_path) # Up until 23/09/2020 cryptocompare may return {} due to bug. # Handle that case by assuming 0 if that happens if cc_to_asset_symbol not in result: return Price(ZERO) return Price(FVal(result[cc_to_asset_symbol]))
def query_endpoint_histohour( self, from_asset: Asset, to_asset: Asset, limit: int, to_timestamp: Timestamp, handling_special_case: bool = False, ) -> Dict[str, Any]: """Returns the full histohour response including TimeFrom and TimeTo - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server """ special_asset = ( from_asset in CRYPTOCOMPARE_SPECIAL_CASES or to_asset in CRYPTOCOMPARE_SPECIAL_CASES ) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_endpoint_histohour', from_asset=from_asset, to_asset=to_asset, limit=limit, to_timestamp=to_timestamp, ) # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = ( f'v2/histohour?fsym={cc_from_asset_symbol}&tsym={cc_to_asset_symbol}' f'&limit={limit}&toTs={to_timestamp}' ) result = self._api_query(path=query_path) return result
def _get_cache_key(from_asset: Asset, to_asset: Asset) -> Optional[PairCacheKey]: try: from_cc_asset = from_asset.to_cryptocompare() to_cc_asset = to_asset.to_cryptocompare() except UnsupportedAsset: return None return PairCacheKey(from_cc_asset + '_' + to_cc_asset)
def _get_cache_key(from_asset: Asset, to_asset: Asset) -> Optional[PairCacheKey]: try: # first see if they both support cryptocompare from_asset.to_cryptocompare() to_asset.to_cryptocompare() except UnsupportedAsset: return None return PairCacheKey(from_asset.identifier + '_' + to_asset.identifier)
def query_endpoint_pricehistorical( self, from_asset: Asset, to_asset: Asset, timestamp: Timestamp, handling_special_case: bool = False, ) -> Price: """Queries the historical daily price of from_asset to to_asset for timestamp - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server - May raise PriceQueryUnsupportedAsset if from/to assets are not known to cryptocompare """ log.debug( 'Querying cryptocompare for daily historical price', from_asset=from_asset, to_asset=to_asset, timestamp=timestamp, ) special_asset = ( from_asset.identifier in CRYPTOCOMPARE_SPECIAL_CASES or to_asset.identifier in CRYPTOCOMPARE_SPECIAL_CASES ) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_endpoint_pricehistorical', from_asset=from_asset, to_asset=to_asset, timestamp=timestamp, ) try: cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() except UnsupportedAsset as e: raise PriceQueryUnsupportedAsset(e.asset_name) from e query_path = ( f'pricehistorical?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' f'&ts={timestamp}' ) if to_asset == 'BTC': query_path += '&tryConversion=false' result = self._api_query(query_path) # Up until 23/09/2020 cryptocompare may return {} due to bug. # Handle that case by assuming 0 if that happens if ( cc_from_asset_symbol not in result or cc_to_asset_symbol not in result[cc_from_asset_symbol] ): return Price(ZERO) return Price(FVal(result[cc_from_asset_symbol][cc_to_asset_symbol]))
def query_endpoint_histohour( self, from_asset: Asset, to_asset: Asset, limit: int, to_timestamp: Timestamp, ) -> Dict[str, Any]: """Returns the full histohour response including TimeFrom and TimeTo""" # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = ( f'histohour?fsym={cc_from_asset_symbol}&tsym={cc_to_asset_symbol}' f'&limit={limit}&toTs={to_timestamp}') result = self._api_query(path=query_path) return result
def query_endpoint_price( self, from_asset: Asset, to_asset: Asset, ) -> Dict[str, Any]: """Returns the current price of an asset compared to another asset - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server """ # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = f'price?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' result = self._api_query(path=query_path) return result
def query_cryptocompare_for_fiat_price(asset: Asset) -> Price: log.debug('Get usd price from cryptocompare', asset=asset) cc_asset_str = asset.to_cryptocompare() resp = retry_calls( 5, 'find_usd_price', 'requests.get', requests.get, u'https://min-api.cryptocompare.com/data/price?' 'fsym={}&tsyms=USD'.format(cc_asset_str), ) if resp.status_code != 200: raise RemoteError( 'Cant reach cryptocompare to get USD value of {}'.format(asset)) resp = rlk_jsonloads_dict(resp.text) # If there is an error in the response skip this token if 'USD' not in resp: error_message = '' if resp['Response'] == 'Error': error_message = resp['Message'] log.error( 'Cryptocompare usd price query failed', asset=asset, error=error_message, ) return Price(ZERO) price = Price(FVal(resp['USD'])) log.debug('Got usd price from cryptocompare', asset=asset, price=price) return price
def query_endpoint_histohour( self, from_asset: Asset, to_asset: Asset, limit: int, to_timestamp: Timestamp, ) -> Dict[str, Any]: # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = ( f'histohour?fsym={cc_from_asset_symbol}&tsym={cc_to_asset_symbol}' f'&limit={limit}&toTs={to_timestamp}' ) result = self._api_query(path=query_path, only_data=False) return result
def query_endpoint_pricehistorical( self, from_asset: Asset, to_asset: Asset, timestamp: Timestamp, handling_special_case: bool = False, ) -> Price: """Queries the historical daily price of from_asset to to_asset for timestamp - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server """ log.debug( 'Querying cryptocompare for daily historical price', from_asset=from_asset, to_asset=to_asset, timestamp=timestamp, ) special_asset = ( from_asset in CRYPTOCOMPARE_SPECIAL_CASES or to_asset in CRYPTOCOMPARE_SPECIAL_CASES ) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_endpoint_pricehistorical', from_asset=from_asset, to_asset=to_asset, timestamp=timestamp, ) # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = ( f'pricehistorical?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' f'&ts={timestamp}' ) if to_asset == 'BTC': query_path += '&tryConversion=false' result = self._api_query(query_path) return Price(FVal(result[cc_from_asset_symbol][cc_to_asset_symbol]))
def query_endpoint_pricehistorical( self, from_asset: Asset, to_asset: Asset, timestamp: Timestamp, ) -> Price: log.debug( 'Querying cryptocompare for daily historical price', from_asset=from_asset, to_asset=to_asset, timestamp=timestamp, ) # These two can raise but them raising here is a bug cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() query_path = ( f'pricehistorical?fsym={cc_from_asset_symbol}&tsyms={cc_to_asset_symbol}' f'&ts={timestamp}') if to_asset == 'BTC': query_path += '&tryConversion=false' result = self._api_query(query_path) return Price(FVal(result[cc_from_asset_symbol][cc_to_asset_symbol]))
def query_endpoint_histohour( self, from_asset: Asset, to_asset: Asset, limit: int, to_timestamp: Timestamp, handling_special_case: bool = False, ) -> Dict[str, Any]: """Returns the full histohour response including TimeFrom and TimeTo - May raise RemoteError if there is a problem reaching the cryptocompare server or with reading the response returned by the server - May raise PriceQueryUnsupportedAsset if from/to assets are not known to cryptocompare """ special_asset = ( from_asset.identifier in CRYPTOCOMPARE_SPECIAL_CASES or to_asset.identifier in CRYPTOCOMPARE_SPECIAL_CASES ) if special_asset and not handling_special_case: return self._special_case_handling( method_name='query_endpoint_histohour', from_asset=from_asset, to_asset=to_asset, limit=limit, to_timestamp=to_timestamp, ) try: cc_from_asset_symbol = from_asset.to_cryptocompare() cc_to_asset_symbol = to_asset.to_cryptocompare() except UnsupportedAsset as e: raise PriceQueryUnsupportedAsset(e.asset_name) from e query_path = ( f'v2/histohour?fsym={cc_from_asset_symbol}&tsym={cc_to_asset_symbol}' f'&limit={limit}&toTs={to_timestamp}' ) result = self._api_query(path=query_path) return result
def query_cryptocompare_for_fiat_price(asset: Asset) -> Price: log.debug('Get usd price from cryptocompare', asset=asset) cc_asset_str = asset.to_cryptocompare() resp = retry_calls( times=5, location='find_usd_price', handle_429=False, backoff_in_seconds=0, method_name='requests.get', function=requests.get, # function's arguments url=( u'https://min-api.cryptocompare.com/data/price?' 'fsym={}&tsyms=USD'.format(cc_asset_str) ), ) if resp.status_code != 200: raise RemoteError('Cant reach cryptocompare to get USD value of {}'.format(asset)) resp = rlk_jsonloads_dict(resp.text) # If there is an error in the response skip this token if 'USD' not in resp: error_message = '' if resp.get('Response', None) == 'Error': error_message = resp.get('Message', '') log.error( 'Cryptocompare usd price query failed', asset=asset, error=error_message, ) return Price(ZERO) price = Price(FVal(resp['USD'])) log.debug('Got usd price from cryptocompare', asset=asset, price=price) return price