From bc25007fef41b6d017e6b7c4df08361bb86246a3 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sat, 12 May 2018 18:45:18 +0200 Subject: [PATCH 01/13] Update cachetools from 2.0.1 to 2.1.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4a06a96ef..deb0c9c5f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ ccxt==1.13.133 SQLAlchemy==1.2.7 python-telegram-bot==10.1.0 arrow==0.12.1 -cachetools==2.0.1 +cachetools==2.1.0 requests==2.18.4 urllib3==1.22 wrapt==1.10.11 From 8b098859f4f5b2a0b528cf63b1cbff118cc5323e Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sat, 12 May 2018 20:15:59 +0200 Subject: [PATCH 02/13] Reduce verbosity of get_ticker_history --- freqtrade/exchange/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 54b88c79c..109e3f7b2 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -297,9 +297,10 @@ def get_ticker_history(pair: str, tick_interval: str, since_ms: Optional[int] = if not data_part: break - logger.info('Downloaded data for time range [%s, %s]', - arrow.get(data_part[0][0] / 1000).format(), - arrow.get(data_part[-1][0] / 1000).format()) + logger.debug('Downloaded data for %s time range [%s, %s]', + pair, + arrow.get(data_part[0][0] / 1000).format(), + arrow.get(data_part[-1][0] / 1000).format()) data.extend(data_part) since_ms = data[-1][0] + 1 From d51ac94662394456cc992c2b53a1e4291c6437c9 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sun, 13 May 2018 05:41:24 +0200 Subject: [PATCH 03/13] Update ccxt from 1.13.133 to 1.13.136 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index deb0c9c5f..90426ffd1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -ccxt==1.13.133 +ccxt==1.13.136 SQLAlchemy==1.2.7 python-telegram-bot==10.1.0 arrow==0.12.1 From 8f17b11610467287a22c24430eee67becf390430 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 13:38:29 +0200 Subject: [PATCH 04/13] Fix testfluke in hyperopt --- freqtrade/tests/optimize/test_hyperopt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 68fc99955..f8fa66b2e 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -123,7 +123,7 @@ def test_loss_calculation_has_limited_profit(init_hyperopt) -> None: assert under > correct -def test_log_results_if_loss_improves(capsys) -> None: +def test_log_results_if_loss_improves(init_hyperopt, capsys) -> None: hyperopt = _HYPEROPT hyperopt.current_best_loss = 2 hyperopt.log_results( From 14c140d2424d989bd34be36a2e47b1781bd906bb Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sun, 13 May 2018 16:26:25 +0200 Subject: [PATCH 05/13] Update ccxt from 1.13.136 to 1.13.138 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 90426ffd1..dc822e710 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -ccxt==1.13.136 +ccxt==1.13.138 SQLAlchemy==1.2.7 python-telegram-bot==10.1.0 arrow==0.12.1 From d07491ceb290ecdb7a8c130dcba51dfd6ad182c8 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 19:46:08 +0200 Subject: [PATCH 06/13] Dynamically load cryptomap --- freqtrade/fiat_convert.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index 1258ee149..d24e5187c 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -5,6 +5,7 @@ e.g BTC to USD import logging import time +from typing import Dict from coinmarketcap import Market @@ -73,12 +74,7 @@ class CryptoToFiatConverter(object): "RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD" ] - CRYPTOMAP = { - 'BTC': 'bitcoin', - 'ETH': 'ethereum', - 'USDT': 'thether', - 'BNB': 'binance-coin' - } + _cryptomap: Dict = {} def __new__(cls): if CryptoToFiatConverter.__instance is None: @@ -91,6 +87,15 @@ class CryptoToFiatConverter(object): def __init__(self) -> None: self._pairs = [] + self._load_cryptomap() + + def _load_cryptomap(self) -> None: + try: + coinlistings = self._coinmarketcap.listings() + self._cryptomap = dict(map(lambda coin: (coin["symbol"], coin["id"]), + coinlistings["data"])) + except ValueError: + logger.error("Could not load FIAT Cryptocurrency map") def convert_amount(self, crypto_amount: float, crypto_symbol: str, fiat_symbol: str) -> float: """ @@ -182,14 +187,14 @@ class CryptoToFiatConverter(object): if not self._is_supported_fiat(fiat=fiat_symbol): raise ValueError('The fiat {} is not supported.'.format(fiat_symbol)) - if crypto_symbol not in self.CRYPTOMAP: + if crypto_symbol not in self._cryptomap: # return 0 for unsupported stake currencies (fiat-convert should not break the bot) logger.warning("unsupported crypto-symbol %s - returning 0.0", crypto_symbol) return 0.0 try: return float( self._coinmarketcap.ticker( - currency=self.CRYPTOMAP[crypto_symbol], + currency=self._cryptomap[crypto_symbol], convert=fiat_symbol )[0]['price_' + fiat_symbol.lower()] ) From 9b8f90dc9fe9586da8140177a6b6a802725e8c58 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 19:50:04 +0200 Subject: [PATCH 07/13] log error in find_price --- freqtrade/fiat_convert.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index d24e5187c..6a80b5641 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -198,5 +198,6 @@ class CryptoToFiatConverter(object): convert=fiat_symbol )[0]['price_' + fiat_symbol.lower()] ) - except BaseException: + except BaseException as ex: + logger.error("Error in _find_price: %s", ex) return 0.0 From 144be37a9aec0edd9f88d020085016138cbba09a Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 19:53:23 +0200 Subject: [PATCH 08/13] Convert ID to string --- freqtrade/fiat_convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index 6a80b5641..28f00acdf 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -92,7 +92,7 @@ class CryptoToFiatConverter(object): def _load_cryptomap(self) -> None: try: coinlistings = self._coinmarketcap.listings() - self._cryptomap = dict(map(lambda coin: (coin["symbol"], coin["id"]), + self._cryptomap = dict(map(lambda coin: (coin["symbol"], str(coin["id"]), coinlistings["data"])) except ValueError: logger.error("Could not load FIAT Cryptocurrency map") From 57fc9df5f355fd21ff2fdcecc6802dbd7b980913 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 19:54:19 +0200 Subject: [PATCH 09/13] Fix typo --- freqtrade/fiat_convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index 28f00acdf..5509b9f3a 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -92,7 +92,7 @@ class CryptoToFiatConverter(object): def _load_cryptomap(self) -> None: try: coinlistings = self._coinmarketcap.listings() - self._cryptomap = dict(map(lambda coin: (coin["symbol"], str(coin["id"]), + self._cryptomap = dict(map(lambda coin: (coin["symbol"], str(coin["id"])), coinlistings["data"])) except ValueError: logger.error("Could not load FIAT Cryptocurrency map") From 3246c604723b5d7d07619604f8d3cc881b9ff291 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 19:58:48 +0200 Subject: [PATCH 10/13] Fix coinmarketcap ticker --- freqtrade/fiat_convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/fiat_convert.py b/freqtrade/fiat_convert.py index 5509b9f3a..7e74adcd2 100644 --- a/freqtrade/fiat_convert.py +++ b/freqtrade/fiat_convert.py @@ -196,7 +196,7 @@ class CryptoToFiatConverter(object): self._coinmarketcap.ticker( currency=self._cryptomap[crypto_symbol], convert=fiat_symbol - )[0]['price_' + fiat_symbol.lower()] + )['data']['quotes'][fiat_symbol.upper()]['price'] ) except BaseException as ex: logger.error("Error in _find_price: %s", ex) From 790f35a5c86004b9efb0f1e19e9d671c151d6c69 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 20:03:54 +0200 Subject: [PATCH 11/13] fix test which resets singleton without reinstating it --- freqtrade/tests/test_fiat_convert.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/freqtrade/tests/test_fiat_convert.py b/freqtrade/tests/test_fiat_convert.py index 2305b27b1..0e288bdf9 100644 --- a/freqtrade/tests/test_fiat_convert.py +++ b/freqtrade/tests/test_fiat_convert.py @@ -128,7 +128,9 @@ def test_fiat_convert_without_network(): fiat_convert = CryptoToFiatConverter() + cmc_temp = CryptoToFiatConverter._coinmarketcap CryptoToFiatConverter._coinmarketcap = None assert fiat_convert._coinmarketcap is None assert fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='USD') == 0.0 + CryptoToFiatConverter._coinmarketcap = cmc_temp From b1c53ec6567697c2ee8af18e13881b2405454764 Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 20:04:40 +0200 Subject: [PATCH 12/13] refactor "patch_coinmarketcap" to conftest" add patch_coinmarketcap to get_patched_freqtradebot --- freqtrade/tests/conftest.py | 23 ++++++++++++++++++++++- freqtrade/tests/test_freqtradebot.py | 17 +---------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index bb42bcff9..1ce7b0af0 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -2,6 +2,7 @@ import json import logging from datetime import datetime +from typing import Dict, Optional from functools import reduce from unittest.mock import MagicMock @@ -34,7 +35,8 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot: :param config: Config to pass to the bot :return: None """ - mocker.patch('freqtrade.fiat_convert.Market', {'price_usd': 12345.0}) + # mocker.patch('freqtrade.fiat_convert.Market', {'price_usd': 12345.0}) + patch_coinmarketcap(mocker, {'price_usd': 12345.0}) mocker.patch('freqtrade.freqtradebot.Analyze', MagicMock()) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) @@ -46,6 +48,25 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot: return FreqtradeBot(config, create_engine('sqlite://')) +def patch_coinmarketcap(mocker, value: Optional[Dict[str, float]] = None) -> None: + """ + Mocker to coinmarketcap to speed up tests + :param mocker: mocker to patch coinmarketcap class + :return: None + """ + mock = MagicMock() + + if value: + mock.ticker = {'price_usd': 12345.0} + mock.listings = {'data': [{'id': 1, 'name': 'Bitcoin', 'symbol': 'BTC', + 'website_slug': 'bitcoin'}, + {'id': 1027, 'name': 'Ethereum', 'symbol': 'ETH', + 'website_slug': 'ethereum'} + ]} + + mocker.patch('freqtrade.fiat_convert.Market', mock) + + @pytest.fixture(scope="function") def default_conf(): """ Returns validated configuration suitable for most tests """ diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py index ead796aca..d9de2c3dc 100644 --- a/freqtrade/tests/test_freqtradebot.py +++ b/freqtrade/tests/test_freqtradebot.py @@ -8,7 +8,6 @@ import logging import re import time from copy import deepcopy -from typing import Dict, Optional from unittest.mock import MagicMock import arrow @@ -20,7 +19,7 @@ from freqtrade import DependencyException, OperationalException, TemporaryError from freqtrade.freqtradebot import FreqtradeBot from freqtrade.persistence import Trade from freqtrade.state import State -from freqtrade.tests.conftest import log_has +from freqtrade.tests.conftest import log_has, patch_coinmarketcap # Functions for recurrent object patching @@ -64,20 +63,6 @@ def patch_RPCManager(mocker) -> MagicMock: return rpc_mock -def patch_coinmarketcap(mocker, value: Optional[Dict[str, float]] = None) -> None: - """ - Mocker to coinmarketcap to speed up tests - :param mocker: mocker to patch coinmarketcap class - :return: None - """ - mock = MagicMock() - - if value: - mock.ticker = {'price_usd': 12345.0} - - mocker.patch('freqtrade.fiat_convert.Market', mock) - - # Unit tests def test_freqtradebot_object() -> None: """ From 8549201502847e656931c333956ee46383bf067b Mon Sep 17 00:00:00 2001 From: Matthias Voppichler Date: Sun, 13 May 2018 20:46:02 +0200 Subject: [PATCH 13/13] add test for new fiat_convert logic --- freqtrade/tests/conftest.py | 20 +++++++++++--------- freqtrade/tests/test_fiat_convert.py | 10 ++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index 1ce7b0af0..5d6195a2f 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -54,17 +54,19 @@ def patch_coinmarketcap(mocker, value: Optional[Dict[str, float]] = None) -> Non :param mocker: mocker to patch coinmarketcap class :return: None """ - mock = MagicMock() - if value: - mock.ticker = {'price_usd': 12345.0} - mock.listings = {'data': [{'id': 1, 'name': 'Bitcoin', 'symbol': 'BTC', - 'website_slug': 'bitcoin'}, - {'id': 1027, 'name': 'Ethereum', 'symbol': 'ETH', - 'website_slug': 'ethereum'} - ]} + tickermock = MagicMock(return_value={'price_usd': 12345.0}) + listmock = MagicMock(return_value={'data': [{'id': 1, 'name': 'Bitcoin', 'symbol': 'BTC', + 'website_slug': 'bitcoin'}, + {'id': 1027, 'name': 'Ethereum', 'symbol': 'ETH', + 'website_slug': 'ethereum'} + ]}) + mocker.patch.multiple( + 'freqtrade.fiat_convert.Market', + ticker=tickermock, + listings=listmock, - mocker.patch('freqtrade.fiat_convert.Market', mock) + ) @pytest.fixture(scope="function") diff --git a/freqtrade/tests/test_fiat_convert.py b/freqtrade/tests/test_fiat_convert.py index 0e288bdf9..f5be9daf0 100644 --- a/freqtrade/tests/test_fiat_convert.py +++ b/freqtrade/tests/test_fiat_convert.py @@ -7,6 +7,7 @@ from unittest.mock import MagicMock import pytest from freqtrade.fiat_convert import CryptoFiat, CryptoToFiatConverter +from freqtrade.tests.conftest import patch_coinmarketcap def test_pair_convertion_object(): @@ -123,6 +124,15 @@ def test_fiat_convert_get_price(mocker): assert fiat_convert._pairs[0]._expiration is not expiration +def test_loadcryptomap(mocker): + patch_coinmarketcap(mocker) + + fiat_convert = CryptoToFiatConverter() + assert len(fiat_convert._cryptomap) == 2 + + assert fiat_convert._cryptomap["BTC"] == "1" + + def test_fiat_convert_without_network(): # Because CryptoToFiatConverter is a Singleton we reset the value of _coinmarketcap