Merge pull request #1 from gcarq/develop

Updating to head of FreqTrade / develop
This commit is contained in:
Alocaly 2018-05-14 00:02:43 +02:00 committed by GitHub
commit 7649ef0b6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 33 deletions

View File

@ -297,7 +297,8 @@ def get_ticker_history(pair: str, tick_interval: str, since_ms: Optional[int] =
if not data_part: if not data_part:
break break
logger.info('Downloaded data for time range [%s, %s]', logger.debug('Downloaded data for %s time range [%s, %s]',
pair,
arrow.get(data_part[0][0] / 1000).format(), arrow.get(data_part[0][0] / 1000).format(),
arrow.get(data_part[-1][0] / 1000).format()) arrow.get(data_part[-1][0] / 1000).format())

View File

@ -5,6 +5,7 @@ e.g BTC to USD
import logging import logging
import time import time
from typing import Dict
from coinmarketcap import Market from coinmarketcap import Market
@ -73,12 +74,7 @@ class CryptoToFiatConverter(object):
"RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD" "RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD"
] ]
CRYPTOMAP = { _cryptomap: Dict = {}
'BTC': 'bitcoin',
'ETH': 'ethereum',
'USDT': 'thether',
'BNB': 'binance-coin'
}
def __new__(cls): def __new__(cls):
if CryptoToFiatConverter.__instance is None: if CryptoToFiatConverter.__instance is None:
@ -91,6 +87,15 @@ class CryptoToFiatConverter(object):
def __init__(self) -> None: def __init__(self) -> None:
self._pairs = [] self._pairs = []
self._load_cryptomap()
def _load_cryptomap(self) -> None:
try:
coinlistings = self._coinmarketcap.listings()
self._cryptomap = dict(map(lambda coin: (coin["symbol"], str(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: def convert_amount(self, crypto_amount: float, crypto_symbol: str, fiat_symbol: str) -> float:
""" """
@ -182,16 +187,17 @@ class CryptoToFiatConverter(object):
if not self._is_supported_fiat(fiat=fiat_symbol): if not self._is_supported_fiat(fiat=fiat_symbol):
raise ValueError('The fiat {} is not supported.'.format(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) # return 0 for unsupported stake currencies (fiat-convert should not break the bot)
logger.warning("unsupported crypto-symbol %s - returning 0.0", crypto_symbol) logger.warning("unsupported crypto-symbol %s - returning 0.0", crypto_symbol)
return 0.0 return 0.0
try: try:
return float( return float(
self._coinmarketcap.ticker( self._coinmarketcap.ticker(
currency=self.CRYPTOMAP[crypto_symbol], currency=self._cryptomap[crypto_symbol],
convert=fiat_symbol convert=fiat_symbol
)[0]['price_' + fiat_symbol.lower()] )['data']['quotes'][fiat_symbol.upper()]['price']
) )
except BaseException: except BaseException as ex:
logger.error("Error in _find_price: %s", ex)
return 0.0 return 0.0

View File

@ -2,6 +2,7 @@
import json import json
import logging import logging
from datetime import datetime from datetime import datetime
from typing import Dict, Optional
from functools import reduce from functools import reduce
from unittest.mock import MagicMock from unittest.mock import MagicMock
@ -34,7 +35,8 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot:
:param config: Config to pass to the bot :param config: Config to pass to the bot
:return: None :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.Analyze', MagicMock())
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock()) mocker.patch('freqtrade.freqtradebot.persistence.init', MagicMock())
@ -46,6 +48,27 @@ def get_patched_freqtradebot(mocker, config) -> FreqtradeBot:
return FreqtradeBot(config, create_engine('sqlite://')) 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
"""
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,
)
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def default_conf(): def default_conf():
""" Returns validated configuration suitable for most tests """ """ Returns validated configuration suitable for most tests """

View File

@ -123,7 +123,7 @@ def test_loss_calculation_has_limited_profit(init_hyperopt) -> None:
assert under > correct 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 = _HYPEROPT
hyperopt.current_best_loss = 2 hyperopt.current_best_loss = 2
hyperopt.log_results( hyperopt.log_results(

View File

@ -7,6 +7,7 @@ from unittest.mock import MagicMock
import pytest import pytest
from freqtrade.fiat_convert import CryptoFiat, CryptoToFiatConverter from freqtrade.fiat_convert import CryptoFiat, CryptoToFiatConverter
from freqtrade.tests.conftest import patch_coinmarketcap
def test_pair_convertion_object(): def test_pair_convertion_object():
@ -123,12 +124,23 @@ def test_fiat_convert_get_price(mocker):
assert fiat_convert._pairs[0]._expiration is not expiration 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(): def test_fiat_convert_without_network():
# Because CryptoToFiatConverter is a Singleton we reset the value of _coinmarketcap # Because CryptoToFiatConverter is a Singleton we reset the value of _coinmarketcap
fiat_convert = CryptoToFiatConverter() fiat_convert = CryptoToFiatConverter()
cmc_temp = CryptoToFiatConverter._coinmarketcap
CryptoToFiatConverter._coinmarketcap = None CryptoToFiatConverter._coinmarketcap = None
assert fiat_convert._coinmarketcap is None assert fiat_convert._coinmarketcap is None
assert fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='USD') == 0.0 assert fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='USD') == 0.0
CryptoToFiatConverter._coinmarketcap = cmc_temp

View File

@ -8,7 +8,6 @@ import logging
import re import re
import time import time
from copy import deepcopy from copy import deepcopy
from typing import Dict, Optional
from unittest.mock import MagicMock from unittest.mock import MagicMock
import arrow import arrow
@ -20,7 +19,7 @@ from freqtrade import DependencyException, OperationalException, TemporaryError
from freqtrade.freqtradebot import FreqtradeBot from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.state import State 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 # Functions for recurrent object patching
@ -64,20 +63,6 @@ def patch_RPCManager(mocker) -> MagicMock:
return rpc_mock 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 # Unit tests
def test_freqtradebot_object() -> None: def test_freqtradebot_object() -> None:
""" """

View File

@ -1,8 +1,8 @@
ccxt==1.13.133 ccxt==1.13.138
SQLAlchemy==1.2.7 SQLAlchemy==1.2.7
python-telegram-bot==10.1.0 python-telegram-bot==10.1.0
arrow==0.12.1 arrow==0.12.1
cachetools==2.0.1 cachetools==2.1.0
requests==2.18.4 requests==2.18.4
urllib3==1.22 urllib3==1.22
wrapt==1.10.11 wrapt==1.10.11