From dd3a2675b53c30e9f3ff23e9799d2cfd41352fb0 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Sun, 19 Jul 2020 22:02:53 +0700 Subject: [PATCH 01/11] Add telegram trades command to list recent trades --- freqtrade/rpc/telegram.py | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 13cc1afaf..72dbd2ea7 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -92,6 +92,7 @@ class Telegram(RPC): CommandHandler('stop', self._stop), CommandHandler('forcesell', self._forcesell), CommandHandler('forcebuy', self._forcebuy), + CommandHandler('trades', self._trades), CommandHandler('performance', self._performance), CommandHandler('daily', self._daily), CommandHandler('count', self._count), @@ -496,6 +497,48 @@ class Telegram(RPC): except RPCException as e: self._send_msg(str(e)) + @authorized_only + def _trades(self, update: Update, context: CallbackContext) -> None: + """ + Handler for /trades + Returns last n recent trades. + :param bot: telegram bot + :param update: message update + :return: None + """ + stake_cur = self._config['stake_currency'] + fiat_disp_cur = self._config.get('fiat_display_currency', '') + try: + nrecent = int(context.args[0]) + except (TypeError, ValueError, IndexError): + nrecent = 10 + try: + trades = self._rpc_trade_history( + nrecent + ) + trades_tab = tabulate( + [[trade['open_date'], + trade['pair'], + f"{trade['open_rate']}", + f"{trade['stake_amount']}", + trade['close_date'], + f"{trade['close_rate']}", + f"{trade['close_profit_abs']}"] for trade in trades['trades']], + headers=[ + 'Open Date', + 'Pair', + 'Open rate', + 'Stake Amount', + 'Close date', + 'Close rate', + 'Profit', + ], + tablefmt='simple') + message = f'{nrecent} recent trades:\n
{trades_tab}
' + self._send_msg(message, parse_mode=ParseMode.HTML) + except RPCException as e: + self._send_msg(str(e)) + @authorized_only def _performance(self, update: Update, context: CallbackContext) -> None: """ From 08fdd7d86331c5a2c55c69c130350a7b21a104e3 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Sun, 19 Jul 2020 22:10:59 +0700 Subject: [PATCH 02/11] Add telegram /delete command to delete tradeid code inspired from _rpc_forcesell --- freqtrade/rpc/rpc.py | 22 ++++++++++++++++++++++ freqtrade/rpc/telegram.py | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index c73fcbf54..2a3feea25 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -537,6 +537,28 @@ class RPC: else: return None + def _rpc_delete(self, trade_id: str) -> Dict[str, str]: + """ + Handler for delete . + Delete the given trade + """ + def _exec_delete(trade: Trade) -> None: + Trade.session.delete(trade) + Trade.session.flush() + + with self._freqtrade._sell_lock: + trade = Trade.get_trades( + trade_filter=[Trade.id == trade_id, ] + ).first() + if not trade: + logger.warning('delete: Invalid argument received') + raise RPCException('invalid argument') + + _exec_delete(trade) + Trade.session.flush() + self._freqtrade.wallets.update() + return {'result': f'Deleted trade {trade_id}.'} + def _rpc_performance(self) -> List[Dict[str, Any]]: """ Handler for performance. diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 72dbd2ea7..474376938 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -93,6 +93,7 @@ class Telegram(RPC): CommandHandler('forcesell', self._forcesell), CommandHandler('forcebuy', self._forcebuy), CommandHandler('trades', self._trades), + CommandHandler('delete', self._delete), CommandHandler('performance', self._performance), CommandHandler('daily', self._daily), CommandHandler('count', self._count), @@ -497,6 +498,24 @@ class Telegram(RPC): except RPCException as e: self._send_msg(str(e)) + @authorized_only + def _delete(self, update: Update, context: CallbackContext) -> None: + """ + Handler for /delete . + Delete the given trade + :param bot: telegram bot + :param update: message update + :return: None + """ + + trade_id = context.args[0] if len(context.args) > 0 else None + try: + msg = self._rpc_delete(trade_id) + self._send_msg('Delete Result: `{result}`'.format(**msg)) + + except RPCException as e: + self._send_msg(str(e)) + @authorized_only def _trades(self, update: Update, context: CallbackContext) -> None: """ From 28f4a1101e58e38df1fddc22ff573e852a80de33 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Mon, 20 Jul 2020 10:54:17 +0700 Subject: [PATCH 03/11] Revert "Add telegram /delete command to delete tradeid" This reverts commit 08fdd7d86331c5a2c55c69c130350a7b21a104e3. --- freqtrade/rpc/rpc.py | 22 ---------------------- freqtrade/rpc/telegram.py | 19 ------------------- 2 files changed, 41 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 2a3feea25..c73fcbf54 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -537,28 +537,6 @@ class RPC: else: return None - def _rpc_delete(self, trade_id: str) -> Dict[str, str]: - """ - Handler for delete . - Delete the given trade - """ - def _exec_delete(trade: Trade) -> None: - Trade.session.delete(trade) - Trade.session.flush() - - with self._freqtrade._sell_lock: - trade = Trade.get_trades( - trade_filter=[Trade.id == trade_id, ] - ).first() - if not trade: - logger.warning('delete: Invalid argument received') - raise RPCException('invalid argument') - - _exec_delete(trade) - Trade.session.flush() - self._freqtrade.wallets.update() - return {'result': f'Deleted trade {trade_id}.'} - def _rpc_performance(self) -> List[Dict[str, Any]]: """ Handler for performance. diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 474376938..72dbd2ea7 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -93,7 +93,6 @@ class Telegram(RPC): CommandHandler('forcesell', self._forcesell), CommandHandler('forcebuy', self._forcebuy), CommandHandler('trades', self._trades), - CommandHandler('delete', self._delete), CommandHandler('performance', self._performance), CommandHandler('daily', self._daily), CommandHandler('count', self._count), @@ -498,24 +497,6 @@ class Telegram(RPC): except RPCException as e: self._send_msg(str(e)) - @authorized_only - def _delete(self, update: Update, context: CallbackContext) -> None: - """ - Handler for /delete . - Delete the given trade - :param bot: telegram bot - :param update: message update - :return: None - """ - - trade_id = context.args[0] if len(context.args) > 0 else None - try: - msg = self._rpc_delete(trade_id) - self._send_msg('Delete Result: `{result}`'.format(**msg)) - - except RPCException as e: - self._send_msg(str(e)) - @authorized_only def _trades(self, update: Update, context: CallbackContext) -> None: """ From 4c97527b041234d6865d24fb490963b1c17b88ea Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 20 Jul 2020 19:11:15 +0200 Subject: [PATCH 04/11] FIx failing test --- freqtrade/rpc/telegram.py | 2 -- tests/rpc/test_rpc_telegram.py | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 72dbd2ea7..343b26072 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -506,8 +506,6 @@ class Telegram(RPC): :param update: message update :return: None """ - stake_cur = self._config['stake_currency'] - fiat_disp_cur = self._config.get('fiat_display_currency', '') try: nrecent = int(context.args[0]) except (TypeError, ValueError, IndexError): diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 0a4352f5b..1ea211584 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -60,7 +60,7 @@ def test__init__(default_conf, mocker) -> None: assert telegram._config == default_conf -def test_init(default_conf, mocker, caplog) -> None: +def test_telegram_init(default_conf, mocker, caplog) -> None: start_polling = MagicMock() mocker.patch('freqtrade.rpc.telegram.Updater', MagicMock(return_value=start_polling)) @@ -72,7 +72,7 @@ def test_init(default_conf, mocker, caplog) -> None: assert start_polling.start_polling.call_count == 1 message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], " - "['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], " + "['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], ['trades'], " "['performance'], ['daily'], ['count'], ['reload_config', 'reload_conf'], " "['show_config', 'show_conf'], ['stopbuy'], ['whitelist'], ['blacklist'], " "['edge'], ['help'], ['version']]") From 0502fe0496382e6cc2a04161ad3a15f4f9f40e26 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Thu, 23 Jul 2020 09:36:05 +0700 Subject: [PATCH 05/11] New /trades 3 columns and exclude open trades --- freqtrade/rpc/telegram.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 343b26072..87a0cdd62 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -5,6 +5,7 @@ This module manage Telegram communication """ import json import logging +import arrow from typing import Any, Callable, Dict from tabulate import tabulate @@ -506,6 +507,7 @@ class Telegram(RPC): :param update: message update :return: None """ + stake_cur = self._config['stake_currency'] try: nrecent = int(context.args[0]) except (TypeError, ValueError, IndexError): @@ -515,21 +517,13 @@ class Telegram(RPC): nrecent ) trades_tab = tabulate( - [[trade['open_date'], + [[arrow.get(trade['open_date']).humanize(), trade['pair'], - f"{trade['open_rate']}", - f"{trade['stake_amount']}", - trade['close_date'], - f"{trade['close_rate']}", - f"{trade['close_profit_abs']}"] for trade in trades['trades']], + f"{(100 * trade['close_profit']):.2f}% ({trade['close_profit_abs']})"] for trade in trades['trades'] if trade['close_profit'] is not None], headers=[ 'Open Date', 'Pair', - 'Open rate', - 'Stake Amount', - 'Close date', - 'Close rate', - 'Profit', + f'Profit ({stake_cur})', ], tablefmt='simple') message = f'{nrecent} recent trades:\n
{trades_tab}
' From a3daf8e41c209e061a3e50f1b5fcba3802bf6421 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Thu, 23 Jul 2020 09:47:53 +0700 Subject: [PATCH 06/11] Fix line too long --- 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 87a0cdd62..943d092db 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -519,7 +519,8 @@ class Telegram(RPC): trades_tab = tabulate( [[arrow.get(trade['open_date']).humanize(), trade['pair'], - f"{(100 * trade['close_profit']):.2f}% ({trade['close_profit_abs']})"] for trade in trades['trades'] if trade['close_profit'] is not None], + f"{(100 * trade['close_profit']):.2f}% ({trade['close_profit_abs']})"] + for trade in trades['trades'] if trade['close_profit'] is not None], headers=[ 'Open Date', 'Pair', From 0bad55637e5e5907d9133df6973c1926056ac6d0 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Thu, 23 Jul 2020 10:12:52 +0700 Subject: [PATCH 07/11] fix flake8 indent error --- freqtrade/rpc/telegram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 943d092db..66583fa53 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -520,7 +520,7 @@ class Telegram(RPC): [[arrow.get(trade['open_date']).humanize(), trade['pair'], f"{(100 * trade['close_profit']):.2f}% ({trade['close_profit_abs']})"] - for trade in trades['trades'] if trade['close_profit'] is not None], + for trade in trades['trades'] if trade['close_profit'] is not None], headers=[ 'Open Date', 'Pair', From 0f18b2a0d45d3056cd52830f3081b359895bb044 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jul 2020 07:12:14 +0200 Subject: [PATCH 08/11] Add test and fix case where no trades were closed yet --- freqtrade/rpc/telegram.py | 3 ++- tests/rpc/test_rpc_telegram.py | 35 ++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 66583fa53..153be1e25 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -527,7 +527,8 @@ class Telegram(RPC): f'Profit ({stake_cur})', ], tablefmt='simple') - message = f'{nrecent} recent trades:\n
{trades_tab}
' + message = (f"{min(trades['trades_count'], nrecent)} recent trades:\n" + + (f"
{trades_tab}
" if trades['trades_count'] > 0 else '')) self._send_msg(message, parse_mode=ParseMode.HTML) except RPCException as e: self._send_msg(str(e)) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 1ea211584..f011b631d 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -21,8 +21,9 @@ from freqtrade.rpc import RPCMessageType from freqtrade.rpc.telegram import Telegram, authorized_only from freqtrade.state import State from freqtrade.strategy.interface import SellType -from tests.conftest import (get_patched_freqtradebot, log_has, patch_exchange, - patch_get_signal, patch_whitelist) +from tests.conftest import (create_mock_trades, get_patched_freqtradebot, + log_has, patch_exchange, patch_get_signal, + patch_whitelist) class DummyCls(Telegram): @@ -1143,6 +1144,36 @@ def test_edge_enabled(edge_conf, update, mocker) -> None: assert 'Pair Winrate Expectancy Stoploss' in msg_mock.call_args_list[0][0][0] +def test_telegram_trades(mocker, update, default_conf, fee): + 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) + context = MagicMock() + context.args = [] + + telegram._trades(update=update, context=context) + assert "0 recent trades:" in msg_mock.call_args_list[0][0][0] + assert "
" not in msg_mock.call_args_list[0][0][0]
+
+    msg_mock.reset_mock()
+    create_mock_trades(fee)
+
+    context = MagicMock()
+    context.args = [5]
+    telegram._trades(update=update, context=context)
+    msg_mock.call_count == 1
+    assert "3 recent trades:" in msg_mock.call_args_list[0][0][0]
+    assert "Profit (" in msg_mock.call_args_list[0][0][0]
+    assert "Open Date" in msg_mock.call_args_list[0][0][0]
+    assert "
" in msg_mock.call_args_list[0][0][0]
+
+
 def test_help_handle(default_conf, update, mocker) -> None:
     msg_mock = MagicMock()
     mocker.patch.multiple(

From 8300eb59d4b448b4f04da34b80efd603a32a6002 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Thu, 23 Jul 2020 07:49:44 +0200
Subject: [PATCH 09/11] Extend create_mock_trades to create 4 trades

2 closed, and 2 open trades
---
 tests/commands/test_commands.py |  2 +-
 tests/conftest.py               | 14 ++++++++++++++
 tests/data/test_btanalysis.py   |  2 +-
 tests/test_freqtradebot.py      |  2 +-
 tests/test_persistence.py       |  6 +++---
 5 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py
index ffced956d..3ec7e4798 100644
--- a/tests/commands/test_commands.py
+++ b/tests/commands/test_commands.py
@@ -1089,7 +1089,7 @@ def test_show_trades(mocker, fee, capsys, caplog):
     pargs = get_args(args)
     pargs['config'] = None
     start_show_trades(pargs)
-    assert log_has("Printing 3 Trades: ", caplog)
+    assert log_has("Printing 4 Trades: ", caplog)
     captured = capsys.readouterr()
     assert "Trade(id=1" in captured.out
     assert "Trade(id=2" in captured.out
diff --git a/tests/conftest.py b/tests/conftest.py
index 43dc8ca78..fe8d54480 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -199,6 +199,20 @@ def create_mock_trades(fee):
     )
     Trade.session.add(trade)
 
+    trade = Trade(
+        pair='XRP/BTC',
+        stake_amount=0.001,
+        amount=123.0,
+        fee_open=fee.return_value,
+        fee_close=fee.return_value,
+        open_rate=0.05,
+        close_rate=0.06,
+        close_profit=0.01,
+        exchange='bittrex',
+        is_open=False,
+    )
+    Trade.session.add(trade)
+
     # Simulate prod entry
     trade = Trade(
         pair='ETC/BTC',
diff --git a/tests/data/test_btanalysis.py b/tests/data/test_btanalysis.py
index b65db7fd8..718c02f05 100644
--- a/tests/data/test_btanalysis.py
+++ b/tests/data/test_btanalysis.py
@@ -43,7 +43,7 @@ def test_load_trades_from_db(default_conf, fee, mocker):
 
     trades = load_trades_from_db(db_url=default_conf['db_url'])
     assert init_mock.call_count == 1
-    assert len(trades) == 3
+    assert len(trades) == 4
     assert isinstance(trades, DataFrame)
     assert "pair" in trades.columns
     assert "open_time" in trades.columns
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
index ada0d87fd..54e33be4d 100644
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -4090,7 +4090,7 @@ def test_cancel_all_open_orders(mocker, default_conf, fee, limit_buy_order, limi
     freqtrade = get_patched_freqtradebot(mocker, default_conf)
     create_mock_trades(fee)
     trades = Trade.query.all()
-    assert len(trades) == 3
+    assert len(trades) == 4
     freqtrade.cancel_all_open_orders()
     assert buy_mock.call_count == 1
     assert sell_mock.call_count == 1
diff --git a/tests/test_persistence.py b/tests/test_persistence.py
index 8dd27e53a..ab23243a5 100644
--- a/tests/test_persistence.py
+++ b/tests/test_persistence.py
@@ -989,7 +989,7 @@ def test_get_overall_performance(fee):
     create_mock_trades(fee)
     res = Trade.get_overall_performance()
 
-    assert len(res) == 1
+    assert len(res) == 2
     assert 'pair' in res[0]
     assert 'profit' in res[0]
     assert 'count' in res[0]
@@ -1004,5 +1004,5 @@ def test_get_best_pair(fee):
     create_mock_trades(fee)
     res = Trade.get_best_pair()
     assert len(res) == 2
-    assert res[0] == 'ETC/BTC'
-    assert res[1] == 0.005
+    assert res[0] == 'XRP/BTC'
+    assert res[1] == 0.01

From fdc84eef5905d81a69076199990d3e7bf999e938 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Thu, 23 Jul 2020 07:50:45 +0200
Subject: [PATCH 10/11] /trades shall only return closed trades

---
 freqtrade/rpc/rpc.py            |  5 +++--
 freqtrade/rpc/telegram.py       |  2 +-
 tests/rpc/test_rpc.py           | 11 +++++------
 tests/rpc/test_rpc_apiserver.py |  8 ++++----
 tests/rpc/test_rpc_telegram.py  |  2 +-
 5 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py
index c73fcbf54..b39d5aec4 100644
--- a/freqtrade/rpc/rpc.py
+++ b/freqtrade/rpc/rpc.py
@@ -252,9 +252,10 @@ class RPC:
     def _rpc_trade_history(self, limit: int) -> Dict:
         """ Returns the X last trades """
         if limit > 0:
-            trades = Trade.get_trades().order_by(Trade.id.desc()).limit(limit)
+            trades = Trade.get_trades([Trade.is_open.is_(False)]).order_by(
+                Trade.id.desc()).limit(limit)
         else:
-            trades = Trade.get_trades().order_by(Trade.id.desc()).all()
+            trades = Trade.get_trades([Trade.is_open.is_(False)]).order_by(Trade.id.desc()).all()
 
         output = [trade.to_json() for trade in trades]
 
diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py
index 153be1e25..17f0e21f9 100644
--- a/freqtrade/rpc/telegram.py
+++ b/freqtrade/rpc/telegram.py
@@ -520,7 +520,7 @@ class Telegram(RPC):
                 [[arrow.get(trade['open_date']).humanize(),
                   trade['pair'],
                   f"{(100 * trade['close_profit']):.2f}% ({trade['close_profit_abs']})"]
-                 for trade in trades['trades'] if trade['close_profit'] is not None],
+                 for trade in trades['trades']],
                 headers=[
                     'Open Date',
                     'Pair',
diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py
index de9327ba9..e5859fcd9 100644
--- a/tests/rpc/test_rpc.py
+++ b/tests/rpc/test_rpc.py
@@ -284,12 +284,11 @@ def test_rpc_trade_history(mocker, default_conf, markets, fee):
     assert isinstance(trades['trades'][1], dict)
 
     trades = rpc._rpc_trade_history(0)
-    assert len(trades['trades']) == 3
-    assert trades['trades_count'] == 3
-    # The first trade is for ETH ... sorting is descending
-    assert trades['trades'][-1]['pair'] == 'ETH/BTC'
-    assert trades['trades'][0]['pair'] == 'ETC/BTC'
-    assert trades['trades'][1]['pair'] == 'ETC/BTC'
+    assert len(trades['trades']) == 2
+    assert trades['trades_count'] == 2
+    # The first closed trade is for ETC ... sorting is descending
+    assert trades['trades'][-1]['pair'] == 'ETC/BTC'
+    assert trades['trades'][0]['pair'] == 'XRP/BTC'
 
 
 def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index 355b63f48..f4d7b8ca3 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -368,12 +368,12 @@ def test_api_trades(botclient, mocker, ticker, fee, markets):
 
     rc = client_get(client, f"{BASE_URI}/trades")
     assert_response(rc)
-    assert len(rc.json['trades']) == 3
-    assert rc.json['trades_count'] == 3
-    rc = client_get(client, f"{BASE_URI}/trades?limit=2")
-    assert_response(rc)
     assert len(rc.json['trades']) == 2
     assert rc.json['trades_count'] == 2
+    rc = client_get(client, f"{BASE_URI}/trades?limit=1")
+    assert_response(rc)
+    assert len(rc.json['trades']) == 1
+    assert rc.json['trades_count'] == 1
 
 
 def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py
index f011b631d..cfe0ade6f 100644
--- a/tests/rpc/test_rpc_telegram.py
+++ b/tests/rpc/test_rpc_telegram.py
@@ -1168,7 +1168,7 @@ def test_telegram_trades(mocker, update, default_conf, fee):
     context.args = [5]
     telegram._trades(update=update, context=context)
     msg_mock.call_count == 1
-    assert "3 recent trades:" in msg_mock.call_args_list[0][0][0]
+    assert "2 recent trades:" in msg_mock.call_args_list[0][0][0]
     assert "Profit (" in msg_mock.call_args_list[0][0][0]
     assert "Open Date" in msg_mock.call_args_list[0][0][0]
     assert "
" in msg_mock.call_args_list[0][0][0]

From e0c14e6214a79e25d0c6b1d6b189001d89d89e4f Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Thu, 23 Jul 2020 07:54:45 +0200
Subject: [PATCH 11/11] Add /trades to help (so users know about it)

---
 docs/telegram-usage.md    | 1 +
 freqtrade/rpc/telegram.py | 1 +
 2 files changed, 2 insertions(+)

diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md
index f423a9376..250293d25 100644
--- a/docs/telegram-usage.md
+++ b/docs/telegram-usage.md
@@ -56,6 +56,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
 | `/status` | | Lists all open trades
 | `/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.
 | `/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
 | `/forcesell ` | | Instantly sells the given trade  (Ignoring `minimum_roi`).
diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py
index 17f0e21f9..ab784c962 100644
--- a/freqtrade/rpc/telegram.py
+++ b/freqtrade/rpc/telegram.py
@@ -646,6 +646,7 @@ class Telegram(RPC):
                    "         *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"
+                   "*/trades [limit]:* `Lists last closed trades (limited to 10 by default)`\n"
                    "*/profit:* `Lists cumulative profit from all finished trades`\n"
                    "*/forcesell |all:* `Instantly sells the given trade or all trades, "
                    "regardless of profit`\n"