From 6d40814dbf3059fe8c23bede6a98d433ecd15651 Mon Sep 17 00:00:00 2001 From: Andreas Brunner Date: Sun, 17 Jan 2021 20:39:35 +0100 Subject: [PATCH 1/6] extend status bot command to query specific trades --- freqtrade/rpc/rpc.py | 10 +++++++--- freqtrade/rpc/telegram.py | 8 +++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 1e304f01b..03108b0f4 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -144,13 +144,17 @@ class RPC: } return val - def _rpc_trade_status(self) -> List[Dict[str, Any]]: + def _rpc_trade_status(self, trade_ids=None) -> List[Dict[str, Any]]: """ Below follows the RPC backend it is prefixed with rpc_ to raise awareness that it is a remotely exposed function """ - # Fetch open trade - trades = Trade.get_open_trades() + # Fetch open trades + if trade_ids: + trades = Trade.get_trades(trade_filter=Trade.id.in_(trade_ids)) + else: + trades = Trade.get_open_trades() + if not trades: raise RPCException('no active trade') else: diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 7ec67e5d0..d304188c2 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -277,7 +277,13 @@ class Telegram(RPCHandler): return try: - results = self._rpc._rpc_trade_status() + + # Check if there's at least one numerical ID provided. If so, try to get only these trades. + trade_ids = None + if context.args and len(context.args) > 0: + trade_ids = [i for i in context.args if i.isnumeric()] + + results = self._rpc._rpc_trade_status(trade_ids=trade_ids) messages = [] for r in results: From 3ea33d1737ee82750d4d6b4d1707f6cc49d27cf1 Mon Sep 17 00:00:00 2001 From: Andreas Brunner Date: Sun, 17 Jan 2021 21:15:17 +0100 Subject: [PATCH 2/6] updating doc and help with new /status argument --- README.md | 2 +- docs/telegram-usage.md | 1 + freqtrade/rpc/telegram.py | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1031e4d67..c61116219 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Telegram is not mandatory. However, this is a great way to control your bot. Mor - `/start`: Starts the trader. - `/stop`: Stops the trader. - `/stopbuy`: Stop entering new trades. -- `/status [table]`: Lists all open trades. +- `/status |[table]`: Lists all or specific open trades. - `/profit`: Lists cumulative profit from all finished trades - `/forcesell |all`: Instantly sells the given trade (Ignoring `minimum_roi`). - `/performance`: Show performance of each finished trade grouped by pair diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 40481684d..57f2e98bd 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -137,6 +137,7 @@ official commands. You can ask at any moment for help with `/help`. | `/show_config` | Shows part of the current configuration with relevant settings to operation | `/logs [limit]` | Show last log messages. | `/status` | Lists all open trades +| `/status ` | Lists one or more specific trade. Separate multiple with a blank space. | `/status table` | List all open trades in a table format. Pending buy orders are marked with an asterisk (*) Pending sell orders are marked with a double asterisk (**) | `/trades [limit]` | List all recently closed trades in a table format. | `/delete ` | Delete a specific trade from the Database. Tries to close open orders. Requires manual handling of this trade on the exchange. diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index d304188c2..abdaa948d 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -821,7 +821,9 @@ class Telegram(RPCHandler): "Optionally takes a rate at which to buy.` \n") message = ("*/start:* `Starts the trader`\n" "*/stop:* `Stops the trader`\n" - "*/status [table]:* `Lists all open trades`\n" + "*/status |[table]:* `Lists all open trades`\n" + " * :* `Lists one or more specific trades.`\n" + " `Separate multiple with a blank space.`\n" " *table :* `will display trades in a table`\n" " `pending buy orders are marked with an asterisk (*)`\n" " `pending sell orders are marked with a double asterisk (**)`\n" From d21eff0d5231ca49c4a7a7544b6bc17e1137dbbb Mon Sep 17 00:00:00 2001 From: Andreas Brunner Date: Sun, 17 Jan 2021 21:21:31 +0100 Subject: [PATCH 3/6] fix, if an non existing trade_id is provided --- freqtrade/rpc/rpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 03108b0f4..69e3d057d 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -151,7 +151,7 @@ class RPC: """ # Fetch open trades if trade_ids: - trades = Trade.get_trades(trade_filter=Trade.id.in_(trade_ids)) + trades = Trade.get_trades(trade_filter=Trade.id.in_(trade_ids)).all() else: trades = Trade.get_open_trades() From eb95d970e9b029cb7b9778be1732f96e677cacfe Mon Sep 17 00:00:00 2001 From: Andreas Brunner Date: Sun, 17 Jan 2021 21:26:55 +0100 Subject: [PATCH 4/6] flake8 beautify --- freqtrade/rpc/telegram.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index abdaa948d..c310f9803 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -278,7 +278,8 @@ class Telegram(RPCHandler): try: - # Check if there's at least one numerical ID provided. If so, try to get only these trades. + # Check if there's at least one numerical ID provided. + # If so, try to get only these trades. trade_ids = None if context.args and len(context.args) > 0: trade_ids = [i for i in context.args if i.isnumeric()] From a68a546dd9fca6b1cf4abb67f4a4036280251bf8 Mon Sep 17 00:00:00 2001 From: Andreas Brunner Date: Mon, 18 Jan 2021 15:26:53 +0100 Subject: [PATCH 5/6] _rpc_trade_status argument datatype optimizations --- freqtrade/rpc/rpc.py | 2 +- freqtrade/rpc/telegram.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 69e3d057d..f74d63408 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -144,7 +144,7 @@ class RPC: } return val - def _rpc_trade_status(self, trade_ids=None) -> List[Dict[str, Any]]: + def _rpc_trade_status(self, trade_ids: List[int] = []) -> List[Dict[str, Any]]: """ Below follows the RPC backend it is prefixed with rpc_ to raise awareness that it is a remotely exposed function diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index c310f9803..99f9a8a91 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -280,9 +280,9 @@ class Telegram(RPCHandler): # Check if there's at least one numerical ID provided. # If so, try to get only these trades. - trade_ids = None + trade_ids = [] if context.args and len(context.args) > 0: - trade_ids = [i for i in context.args if i.isnumeric()] + trade_ids = [int(i) for i in context.args if i.isnumeric()] results = self._rpc._rpc_trade_status(trade_ids=trade_ids) From cd8d4da46696d64033e9d3a963d61948b2ee3cd3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 19 Jan 2021 19:44:16 +0100 Subject: [PATCH 6/6] Add test for /status functionality --- tests/rpc/test_rpc_telegram.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index a21a19e3a..1c34b6b26 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -205,13 +205,14 @@ def test_telegram_status(default_conf, update, mocker) -> None: assert msg_mock.call_count == 1 context = MagicMock() - # /status table 2 3 - context.args = ["table", "2", "3"] + # /status table + context.args = ["table"] telegram._status(update=update, context=context) assert status_table.call_count == 1 def test_status_handle(default_conf, update, ticker, fee, mocker) -> None: + default_conf['max_open_trades'] = 3 mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, @@ -252,8 +253,23 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None: assert 'Close Rate' not in ''.join(lines) assert 'Close Profit' not in ''.join(lines) - assert msg_mock.call_count == 1 + assert msg_mock.call_count == 3 assert 'ETH/BTC' in msg_mock.call_args_list[0][0][0] + assert 'LTC/BTC' in msg_mock.call_args_list[1][0][0] + + msg_mock.reset_mock() + context = MagicMock() + context.args = ["2", "3"] + + telegram._status(update=update, context=context) + + lines = msg_mock.call_args_list[0][0][0].split('\n') + assert '' not in lines + assert 'Close Rate' not in ''.join(lines) + assert 'Close Profit' not in ''.join(lines) + + assert msg_mock.call_count == 2 + assert 'LTC/BTC' in msg_mock.call_args_list[0][0][0] def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None: