diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 4a17e889e..eb92375ec 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -140,7 +140,7 @@ class FreqtradeBot(object): f'*Strategy:* `{strategy_name}`' }) if self.config.get('dynamic_whitelist', False): - top_pairs = 'top ' + str(self.config.get('dynamic_whitelist', 20)) + top_pairs = 'top volume ' + str(self.config.get('dynamic_whitelist', 20)) specific_pairs = '' else: top_pairs = 'whitelisted' diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 7e7b60ebc..50cbd27ef 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -443,3 +443,10 @@ class RPC(object): raise RPCException('trader is not running') return Trade.query.filter(Trade.is_open.is_(True)).all() + + def _rpc_whitelist(self) -> Dict: + """ Returns the currently active whitelist""" + res = {'method': self._freqtrade.config.get('dynamic_whitelist', 0) or 'static', + 'whitelist': self._freqtrade.active_pair_whitelist + } + return res diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index eaabd35c6..55c5abef2 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -91,6 +91,7 @@ class Telegram(RPC): CommandHandler('daily', self._daily), CommandHandler('count', self._count), CommandHandler('reload_conf', self._reload_conf), + CommandHandler('whitelist', self._whitelist), CommandHandler('help', self._help), CommandHandler('version', self._version), ] @@ -438,6 +439,25 @@ class Telegram(RPC): except RPCException as e: self._send_msg(str(e), bot=bot) + @authorized_only + def _whitelist(self, bot: Bot, update: Update) -> None: + """ + Handler for /whitelist + Shows the currently active whitelist + """ + try: + whitelist = self._rpc_whitelist() + if whitelist['method'] == 'static': + message = f"Using static whitelist with `{len(whitelist['whitelist'])}` pairs \n" + else: + message = f"Dynamic whitelist with `{whitelist['method']}` pairs\n" + message += f"`{', '.join(whitelist['whitelist'])}`" + + logger.debug(message) + self._send_msg(message) + except RPCException as e: + self._send_msg(str(e), bot=bot) + @authorized_only def _help(self, bot: Bot, update: Update) -> None: """ @@ -460,6 +480,7 @@ class Telegram(RPC): "\n" \ "*/balance:* `Show account balance per currency`\n" \ "*/reload_conf:* `Reload configuration file` \n" \ + "*/whitelist:* `Show current whitelist` \n" \ "*/help:* `This help message`\n" \ "*/version:* `Show version`" diff --git a/freqtrade/tests/rpc/test_rpc.py b/freqtrade/tests/rpc/test_rpc.py index 19692db50..ff72ef634 100644 --- a/freqtrade/tests/rpc/test_rpc.py +++ b/freqtrade/tests/rpc/test_rpc.py @@ -645,3 +645,28 @@ def test_rpcforcebuy_disabled(mocker, default_conf) -> None: pair = 'ETH/BTC' with pytest.raises(RPCException, match=r'Forcebuy not enabled.'): rpc._rpc_forcebuy(pair, None) + + +def test_rpc_whitelist(mocker, default_conf) -> None: + patch_coinmarketcap(mocker) + patch_exchange(mocker) + mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) + + freqtradebot = FreqtradeBot(default_conf) + rpc = RPC(freqtradebot) + ret = rpc._rpc_whitelist() + assert ret['method'] == 'static' + assert ret['whitelist'] == default_conf['exchange']['pair_whitelist'] + + +def test_rpc_whitelist_dynamic(mocker, default_conf) -> None: + patch_coinmarketcap(mocker) + patch_exchange(mocker) + default_conf['dynamic_whitelist'] = 4 + mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) + + freqtradebot = FreqtradeBot(default_conf) + rpc = RPC(freqtradebot) + ret = rpc._rpc_whitelist() + assert ret['method'] == 4 + assert ret['whitelist'] == default_conf['exchange']['pair_whitelist'] diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py index 097fc1ff2..a8e8bf003 100644 --- a/freqtrade/tests/rpc/test_rpc_telegram.py +++ b/freqtrade/tests/rpc/test_rpc_telegram.py @@ -72,7 +72,8 @@ def test_init(default_conf, mocker, caplog) -> None: message_str = "rpc.telegram is listening for following commands: [['status'], ['profit'], " \ "['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], " \ - "['performance'], ['daily'], ['count'], ['reload_conf'], ['help'], ['version']]" + "['performance'], ['daily'], ['count'], ['reload_conf'], " \ + "['whitelist'], ['help'], ['version']]" assert log_has(message_str, caplog.record_tuples) @@ -1006,6 +1007,43 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non assert msg in msg_mock.call_args_list[0][0][0] +def test_whitelist_static(default_conf, update, mocker) -> None: + patch_coinmarketcap(mocker) + msg_mock = MagicMock() + mocker.patch.multiple( + 'freqtrade.rpc.telegram.Telegram', + _init=MagicMock(), + _send_msg=msg_mock + ) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) + + telegram = Telegram(freqtradebot) + + telegram._whitelist(bot=MagicMock(), update=update) + assert msg_mock.call_count == 1 + assert ('Using static whitelist with `4` pairs \n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`' + in msg_mock.call_args_list[0][0][0]) + + +def test_whitelist_dynamic(default_conf, update, mocker) -> None: + patch_coinmarketcap(mocker) + msg_mock = MagicMock() + mocker.patch.multiple( + 'freqtrade.rpc.telegram.Telegram', + _init=MagicMock(), + _send_msg=msg_mock + ) + default_conf['dynamic_whitelist'] = 4 + freqtradebot = get_patched_freqtradebot(mocker, default_conf) + + telegram = Telegram(freqtradebot) + + telegram._whitelist(bot=MagicMock(), update=update) + assert msg_mock.call_count == 1 + assert ('Dynamic whitelist with `4` pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`' + in msg_mock.call_args_list[0][0][0]) + + def test_help_handle(default_conf, update, mocker) -> None: patch_coinmarketcap(mocker) msg_mock = MagicMock()