From 2c976bdd24b00ee448463d3399cc95d9e183d115 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 17 Nov 2019 14:56:08 +0100 Subject: [PATCH 1/5] Add show_config endpoint --- freqtrade/rpc/api_server.py | 10 ++++++++++ freqtrade/rpc/rpc.py | 20 ++++++++++++++++++++ scripts/rest_client.py | 7 +++++++ tests/rpc/test_rpc_apiserver.py | 12 ++++++++++++ 4 files changed, 49 insertions(+) diff --git a/freqtrade/rpc/api_server.py b/freqtrade/rpc/api_server.py index 3b59c9592..0426eb598 100644 --- a/freqtrade/rpc/api_server.py +++ b/freqtrade/rpc/api_server.py @@ -169,6 +169,8 @@ class ApiServer(RPC): view_func=self._status, methods=['GET']) self.app.add_url_rule(f'{BASE_URI}/version', 'version', view_func=self._version, methods=['GET']) + self.app.add_url_rule(f'{BASE_URI}/show_config', 'show_config', + view_func=self._show_config, methods=['GET']) self.app.add_url_rule(f'{BASE_URI}/ping', 'ping', view_func=self._ping, methods=['GET']) @@ -241,6 +243,14 @@ class ApiServer(RPC): """ return self.rest_dump({"version": __version__}) + @require_login + @rpc_catch_errors + def _show_config(self): + """ + Prints the bot's version + """ + return self.rest_dump(self._rpc_show_config()) + @require_login @rpc_catch_errors def _reload_conf(self): diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 5ab92cf33..c78951a6d 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -80,6 +80,26 @@ class RPC: def send_msg(self, msg: Dict[str, str]) -> None: """ Sends a message to all registered rpc modules """ + def _rpc_show_config(self) -> Dict: + """ + Return a dict of config options. + Explicitly does NOT return the full config to avoid leakage of sensitive + information via rpc. + """ + config = self._freqtrade.config + val = { + 'dry_run': config.get('dry_run', False), + 'stake_currency': config['stake_currency'], + 'stake_amount': config['stake_amount'], + 'minimal_roi': config['minimal_roi'].copy(), + 'stoploss': config['stoploss'], + 'trailing_stop': config['trailing_stop'], + 'ticker_interval': config['ticker_interval'], + 'exchange': config['exchange']['name'], + 'strategy': config['strategy'], + } + return val + def _rpc_trade_status(self) -> List[Dict[str, Any]]: """ Below follows the RPC backend it is prefixed with rpc_ to raise awareness that it is diff --git a/scripts/rest_client.py b/scripts/rest_client.py index a46b3ebfb..7408acab8 100755 --- a/scripts/rest_client.py +++ b/scripts/rest_client.py @@ -147,6 +147,13 @@ class FtRestClient(): """ return self._get("version") + def show_config(self): + """ + Returns part of the configuration, relevant for trading operations. + :return: json object containing the version + """ + return self._get("show_config") + def whitelist(self): """ Show the current whitelist diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 6e65cf934..d1ebe961b 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -284,6 +284,18 @@ def test_api_count(botclient, mocker, ticker, fee, markets): assert rc.json["max"] == 1.0 +def test_api_show_config(botclient, mocker): + ftbot, client = botclient + patch_get_signal(ftbot, (True, False)) + + rc = client_get(client, f"{BASE_URI}/show_config") + assert_response(rc) + assert 'dry_run' in rc.json + assert rc.json['exchange'] == 'bittrex' + assert rc.json['ticker_interval'] == '5m' + assert not rc.json['trailing_stop'] + + def test_api_daily(botclient, mocker, ticker, fee, markets): ftbot, client = botclient patch_get_signal(ftbot, (True, False)) From acab56793f1253dc46252a3bf6afafd6081c453a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 17 Nov 2019 15:03:45 +0100 Subject: [PATCH 2/5] Add /show_config to telegram --- freqtrade/rpc/telegram.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 8a81848ac..ba475e39e 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -101,6 +101,7 @@ class Telegram(RPC): CommandHandler('edge', self._edge), CommandHandler('help', self._help), CommandHandler('version', self._version), + CommandHandler('show_config', self._show_config), ] for handle in handles: self._updater.dispatcher.add_handler(handle) @@ -550,6 +551,7 @@ class Telegram(RPC): "*/balance:* `Show account balance per currency`\n" \ "*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" \ "*/reload_conf:* `Reload configuration file` \n" \ + "*/show_config:* `Show running configuration` \n" \ "*/whitelist:* `Show current whitelist` \n" \ "*/blacklist [pair]:* `Show current blacklist, or adds one or more pairs " \ "to the blacklist.` \n" \ @@ -570,6 +572,26 @@ class Telegram(RPC): """ self._send_msg('*Version:* `{}`'.format(__version__)) + @authorized_only + def _show_config(self, update: Update, context: CallbackContext) -> None: + """ + Handler for /show_config. + Show config information information + :param bot: telegram bot + :param update: message update + :return: None + """ + val = self._rpc_show_config() + self._send_msg( + f"*Mode:* `{'Dry-run' if val['dry_run'] else 'Live'}`\n" + f"*Exchange:* `{val['exchange']}`\n" + f"*Stake per trade:* `{val['stake_amount']} {val['stake_currency']}`\n" + f"*Minimum ROI:* `{val['minimal_roi']}`\n" + f"*{'Trailing ' if val['trailing_stop'] else ''}Stoploss:* `{val['stoploss']}`\n" + f"*Ticker Interval:* `{val['ticker_interval']}`\n" + f"*Strategy:* `{val['strategy']}`'" + ) + def _send_msg(self, msg: str, parse_mode: ParseMode = ParseMode.MARKDOWN) -> None: """ Send given markdown message From 2b190e5638d8f65b92d3b3ef75bb34324bc8db35 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 17 Nov 2019 15:05:56 +0100 Subject: [PATCH 3/5] Add documentation --- docs/rest-api.md | 5 +++++ docs/telegram-usage.md | 1 + 2 files changed, 6 insertions(+) diff --git a/docs/rest-api.md b/docs/rest-api.md index 70e090569..187a71c97 100644 --- a/docs/rest-api.md +++ b/docs/rest-api.md @@ -106,6 +106,7 @@ python3 scripts/rest_client.py --config rest_config.json [optional par | `stop` | | Stops the trader | `stopbuy` | | Stops the trader from opening new trades. Gracefully closes open trades according to their rules. | `reload_conf` | | Reloads the configuration file +| `show_config` | | Shows part of the current configuration with relevant settings to operation | `status` | | Lists all open trades | `count` | | Displays number of trades used and available | `profit` | | Display a summary of your profit/loss from close trades and some stats about your performance @@ -172,6 +173,10 @@ reload_conf Reload configuration :returns: json object +show_config + Returns part of the configuration, relevant for trading operations. + :return: json object containing the version + start Start the bot if it's in stopped state. :returns: json object diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 424b55faf..ed0c21a6e 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -53,6 +53,7 @@ official commands. You can ask at any moment for help with `/help`. | `/stop` | | Stops the trader | `/stopbuy` | | Stops the trader from opening new trades. Gracefully closes open trades according to their rules. | `/reload_conf` | | Reloads the configuration file +| `/show_config` | | Shows part of the current configuration with relevant settings to operation | `/status` | | Lists all open trades | `/status table` | | List all open trades in a table format | `/count` | | Displays number of trades used and available From e4e8a611be888e657ebdd5f7c5b61ac71846d388 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 17 Nov 2019 15:12:53 +0100 Subject: [PATCH 4/5] Add tests for telegram --- freqtrade/rpc/rpc.py | 5 ++++- tests/rpc/test_rpc_telegram.py | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index c78951a6d..8b557df96 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -80,7 +80,7 @@ class RPC: def send_msg(self, msg: Dict[str, str]) -> None: """ Sends a message to all registered rpc modules """ - def _rpc_show_config(self) -> Dict: + def _rpc_show_config(self) -> Dict[str, Any]: """ Return a dict of config options. Explicitly does NOT return the full config to avoid leakage of sensitive @@ -94,6 +94,9 @@ class RPC: 'minimal_roi': config['minimal_roi'].copy(), 'stoploss': config['stoploss'], 'trailing_stop': config['trailing_stop'], + 'trailing_stop_positive': config.get('trailing_stop_positive'), + 'trailing_stop_positive_offset': config.get('trailing_stop_positive_offset'), + 'trailing_only_offset_is_reached': config.get('trailing_only_offset_is_reached'), 'ticker_interval': config['ticker_interval'], 'exchange': config['exchange']['name'], 'strategy': config['strategy'], diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 766511d2d..73b38b808 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1174,6 +1174,23 @@ def test_version_handle(default_conf, update, mocker) -> None: assert '*Version:* `{}`'.format(__version__) in msg_mock.call_args_list[0][0][0] +def test_show_config_handle(default_conf, update, mocker) -> None: + 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._show_config(update=update, context=MagicMock()) + assert msg_mock.call_count == 1 + assert '*Mode:* `{}`'.format('Dry-run') in msg_mock.call_args_list[0][0][0] + assert '*Exchange:* `bittrex`' in msg_mock.call_args_list[0][0][0] + assert '*Strategy:* `DefaultStrategy`' in msg_mock.call_args_list[0][0][0] + + def test_send_msg_buy_notification(default_conf, mocker) -> None: msg_mock = MagicMock() mocker.patch.multiple( From 547d65b06511515952dfa49156c4ab3ccbd75267 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 17 Nov 2019 15:22:14 +0100 Subject: [PATCH 5/5] Fix broken test --- freqtrade/rpc/telegram.py | 2 +- tests/rpc/test_rpc_telegram.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index ba475e39e..0547af7b0 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -95,13 +95,13 @@ class Telegram(RPC): CommandHandler('daily', self._daily), CommandHandler('count', self._count), CommandHandler('reload_conf', self._reload_conf), + CommandHandler('show_config', self._show_config), CommandHandler('stopbuy', self._stopbuy), CommandHandler('whitelist', self._whitelist), CommandHandler('blacklist', self._blacklist), CommandHandler('edge', self._edge), CommandHandler('help', self._help), CommandHandler('version', self._version), - CommandHandler('show_config', self._show_config), ] for handle in handles: self._updater.dispatcher.add_handler(handle) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 73b38b808..c6a8094ab 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -73,7 +73,7 @@ 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'], " \ + "['performance'], ['daily'], ['count'], ['reload_conf'], ['show_config'], " \ "['stopbuy'], ['whitelist'], ['blacklist'], ['edge'], ['help'], ['version']]" assert log_has(message_str, caplog)