diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index b3f0b8144..97590d97f 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -192,42 +192,44 @@ class FreqtradeBot(object): :param key: sort key (defaults to 'BaseVolume') :return: List of pairs """ - summaries = sorted( - (v for s, v in exchange.get_market_summaries().items() if v['symbol'].endswith(base_currency)), - key=lambda v: v.get('info').get(key) or 0.0, + pairs = sorted( + [s['symbol'] for s in exchange.get_markets() if s['quote'] == base_currency], reverse=True ) - return [s['symbol'] for s in summaries] + return pairs def _refresh_whitelist(self, whitelist: List[str]) -> List[str]: """ - Check wallet health and remove pair from whitelist if necessary + Check available markets and remove pair from whitelist if necessary :param whitelist: the sorted list (based on BaseVolume) of pairs the user might want to trade :return: the list of pairs the user wants to trade without the one unavailable or black_listed """ sanitized_whitelist = whitelist - health = exchange.get_wallet_health() + markets = exchange.get_markets() + + markets = [m for m in markets if m['quote'] == self.config['stake_currency']] known_pairs = set() - for symbol, status in health.items(): - pair = f"{status['base']}/{self.config['stake_currency']}" + for market in markets: + pair = market['symbol'] # pair is not int the generated dynamic market, or in the blacklist ... ignore it if pair not in whitelist or pair in self.config['exchange'].get('pair_blacklist', []): continue # else the pair is valid known_pairs.add(pair) # Market is not active - if not status['active']: + if not market['active']: sanitized_whitelist.remove(pair) self.logger.info( - 'Ignoring %s from whitelist (reason: %s).', - pair, status.get('Notice') or 'wallet is not active' + 'Ignoring %s from whitelist. Market is not active.', + pair ) # We need to remove pairs that are unknown final_list = [x for x in sanitized_whitelist if x in known_pairs] + return final_list def get_target_bid(self, ticker: Dict[str, float]) -> float: diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index 898babf44..21868abe9 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -127,32 +127,80 @@ def ticker_sell_down(): @pytest.fixture -def health(): - return MagicMock(return_value={ - "ETH/BTC": { +def markets(): + return MagicMock(return_value=[ + { + 'id': 'ethbtc', + 'symbol': 'ETH/BTC', 'base': 'ETH', + 'quote': 'BTC', 'active': True, - 'LastChecked': '2017-11-13T20:15:00.00', - 'Notice': None + 'precision': { + 'price': 8, + 'amount': 8, + 'cost': 8, + }, + 'lot': 0.00000001, + 'limits': { + 'amount': { + 'min': 0.01, + 'max': 1000, + }, + 'price': 500000, + 'cost': 500000, + }, + 'info': '', }, - "TRST/BTC": { - 'base': 'TRST', + { + 'id': 'tknbtc', + 'symbol': 'TKN/BTC', + 'base': 'TKN', + 'quote': 'BTC', 'active': True, - 'LastChecked': '2017-11-13T20:15:00.00', - 'Notice': None + 'precision': { + 'price': 8, + 'amount': 8, + 'cost': 8, + }, + 'lot': 0.00000001, + 'limits': { + 'amount': { + 'min': 0.01, + 'max': 1000, + }, + 'price': 500000, + 'cost': 500000, + }, + 'info': '', }, - "SWT/BTC": { - 'base': 'SWT', + { + 'id': 'blkbtc', + 'symbol': 'BLK/BTC', + 'base': 'BLK', + 'quote': 'BTC', 'active': True, - 'LastChecked': '2017-11-13T20:15:00.00', - 'Notice': None - }, - "BCC/BTC": { - 'base': 'BCC', - 'active': False, - 'LastChecked': '2017-11-13T20:15:00.00', - 'Notice': None - }}) + 'precision': { + 'price': 8, + 'amount': 8, + 'cost': 8, + }, + 'lot': 0.00000001, + 'limits': { + 'amount': { + 'min': 0.01, + 'max': 1000, + }, + 'price': 500000, + 'cost': 500000, + }, + 'info': '', + } + ]) + + +@pytest.fixture +def markets_empty(): + return MagicMock(return_value=[]) @pytest.fixture @@ -334,3 +382,4 @@ def result(): # that inserts a trade of some type and open-status # return the open-order-id # See tests in rpc/main that could use this + diff --git a/freqtrade/tests/test_acl_pair.py b/freqtrade/tests/test_acl_pair.py index 174f1fde9..fecf3a9f3 100644 --- a/freqtrade/tests/test_acl_pair.py +++ b/freqtrade/tests/test_acl_pair.py @@ -26,81 +26,12 @@ def whitelist_conf(): return config -def get_market_summaries(): - return { - 'TKN/BTC': { - 'symbol': 'TKN/BTC', - 'info': { - 'High': 0.00000919, - 'Low': 0.00000820, - 'Volume': 74339.61396015, - 'Last': 0.00000820, - 'BaseVolume': 1664, - 'TimeStamp': '2014-07-09T07:19:30.15', - 'Bid': 0.00000820, - 'Ask': 0.00000831, - 'OpenBuyOrders': 15, - 'OpenSellOrders': 15, - 'PrevDay': 0.00000821, - 'Created': '2014-03-20T06:00:00', - 'DisplayMarketName': '' - } - }, - 'ETH/BTC': { - 'symbol': 'ETH/BTC', - 'info': { - 'High': 0.00000072, - 'Low': 0.00000001, - 'Volume': 166340678.42280999, - 'Last': 0.00000005, - 'BaseVolume': 42, - 'TimeStamp': '2014-07-09T07:21:40.51', - 'Bid': 0.00000004, - 'Ask': 0.00000005, - 'OpenBuyOrders': 18, - 'OpenSellOrders': 18, - 'PrevDay': 0.00000002, - 'Created': '2014-05-30T07:57:49.637', - 'DisplayMarketName': '' - } - }, - 'BLK/BTC': { - 'symbol': 'BLK/BTC', - 'info': { - 'High': 0.00000072, - 'Low': 0.00000001, - 'Volume': 166340678.42280999, - 'Last': 0.00000005, - 'BaseVolume': 3, - 'TimeStamp': '2014-07-09T07:21:40.51', - 'Bid': 0.00000004, - 'Ask': 0.00000005, - 'OpenBuyOrders': 18, - 'OpenSellOrders': 18, - 'PrevDay': 0.00000002, - 'Created': '2014-05-30T07:57:49.637', - 'DisplayMarketName': '' - }} - } - - -def get_health(): - return { - 'ETH/BTC': {'base': 'ETH', 'active': True}, - 'TKN/BTC': {'base': 'TKN', 'active': True}, - 'BLK/BTC': {'base': 'BLK', 'active': True}} - - -def get_health_empty(): - return {} - - -def test_refresh_market_pair_not_in_whitelist(mocker): +def test_refresh_market_pair_not_in_whitelist(mocker, markets): conf = whitelist_conf() freqtradebot = tt.get_patched_freqtradebot(mocker, conf) - mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health) + mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets) refreshedwhitelist = freqtradebot._refresh_whitelist( conf['exchange']['pair_whitelist'] + ['XXX/BTC'] ) @@ -110,11 +41,11 @@ def test_refresh_market_pair_not_in_whitelist(mocker): assert whitelist == refreshedwhitelist -def test_refresh_whitelist(mocker): +def test_refresh_whitelist(mocker, markets): conf = whitelist_conf() freqtradebot = tt.get_patched_freqtradebot(mocker, conf) - mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health) + mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets) refreshedwhitelist = freqtradebot._refresh_whitelist(conf['exchange']['pair_whitelist']) # List ordered by BaseVolume @@ -123,14 +54,10 @@ def test_refresh_whitelist(mocker): assert whitelist == refreshedwhitelist -def test_refresh_whitelist_dynamic(mocker): +def test_refresh_whitelist_dynamic(mocker, markets): conf = whitelist_conf() freqtradebot = tt.get_patched_freqtradebot(mocker, conf) - mocker.patch.multiple( - 'freqtrade.freqtradebot.exchange', - get_wallet_health=get_health, - get_market_summaries=get_market_summaries - ) + mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets) # argument: use the whitelist dynamically by exchange-volume whitelist = ['TKN/BTC', 'ETH/BTC'] @@ -142,10 +69,10 @@ def test_refresh_whitelist_dynamic(mocker): assert whitelist == refreshedwhitelist -def test_refresh_whitelist_dynamic_empty(mocker): +def test_refresh_whitelist_dynamic_empty(mocker, markets_empty): conf = whitelist_conf() freqtradebot = tt.get_patched_freqtradebot(mocker, conf) - mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health_empty) + mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets_empty) # argument: use the whitelist dynamically by exchange-volume whitelist = [] diff --git a/freqtrade/tests/test_freqtradebot.py b/freqtrade/tests/test_freqtradebot.py index 3792fd88d..2548faac3 100644 --- a/freqtrade/tests/test_freqtradebot.py +++ b/freqtrade/tests/test_freqtradebot.py @@ -201,15 +201,12 @@ def test_throttle_with_assets(mocker, default_conf) -> None: assert result == -1 -def test_gen_pair_whitelist(mocker, default_conf, get_market_summaries_data) -> None: +def test_gen_pair_whitelist(mocker, default_conf, markets) -> None: """ Test _gen_pair_whitelist() method """ freqtrade = get_patched_freqtradebot(mocker, default_conf) - mocker.patch( - 'freqtrade.freqtradebot.exchange.get_market_summaries', - return_value=get_market_summaries_data - ) + mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets) # Test to retrieved BTC sorted on BaseVolume whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC') @@ -392,7 +389,7 @@ def test_create_trade_no_signal(default_conf, mocker) -> None: def test_process_trade_creation(default_conf, ticker, limit_buy_order, - health, mocker, caplog) -> None: + markets, mocker, caplog) -> None: """ Test the trade creation in _process() method """ @@ -403,7 +400,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, 'freqtrade.freqtradebot.exchange', validate_pairs=MagicMock(), get_ticker=ticker, - get_wallet_health=health, + get_markets=markets, buy=MagicMock(return_value='mocked_limit_buy'), get_order=MagicMock(return_value=limit_buy_order) ) @@ -432,7 +429,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, ) -def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None: +def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> None: """ Test _process() method when a RequestException happens """ @@ -443,7 +440,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None 'freqtrade.freqtradebot.exchange', validate_pairs=MagicMock(), get_ticker=ticker, - get_wallet_health=health, + get_markets=markets, buy=MagicMock(side_effect=requests.exceptions.RequestException) ) sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None) @@ -454,7 +451,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None assert sleep_mock.has_calls() -def test_process_operational_exception(default_conf, ticker, health, mocker) -> None: +def test_process_operational_exception(default_conf, ticker, markets, mocker) -> None: """ Test _process() method when an OperationalException happens """ @@ -465,7 +462,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker) -> 'freqtrade.freqtradebot.exchange', validate_pairs=MagicMock(), get_ticker=ticker, - get_wallet_health=health, + get_markets=markets, buy=MagicMock(side_effect=OperationalException) ) freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://')) @@ -477,7 +474,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker) -> assert 'OperationalException' in msg_mock.call_args_list[-1][0][0] -def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, mocker) -> None: +def test_process_trade_handling(default_conf, ticker, limit_buy_order, markets, mocker) -> None: """ Test _process() """ @@ -488,7 +485,7 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m 'freqtrade.freqtradebot.exchange', validate_pairs=MagicMock(), get_ticker=ticker, - get_wallet_health=health, + get_markets=markets, buy=MagicMock(return_value='mocked_limit_buy'), get_order=MagicMock(return_value=limit_buy_order) )