From c5c592329e7700cc7ece5d4f748f8463cdef1cf4 Mon Sep 17 00:00:00 2001 From: AuroraTradingTeam Date: Tue, 7 Nov 2017 14:42:12 +0000 Subject: [PATCH] Added get_instruments on cryptocompare. --- Makefile | 1 + libcryptomarket/api/coinmarketcap_api.py | 7 +- libcryptomarket/api/cryptocompare_api.py | 38 ++++++++++ libcryptomarket/instrument.py | 26 +++++-- tests/test_coinmarketcap_api.py | 83 +++++++++++++++------ tests/test_cryptocompare_api.py | 93 ++++++++++++++++++++++++ 6 files changed, 217 insertions(+), 31 deletions(-) create mode 100644 libcryptomarket/api/cryptocompare_api.py create mode 100644 tests/test_cryptocompare_api.py diff --git a/Makefile b/Makefile index c0033d4..d1a2ed2 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,7 @@ clean-test: ## remove test and coverage artifacts autopep8: ## autopep8 to clean autopep8 --aggressive --in-place --recursive libcryptomarket/*/*.py + autopep8 --aggressive --in-place --recursive libcryptomarket/*.py autopep8 --aggressive --in-place --recursive tests/*.py lint: ## check style with flake8 diff --git a/libcryptomarket/api/coinmarketcap_api.py b/libcryptomarket/api/coinmarketcap_api.py index 9695ed4..290de21 100644 --- a/libcryptomarket/api/coinmarketcap_api.py +++ b/libcryptomarket/api/coinmarketcap_api.py @@ -5,13 +5,14 @@ from datetime import datetime TICKET_URL = "https://api.coinmarketcap.com/v1/ticker/" + class CoinMarketCapApiTicker: """Result class of query /ticker """ def __init__(self, **kwargs): """Constructor. - + Constructed from the request result like the following { "id": "bitcoin", @@ -46,6 +47,7 @@ class CoinMarketCapApiTicker: self.r_last_updated = datetime.fromtimestamp( int(kwargs["last_updated"])) + def get_ticker(coin=None): """Return the ticker of all coins or the particular coin. @@ -59,5 +61,4 @@ def get_ticker(coin=None): if coin is not None: url += coin - return [CoinMarketCapApiTicker(**ret) - for ret in requests.get(url).json()] + return requests.get(url).json() diff --git a/libcryptomarket/api/cryptocompare_api.py b/libcryptomarket/api/cryptocompare_api.py new file mode 100644 index 0000000..6a4c674 --- /dev/null +++ b/libcryptomarket/api/cryptocompare_api.py @@ -0,0 +1,38 @@ +#!/bin/python +import requests + +API_URL = "https://www.cryptocompare.com/api/data/" + + +class CryptocompareCoinlist: + """Cryptocompare coinlist. + """ + + def __init__(self, **kwargs): + """Constructor. + """ + self.r_algorithm = kwargs['Algorithm'].replace('N/A', '') or '' + self.r_coinname = kwargs['CoinName'] or '' + self.r_fullname = kwargs['FullName'] or '' + self.r_fullypremined = int(kwargs['FullyPremined'].replace('N/A', '') + or 0) + self.r_id = kwargs['Id'] or '' + self.r_imageurl = kwargs.get('ImageUrl', '') or '' + self.r_name = kwargs['Name'] or '' + self.r_preminedvalue = float(kwargs['PreMinedValue'].replace('N/A', '') + or '0') + self.r_prooftype = kwargs['ProofType'].replace('N/A', '') or '' + self.r_sortorder = int(kwargs['SortOrder'].replace('N/A', '') or '0') + self.r_sponsored = kwargs['Sponsored'] or False + self.r_symbol = kwargs['Symbol'] or '' + # TotalCoinSupply and TotalCoinsFreeFloat are not supported due to + # very dirty data. + self.r_url = kwargs['Url'] or '' + + +def get_coinlist(): + """Return general info for all coins available. + """ + url = API_URL + "coinlist" + + return requests.get(url).json() diff --git a/libcryptomarket/instrument.py b/libcryptomarket/instrument.py index d5a73ea..d955f58 100644 --- a/libcryptomarket/instrument.py +++ b/libcryptomarket/instrument.py @@ -1,12 +1,26 @@ import pandas as pd -from libcryptomarket.api.coinmarketcap_api import get_ticker - -def get_instruments(): +def get_instruments(source='coinmarketcap', **kwargs): """Return all the instruments. """ - result = get_ticker() + if source == 'coinmarketcap': + # Coinmarketcap + from libcryptomarket.api.coinmarketcap_api import ( + get_ticker, CoinMarketCapApiTicker) + + result = get_ticker(**kwargs) + result = [CoinMarketCapApiTicker(**e) for e in result] + elif source == 'cryptocompare': + # Cryptocompare + from libcryptomarket.api.cryptocompare_api import ( + get_coinlist, CryptocompareCoinlist) + + result = get_coinlist(**kwargs) + result = [CryptocompareCoinlist(**value) + for key, value in result['Data'].items()] + else: + raise ValueError("No source is called {0}".format(source)) + result = pd.DataFrame([r.__dict__ for r in result]) - - return result \ No newline at end of file + return result diff --git a/tests/test_coinmarketcap_api.py b/tests/test_coinmarketcap_api.py index 123a6e4..6b25e09 100644 --- a/tests/test_coinmarketcap_api.py +++ b/tests/test_coinmarketcap_api.py @@ -1,10 +1,13 @@ import requests import datetime -from libcryptomarket.api.coinmarketcap_api import get_ticker +import pandas as pd +from pandas.util.testing import assert_frame_equal + +from libcryptomarket.instrument import get_instruments -def test_get_ticker(monkeypatch): +def test_get_instruments_coinmarketcap(monkeypatch): def mockreturn(url): # The result is from request.get(...).json() class MockReturnClass: @@ -71,25 +74,61 @@ def test_get_ticker(monkeypatch): monkeypatch.setattr(requests, 'get', mockreturn) # Test getting all coins - result = get_ticker() - assert len(result) == 2 + result = get_instruments(source='coinmarketcap') + expected_result = pd.DataFrame([ + { + "r_id": "bitcoin", + "r_name": "Bitcoin", + "r_symbol": "BTC", + "r_rank": 1, + "r_price_usd": 573.137, + "r_price_btc": 1.0, + "r_24h_volume_usd": 72855700.0, + "r_market_cap_usd": 9080883500.0, + "r_available_supply": 15844176.0, + "r_total_supply": 15844176.0, + "r_percent_change_1h": 0.04, + "r_percent_change_24h": -0.3, + "r_percent_change_7d": -0.57, + "r_last_updated": datetime.datetime(2016, 9, 1, 20, 34, 27) + }, + { + "r_id": "ethereum", + "r_name": "Ethereum", + "r_symbol": "ETH", + "r_rank": 2, + "r_price_usd": 12.1844, + "r_price_btc": 0.021262, + "r_24h_volume_usd": 24085900.0, + "r_market_cap_usd": 1018098455.0, + "r_available_supply": 83557537.0, + "r_total_supply": 83557537.0, + "r_percent_change_1h": -0.58, + "r_percent_change_24h": 6.34, + "r_percent_change_7d": 8.59, + "r_last_updated": datetime.datetime(2016, 9, 1, 20, 34, 22) + }]) + assert_frame_equal(result.set_index(['r_id']).sort_index(), + expected_result.set_index(['r_id']).sort_index()) # Test getting only bitcoin - result = get_ticker("bitcoin") - assert len(result) == 1 - - result = result[0] - assert result.r_id == "bitcoin" - assert result.r_name == "Bitcoin" - assert result.r_symbol == "BTC" - assert result.r_rank == 1 - assert result.r_price_usd == 573.137 - assert result.r_price_btc == 1.0 - assert result.r_24h_volume_usd == 72855700.0 - assert result.r_market_cap_usd == 9080883500.0 - assert result.r_available_supply == 15844176.0 - assert result.r_total_supply == 15844176.0 - assert result.r_percent_change_1h == 0.04 - assert result.r_percent_change_24h == -0.3 - assert result.r_percent_change_7d == -0.57 - assert result.r_last_updated == datetime.datetime(2016, 9, 1, 20, 34, 27) \ No newline at end of file + result = get_instruments(source='coinmarketcap', coin='bitcoin') + expected_result = pd.DataFrame([ + { + "r_id": "bitcoin", + "r_name": "Bitcoin", + "r_symbol": "BTC", + "r_rank": 1, + "r_price_usd": 573.137, + "r_price_btc": 1.0, + "r_24h_volume_usd": 72855700.0, + "r_market_cap_usd": 9080883500.0, + "r_available_supply": 15844176.0, + "r_total_supply": 15844176.0, + "r_percent_change_1h": 0.04, + "r_percent_change_24h": -0.3, + "r_percent_change_7d": -0.57, + "r_last_updated": datetime.datetime(2016, 9, 1, 20, 34, 27) + }]) + assert_frame_equal(result.set_index(['r_id']).sort_index(), + expected_result.set_index(['r_id']).sort_index()) diff --git a/tests/test_cryptocompare_api.py b/tests/test_cryptocompare_api.py new file mode 100644 index 0000000..314ab11 --- /dev/null +++ b/tests/test_cryptocompare_api.py @@ -0,0 +1,93 @@ +import requests + +import pandas as pd +from pandas.util.testing import assert_frame_equal + +from libcryptomarket.instrument import get_instruments + + +def test_get_instruments_cryptocompare(monkeypatch): + def mockreturn(url): + # The result is from request.get(...).json() + class MockReturnClass: + @classmethod + def json(cls): + # Query all symbols + return { + 'BaseImageUrl': 'https://www.cryptocompare.com', + 'BaseLinkUrl': 'https://www.cryptocompare.com', + 'Data': { + 'STX': { + 'Algorithm': 'N/A', + 'CoinName': 'Stox', + 'FullName': 'Stox (STX)', + 'FullyPremined': '0', + 'Id': '204716', + 'ImageUrl': '/media/1383946/stx.png', + 'Name': 'STX', + 'PreMinedValue': 'N/A', + 'ProofType': 'N/A', + 'SortOrder': '1431', + 'Sponsored': False, + 'Symbol': 'STX', + 'TotalCoinSupply': '29600000', + 'TotalCoinsFreeFloat': 'N/A', + 'Url': '/coins/stx/overview'}, + 'BCN': { + 'Algorithm': 'CryptoNight', + 'CoinName': 'ByteCoin', + 'FullName': 'ByteCoin (BCN)', + 'FullyPremined': '0', + 'Id': '5280', + 'ImageUrl': '/media/12318404/bcn.png', + 'Name': 'BCN', + 'PreMinedValue': 'N/A', + 'ProofType': 'PoW', + 'SortOrder': '249', + 'Sponsored': False, + 'Symbol': 'BCN', + 'TotalCoinSupply': '184467440735', + 'TotalCoinsFreeFloat': 'N/A', + 'Url': '/coins/bcn/overview'} + } + } + + return MockReturnClass() + + monkeypatch.setattr(requests, 'get', mockreturn) + + # Test getting all coins + result = get_instruments(source='cryptocompare') + + assert len(result) == 2 + expected_result = pd.DataFrame([ + { + 'r_algorithm': '', + 'r_coinname': 'Stox', + 'r_fullname': 'Stox (STX)', + 'r_fullypremined': 0, + 'r_id': '204716', + 'r_imageurl': '/media/1383946/stx.png', + 'r_name': 'STX', + 'r_preminedvalue': 0.0, + 'r_prooftype': '', + 'r_sortorder': 1431, + 'r_sponsored': False, + 'r_symbol': 'STX', + 'r_url': '/coins/stx/overview'}, + { + 'r_algorithm': 'CryptoNight', + 'r_coinname': 'ByteCoin', + 'r_fullname': 'ByteCoin (BCN)', + 'r_fullypremined': 0, + 'r_id': '5280', + 'r_imageurl': '/media/12318404/bcn.png', + 'r_name': 'BCN', + 'r_preminedvalue': 0.0, + 'r_prooftype': 'PoW', + 'r_sortorder': 249, + 'r_sponsored': False, + 'r_symbol': 'BCN', + 'r_url': '/coins/bcn/overview'}]) + assert_frame_equal(result.set_index(['r_id']).sort_index(), + expected_result.set_index(['r_id']).sort_index())