From eaa7370174e1b5188192e99bb205f2f03e8063b0 Mon Sep 17 00:00:00 2001 From: thopd88 <20041501+thopd88@users.noreply.github.com> Date: Mon, 20 Jul 2020 11:08:18 +0700 Subject: [PATCH 01/20] add /delete command --- freqtrade/rpc/rpc.py | 22 ++++++++++++++++++++++ freqtrade/rpc/telegram.py | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index c73fcbf54..b76259ad2 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -536,6 +536,28 @@ class RPC: return trade 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]]: """ diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 13cc1afaf..7d006c4e5 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('delete', self._delete), CommandHandler('performance', self._performance), CommandHandler('daily', self._daily), CommandHandler('count', self._count), @@ -496,6 +497,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 _performance(self, update: Update, context: CallbackContext) -> None: """ @@ -613,6 +632,7 @@ class Telegram(RPC): "*/forcesell |all:* `Instantly sells the given trade or all trades, " "regardless of profit`\n" f"{forcebuy_text if self._config.get('forcebuy_enable', False) else ''}" + "*/delete :* `Instantly delete the given trade in the database`\n" "*/performance:* `Show performance of each finished trade grouped by pair`\n" "*/daily :* `Shows profit or loss per day, over the last n days`\n" "*/count:* `Show number of trades running compared to allowed number of trades`" From 14cb29aae1d5fba8fe7d735ddfff7f0aa451434a Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 28 Jul 2020 08:16:55 +0200 Subject: [PATCH 02/20] Add test for remove_pumps in edge --- tests/edge/test_edge.py | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index cf9cb6fe1..7373778ad 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -409,3 +409,98 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc final = edge._process_expectancy(trades_df) assert len(final) == 0 assert isinstance(final, dict) + + +def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): + edge_conf['edge']['min_trade_number'] = 2 + edge_conf['edge']['remove_pumps'] = True + freqtrade = get_patched_freqtradebot(mocker, edge_conf) + + freqtrade.exchange.get_fee = fee + edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy) + + trades = [ + {'pair': 'TEST/BTC', + 'stoploss': -0.9, + 'profit_percent': '', + 'profit_abs': '', + 'open_time': np.datetime64('2018-10-03T00:05:00.000000000'), + 'close_time': np.datetime64('2018-10-03T00:10:00.000000000'), + 'open_index': 1, + 'close_index': 1, + 'trade_duration': '', + 'open_rate': 17, + 'close_rate': 15, + 'exit_type': 'sell_signal'}, + + {'pair': 'TEST/BTC', + 'stoploss': -0.9, + 'profit_percent': '', + 'profit_abs': '', + 'open_time': np.datetime64('2018-10-03T00:20:00.000000000'), + 'close_time': np.datetime64('2018-10-03T00:25:00.000000000'), + 'open_index': 4, + 'close_index': 4, + 'trade_duration': '', + 'open_rate': 20, + 'close_rate': 10, + 'exit_type': 'sell_signal'}, + {'pair': 'TEST/BTC', + 'stoploss': -0.9, + 'profit_percent': '', + 'profit_abs': '', + 'open_time': np.datetime64('2018-10-03T00:20:00.000000000'), + 'close_time': np.datetime64('2018-10-03T00:25:00.000000000'), + 'open_index': 4, + 'close_index': 4, + 'trade_duration': '', + 'open_rate': 20, + 'close_rate': 10, + 'exit_type': 'sell_signal'}, + {'pair': 'TEST/BTC', + 'stoploss': -0.9, + 'profit_percent': '', + 'profit_abs': '', + 'open_time': np.datetime64('2018-10-03T00:20:00.000000000'), + 'close_time': np.datetime64('2018-10-03T00:25:00.000000000'), + 'open_index': 4, + 'close_index': 4, + 'trade_duration': '', + 'open_rate': 20, + 'close_rate': 10, + 'exit_type': 'sell_signal'}, + {'pair': 'TEST/BTC', + 'stoploss': -0.9, + 'profit_percent': '', + 'profit_abs': '', + 'open_time': np.datetime64('2018-10-03T00:20:00.000000000'), + 'close_time': np.datetime64('2018-10-03T00:25:00.000000000'), + 'open_index': 4, + 'close_index': 4, + 'trade_duration': '', + 'open_rate': 20, + 'close_rate': 10, + 'exit_type': 'sell_signal'}, + + {'pair': 'TEST/BTC', + 'stoploss': -0.9, + 'profit_percent': '', + 'profit_abs': '', + 'open_time': np.datetime64('2018-10-03T00:30:00.000000000'), + 'close_time': np.datetime64('2018-10-03T00:40:00.000000000'), + 'open_index': 6, + 'close_index': 7, + 'trade_duration': '', + 'open_rate': 26, + 'close_rate': 134, + 'exit_type': 'sell_signal'} + ] + + trades_df = DataFrame(trades) + trades_df = edge._fill_calculable_fields(trades_df) + final = edge._process_expectancy(trades_df) + + assert 'TEST/BTC' in final + assert final['TEST/BTC'].stoploss == -0.9 + assert final['TEST/BTC'].nb_trades == len(trades_df) - 1 + assert round(final['TEST/BTC'].winrate, 10) == 0.0 From d1cbc567e4895111f877827c9007030a8cf843c1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 28 Jul 2020 13:41:09 +0200 Subject: [PATCH 03/20] Fix filtering for bumped pairs --- freqtrade/edge/edge_positioning.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index 41252ee51..1993eded3 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -281,8 +281,8 @@ class Edge: # # Removing Pumps if self.edge_config.get('remove_pumps', False): - results = results.groupby(['pair', 'stoploss']).apply( - lambda x: x[x['profit_abs'] < 2 * x['profit_abs'].std() + x['profit_abs'].mean()]) + results = results[results['profit_abs'] < 2 * results['profit_abs'].std() + + results['profit_abs'].mean()] ########################################################################## # Removing trades having a duration more than X minutes (set in config) From 5ff09a06c7a74875184aea4cfc159d32825b4566 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2020 07:17:30 +0000 Subject: [PATCH 04/20] Bump pytest from 5.4.3 to 6.0.1 Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.3 to 6.0.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/5.4.3...6.0.1) Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 9f9be638d..c02a439d3 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,7 +8,7 @@ flake8==3.8.3 flake8-type-annotations==0.1.0 flake8-tidy-imports==4.1.0 mypy==0.782 -pytest==5.4.3 +pytest==6.0.1 pytest-asyncio==0.14.0 pytest-cov==2.10.0 pytest-mock==3.2.0 From 809b3ddafc5863caab228cd75c10f5ae8e496e5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2020 07:17:31 +0000 Subject: [PATCH 05/20] Bump mkdocs-material from 5.5.0 to 5.5.1 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 5.5.0 to 5.5.1. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/docs/changelog.md) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/5.5.0...5.5.1) Signed-off-by: dependabot[bot] --- docs/requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 2a2405f8e..c30661b6a 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,2 +1,2 @@ -mkdocs-material==5.5.0 +mkdocs-material==5.5.1 mdx_truly_sane_lists==1.2 From 1855a444fa29f574aa29f5f6e936c9bfd1d879e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2020 07:17:32 +0000 Subject: [PATCH 06/20] Bump pandas from 1.0.5 to 1.1.0 Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.0.5 to 1.1.0. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Changelog](https://github.com/pandas-dev/pandas/blob/master/RELEASE.md) - [Commits](https://github.com/pandas-dev/pandas/compare/v1.0.5...v1.1.0) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2392d4cb2..d65f90325 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ -r requirements-common.txt numpy==1.19.1 -pandas==1.0.5 +pandas==1.1.0 From b3f04d89d259c49f8db954aababe9e812f6f4ca6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2020 07:17:50 +0000 Subject: [PATCH 07/20] Bump ccxt from 1.32.7 to 1.32.45 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.32.7 to 1.32.45. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/doc/exchanges-by-country.rst) - [Commits](https://github.com/ccxt/ccxt/compare/1.32.7...1.32.45) Signed-off-by: dependabot[bot] --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 942fe3792..62cde9dbc 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -1,6 +1,6 @@ # requirements without requirements installable via conda # mainly used for Raspberry pi installs -ccxt==1.32.7 +ccxt==1.32.45 SQLAlchemy==1.3.18 python-telegram-bot==12.8 arrow==0.15.8 From a33346c6b660c518a70bdde9a56dc805046d08b8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 3 Aug 2020 19:21:46 +0200 Subject: [PATCH 08/20] Fix testing errors - which surfaced with pytest 6.0.1 --- freqtrade/exchange/exchange.py | 4 ++-- tests/test_freqtradebot.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 04ad10a68..c3fe3e601 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -258,8 +258,8 @@ class Exchange: api.urls['api'] = api.urls['test'] logger.info("Enabled Sandbox API on %s", name) else: - logger.warning(name, "No Sandbox URL in CCXT, exiting. " - "Please check your config.json") + logger.warning(f"No Sandbox URL in CCXT for {name}, exiting. " + "Please check your config.json") raise OperationalException(f'Exchange {name} does not provide a sandbox api') def _load_async_markets(self, reload: bool = False) -> None: diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index fd57eae6f..dcddf34e3 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -1726,6 +1726,7 @@ def test_update_trade_state_withorderdict(default_conf, trades_for_order, limit_ amount=amount, exchange='binance', open_rate=0.245441, + open_date=arrow.utcnow().datetime, fee_open=fee.return_value, fee_close=fee.return_value, open_order_id="123456", @@ -1816,6 +1817,7 @@ def test_update_trade_state_sell(default_conf, trades_for_order, limit_sell_orde open_rate=0.245441, fee_open=0.0025, fee_close=0.0025, + open_date=arrow.utcnow().datetime, open_order_id="123456", is_open=True, ) From a3688b159fcf703a5cc390d0ae70d884db717762 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 3 Aug 2020 19:28:57 +0200 Subject: [PATCH 09/20] Improve formatting --- freqtrade/exchange/exchange.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index c3fe3e601..c4ed75878 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -258,8 +258,8 @@ class Exchange: api.urls['api'] = api.urls['test'] logger.info("Enabled Sandbox API on %s", name) else: - logger.warning(f"No Sandbox URL in CCXT for {name}, exiting. " - "Please check your config.json") + logger.warning( + f"No Sandbox URL in CCXT for {name}, exiting. Please check your config.json") raise OperationalException(f'Exchange {name} does not provide a sandbox api') def _load_async_markets(self, reload: bool = False) -> None: From 215972c68f3efa6397a6d5a6b17fa2c4ea1a3bea Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 Aug 2020 14:41:22 +0200 Subject: [PATCH 10/20] Implement /delete for api-server --- freqtrade/rpc/api_server.py | 11 +++++++++++ freqtrade/rpc/rpc.py | 4 ++-- freqtrade/rpc/telegram.py | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/freqtrade/rpc/api_server.py b/freqtrade/rpc/api_server.py index 351842e10..f7481fee4 100644 --- a/freqtrade/rpc/api_server.py +++ b/freqtrade/rpc/api_server.py @@ -200,6 +200,8 @@ class ApiServer(RPC): view_func=self._ping, methods=['GET']) self.app.add_url_rule(f'{BASE_URI}/trades', 'trades', view_func=self._trades, methods=['GET']) + self.app.add_url_rule(f'{BASE_URI}/trades/', 'trades_delete', + view_func=self._trades_delete, methods=['DELETE']) # Combined actions and infos self.app.add_url_rule(f'{BASE_URI}/blacklist', 'blacklist', view_func=self._blacklist, methods=['GET', 'POST']) @@ -424,6 +426,15 @@ class ApiServer(RPC): results = self._rpc_trade_history(limit) return self.rest_dump(results) + @require_login + @rpc_catch_errors + def _trades_delete(self, tradeid): + """ + Handler for DELETE /trades/ endpoint. + """ + result = self._rpc_delete(tradeid) + return self.rest_dump(result) + @require_login @rpc_catch_errors def _whitelist(self): diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index f6627ed16..b79cac243 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -537,7 +537,7 @@ class RPC: return trade else: return None - + def _rpc_delete(self, trade_id: str) -> Dict[str, str]: """ Handler for delete . @@ -558,7 +558,7 @@ class RPC: _exec_delete(trade) Trade.session.flush() self._freqtrade.wallets.update() - return {'result': f'Deleted trade {trade_id}.'} + return {'result_msg': f'Deleted trade {trade_id}.'} def _rpc_performance(self) -> List[Dict[str, Any]]: """ diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 20c1cc9dc..293e3a686 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -547,7 +547,7 @@ class Telegram(RPC): 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)) + self._send_msg('Delete Result: `{result_msg}`'.format(**msg)) except RPCException as e: self._send_msg(str(e)) From 26c7341b7d712b4f1bb671722ee0bf0f6e55a42b Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 Aug 2020 14:41:38 +0200 Subject: [PATCH 11/20] Add test for api-server DELETE trade --- tests/rpc/test_rpc_apiserver.py | 38 ++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index f4d7b8ca3..99f17383f 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -50,6 +50,12 @@ def client_get(client, url): 'Origin': 'http://example.com'}) +def client_delete(client, url): + # Add fake Origin to ensure CORS kicks in + return client.delete(url, headers={'Authorization': _basic_auth_str(_TEST_USER, _TEST_PASS), + 'Origin': 'http://example.com'}) + + def assert_response(response, expected_code=200, needs_cors=True): assert response.status_code == expected_code assert response.content_type == "application/json" @@ -352,7 +358,7 @@ def test_api_daily(botclient, mocker, ticker, fee, markets): assert rc.json['data'][0]['date'] == str(datetime.utcnow().date()) -def test_api_trades(botclient, mocker, ticker, fee, markets): +def test_api_trades(botclient, mocker, fee, markets): ftbot, client = botclient patch_get_signal(ftbot, (True, False)) mocker.patch.multiple( @@ -376,6 +382,36 @@ def test_api_trades(botclient, mocker, ticker, fee, markets): assert rc.json['trades_count'] == 1 +def test_api_delete_trade(botclient, mocker, fee, markets): + ftbot, client = botclient + patch_get_signal(ftbot, (True, False)) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + markets=PropertyMock(return_value=markets) + ) + rc = client_delete(client, f"{BASE_URI}/trades/1") + # Error - trade won't exist yet. + assert_response(rc, 502) + + create_mock_trades(fee) + trades = Trade.query.all() + assert len(trades) > 2 + + rc = client_delete(client, f"{BASE_URI}/trades/1") + assert_response(rc) + assert rc.json['result_msg'] == 'Deleted trade 1.' + assert len(trades) - 1 == len(Trade.query.all()) + + rc = client_delete(client, f"{BASE_URI}/trades/1") + # Trade is gone now. + assert_response(rc, 502) + assert len(trades) - 1 == len(Trade.query.all()) + rc = client_delete(client, f"{BASE_URI}/trades/2") + assert_response(rc) + assert rc.json['result_msg'] == 'Deleted trade 2.' + assert len(trades) - 2 == len(Trade.query.all()) + + def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): ftbot, client = botclient patch_get_signal(ftbot, (True, False)) From 4b0164770c50d3efdef5fb979bdcf71452f01ef6 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 4 Aug 2020 14:49:59 +0200 Subject: [PATCH 12/20] Add test for /delete --- freqtrade/rpc/telegram.py | 4 ++-- tests/rpc/test_rpc_telegram.py | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 293e3a686..19d3e1bd9 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -94,7 +94,7 @@ class Telegram(RPC): CommandHandler('forcesell', self._forcesell), CommandHandler('forcebuy', self._forcebuy), CommandHandler('trades', self._trades), - CommandHandler('delete', self._delete), + CommandHandler('delete', self._delete_trade), CommandHandler('performance', self._performance), CommandHandler('daily', self._daily), CommandHandler('count', self._count), @@ -535,7 +535,7 @@ class Telegram(RPC): self._send_msg(str(e)) @authorized_only - def _delete(self, update: Update, context: CallbackContext) -> None: + def _delete_trade(self, update: Update, context: CallbackContext) -> None: """ Handler for /delete . Delete the given trade diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 62a4f49a1..c8ac05d0d 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1177,6 +1177,33 @@ def test_telegram_trades(mocker, update, default_conf, fee): assert "
" in msg_mock.call_args_list[0][0][0]
 
 
+def test_telegram_delete_trade(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._delete_trade(update=update, context=context)
+    assert "invalid argument" in msg_mock.call_args_list[0][0][0]
+
+    msg_mock.reset_mock()
+    create_mock_trades(fee)
+
+    context = MagicMock()
+    context.args = [1]
+    telegram._delete_trade(update=update, context=context)
+    msg_mock.call_count == 1
+    assert "Delete Result" in msg_mock.call_args_list[0][0][0]
+    assert "Deleted trade 1." 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 b954af33cfa06387684297c3f6cce35813603414 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Tue, 4 Aug 2020 16:01:41 +0200
Subject: [PATCH 13/20] Fix type erorr in callable

---
 freqtrade/rpc/api_server.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/freqtrade/rpc/api_server.py b/freqtrade/rpc/api_server.py
index f7481fee4..f28a35ff0 100644
--- a/freqtrade/rpc/api_server.py
+++ b/freqtrade/rpc/api_server.py
@@ -56,7 +56,7 @@ def require_login(func: Callable[[Any, Any], Any]):
 
 
 # Type should really be Callable[[ApiServer], Any], but that will create a circular dependency
-def rpc_catch_errors(func: Callable[[Any], Any]):
+def rpc_catch_errors(func: Callable[..., Any]):
 
     def func_wrapper(obj, *args, **kwargs):
 

From 9163c7f3d3bb0854bcaceea5cef2980ea8ef6a19 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Tue, 4 Aug 2020 19:43:05 +0200
Subject: [PATCH 14/20] Improve api response

---
 freqtrade/rpc/api_server.py     |  4 ++++
 tests/rpc/test_rpc_apiserver.py | 17 ++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/freqtrade/rpc/api_server.py b/freqtrade/rpc/api_server.py
index f28a35ff0..06926ac35 100644
--- a/freqtrade/rpc/api_server.py
+++ b/freqtrade/rpc/api_server.py
@@ -431,6 +431,10 @@ class ApiServer(RPC):
     def _trades_delete(self, tradeid):
         """
         Handler for DELETE /trades/ endpoint.
+        Removes the trade from the database (tries to cancel open orders first!)
+        get:
+          param:
+            tradeid: Numeric trade-id assigned to the trade.
         """
         result = self._rpc_delete(tradeid)
         return self.rest_dump(result)
diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py
index 99f17383f..ccdec6fdc 100644
--- a/tests/rpc/test_rpc_apiserver.py
+++ b/tests/rpc/test_rpc_apiserver.py
@@ -385,31 +385,42 @@ def test_api_trades(botclient, mocker, fee, markets):
 def test_api_delete_trade(botclient, mocker, fee, markets):
     ftbot, client = botclient
     patch_get_signal(ftbot, (True, False))
+    stoploss_mock = MagicMock()
+    cancel_mock = MagicMock()
     mocker.patch.multiple(
         'freqtrade.exchange.Exchange',
-        markets=PropertyMock(return_value=markets)
+        markets=PropertyMock(return_value=markets),
+        cancel_order=cancel_mock,
+        cancel_stoploss_order=stoploss_mock,
     )
     rc = client_delete(client, f"{BASE_URI}/trades/1")
     # Error - trade won't exist yet.
     assert_response(rc, 502)
 
     create_mock_trades(fee)
+    ftbot.strategy.order_types['stoploss_on_exchange'] = True
     trades = Trade.query.all()
+    trades[1].stoploss_order_id = '1234'
     assert len(trades) > 2
 
     rc = client_delete(client, f"{BASE_URI}/trades/1")
     assert_response(rc)
-    assert rc.json['result_msg'] == 'Deleted trade 1.'
+    assert rc.json['result_msg'] == 'Deleted trade 1. Closed 1 open orders.'
     assert len(trades) - 1 == len(Trade.query.all())
+    assert cancel_mock.call_count == 1
 
+    cancel_mock.reset_mock()
     rc = client_delete(client, f"{BASE_URI}/trades/1")
     # Trade is gone now.
     assert_response(rc, 502)
+    assert cancel_mock.call_count == 0
+
     assert len(trades) - 1 == len(Trade.query.all())
     rc = client_delete(client, f"{BASE_URI}/trades/2")
     assert_response(rc)
-    assert rc.json['result_msg'] == 'Deleted trade 2.'
+    assert rc.json['result_msg'] == 'Deleted trade 2. Closed 2 open orders.'
     assert len(trades) - 2 == len(Trade.query.all())
+    assert stoploss_mock.call_count == 1
 
 
 def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):

From 817f5289db94895a6db6e0b045fcf40aa75047b1 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Tue, 4 Aug 2020 19:43:22 +0200
Subject: [PATCH 15/20] /delete should Cancel open orders (and stoploss orders)

---
 freqtrade/rpc/rpc.py  | 46 +++++++++++++++++++++++-----------
 tests/rpc/test_rpc.py | 57 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py
index b79cac243..58fdebe85 100644
--- a/freqtrade/rpc/rpc.py
+++ b/freqtrade/rpc/rpc.py
@@ -11,9 +11,9 @@ from typing import Any, Dict, List, Optional, Tuple
 import arrow
 from numpy import NAN, mean
 
-from freqtrade.exceptions import ExchangeError, PricingError
-
-from freqtrade.exchange import timeframe_to_msecs, timeframe_to_minutes
+from freqtrade.exceptions import (ExchangeError, InvalidOrderException,
+                                  PricingError)
+from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs
 from freqtrade.misc import shorten_date
 from freqtrade.persistence import Trade
 from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
@@ -541,24 +541,42 @@ class RPC:
     def _rpc_delete(self, trade_id: str) -> Dict[str, str]:
         """
         Handler for delete .
-        Delete the given trade
+        Delete the given trade and close eventually existing open orders.
         """
-        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()
+            c_count = 0
+            trade = Trade.get_trades(trade_filter=[Trade.id == trade_id]).first()
             if not trade:
-                logger.warning('delete: Invalid argument received')
+                logger.warning('delete trade: Invalid argument received')
                 raise RPCException('invalid argument')
 
-            _exec_delete(trade)
+            # Try cancelling regular order if that exists
+            if trade.open_order_id:
+                try:
+                    self._freqtrade.exchange.cancel_order(trade.open_order_id, trade.pair)
+                    c_count += 1
+                except (ExchangeError, InvalidOrderException):
+                    pass
+
+            # cancel stoploss on exchange ...
+            if (self._freqtrade.strategy.order_types.get('stoploss_on_exchange')
+                    and trade.stoploss_order_id):
+                try:
+                    self._freqtrade.exchange.cancel_stoploss_order(trade.stoploss_order_id,
+                                                                   trade.pair)
+                    c_count += 1
+                except (ExchangeError, InvalidOrderException):
+                    pass
+
+            Trade.session.delete(trade)
             Trade.session.flush()
             self._freqtrade.wallets.update()
-            return {'result_msg': f'Deleted trade {trade_id}.'}
+            return {
+                'result': 'success',
+                'trade_id': trade_id,
+                'result_msg': f'Deleted trade {trade_id}. Closed {c_count} open orders.',
+                'cancel_order_count': c_count,
+            }
 
     def _rpc_performance(self) -> List[Dict[str, Any]]:
         """
diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py
index e5859fcd9..b4a781459 100644
--- a/tests/rpc/test_rpc.py
+++ b/tests/rpc/test_rpc.py
@@ -8,7 +8,7 @@ import pytest
 from numpy import isnan
 
 from freqtrade.edge import PairInfo
-from freqtrade.exceptions import ExchangeError, TemporaryError
+from freqtrade.exceptions import ExchangeError, InvalidOrderException, TemporaryError
 from freqtrade.persistence import Trade
 from freqtrade.rpc import RPC, RPCException
 from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
@@ -291,6 +291,61 @@ def test_rpc_trade_history(mocker, default_conf, markets, fee):
     assert trades['trades'][0]['pair'] == 'XRP/BTC'
 
 
+def test_rpc_delete_trade(mocker, default_conf, fee, markets, caplog):
+    mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
+    stoploss_mock = MagicMock()
+    cancel_mock = MagicMock()
+    mocker.patch.multiple(
+        'freqtrade.exchange.Exchange',
+        markets=PropertyMock(return_value=markets),
+        cancel_order=cancel_mock,
+        cancel_stoploss_order=stoploss_mock,
+    )
+
+    freqtradebot = get_patched_freqtradebot(mocker, default_conf)
+    freqtradebot.strategy.order_types['stoploss_on_exchange'] = True
+    create_mock_trades(fee)
+    rpc = RPC(freqtradebot)
+    with pytest.raises(RPCException, match='invalid argument'):
+        rpc._rpc_delete('200')
+
+    create_mock_trades(fee)
+    trades = Trade.query.all()
+    trades[1].stoploss_order_id = '1234'
+    trades[2].stoploss_order_id = '1234'
+    assert len(trades) > 2
+
+    res = rpc._rpc_delete('1')
+    assert isinstance(res, dict)
+    assert res['result'] == 'success'
+    assert res['trade_id'] == '1'
+    assert res['cancel_order_count'] == 1
+    assert cancel_mock.call_count == 1
+    assert stoploss_mock.call_count == 0
+    cancel_mock.reset_mock()
+    stoploss_mock.reset_mock()
+
+    res = rpc._rpc_delete('2')
+    assert isinstance(res, dict)
+    assert cancel_mock.call_count == 1
+    assert stoploss_mock.call_count == 1
+    assert res['cancel_order_count'] == 2
+
+    stoploss_mock = mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
+                                 side_effect=InvalidOrderException)
+
+    res = rpc._rpc_delete('3')
+    assert stoploss_mock.call_count == 1
+    stoploss_mock.reset_mock()
+
+    cancel_mock = mocker.patch('freqtrade.exchange.Exchange.cancel_order',
+                               side_effect=InvalidOrderException)
+
+    res = rpc._rpc_delete('4')
+    assert cancel_mock.call_count == 1
+    assert stoploss_mock.call_count == 0
+
+
 def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
                               limit_buy_order, limit_sell_order, mocker) -> None:
     mocker.patch.multiple(

From 075c73b9e38e7f71ce5eb32e2bc8930b1c947fa0 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Tue, 4 Aug 2020 19:56:49 +0200
Subject: [PATCH 16/20] Improve formatting of telegram message

---
 freqtrade/rpc/rpc.py           | 4 ++--
 freqtrade/rpc/telegram.py      | 5 ++++-
 tests/rpc/test_rpc_telegram.py | 2 +-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py
index 58fdebe85..8a1ff7e96 100644
--- a/freqtrade/rpc/rpc.py
+++ b/freqtrade/rpc/rpc.py
@@ -6,7 +6,7 @@ from abc import abstractmethod
 from datetime import date, datetime, timedelta
 from enum import Enum
 from math import isnan
-from typing import Any, Dict, List, Optional, Tuple
+from typing import Any, Dict, List, Optional, Tuple, Union
 
 import arrow
 from numpy import NAN, mean
@@ -538,7 +538,7 @@ class RPC:
         else:
             return None
 
-    def _rpc_delete(self, trade_id: str) -> Dict[str, str]:
+    def _rpc_delete(self, trade_id: str) -> Dict[str, Union[str, int]]:
         """
         Handler for delete .
         Delete the given trade and close eventually existing open orders.
diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py
index 19d3e1bd9..dde19fddb 100644
--- a/freqtrade/rpc/telegram.py
+++ b/freqtrade/rpc/telegram.py
@@ -547,7 +547,10 @@ class Telegram(RPC):
         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_msg}`'.format(**msg))
+            self._send_msg((
+                'Delete Result: `{result_msg}`'
+                'Please make sure to take care of this asset on the exchange manually.'
+            ).format(**msg))
 
         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 c8ac05d0d..ac8dc62c6 100644
--- a/tests/rpc/test_rpc_telegram.py
+++ b/tests/rpc/test_rpc_telegram.py
@@ -1200,8 +1200,8 @@ def test_telegram_delete_trade(mocker, update, default_conf, fee):
     context.args = [1]
     telegram._delete_trade(update=update, context=context)
     msg_mock.call_count == 1
-    assert "Delete Result" in msg_mock.call_args_list[0][0][0]
     assert "Deleted trade 1." in msg_mock.call_args_list[0][0][0]
+    assert "Please make sure to take care of this asset" in msg_mock.call_args_list[0][0][0]
 
 
 def test_help_handle(default_conf, update, mocker) -> None:

From 8ed3b81c618293106ad821585ad3fbe89d8685e5 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Tue, 4 Aug 2020 19:57:28 +0200
Subject: [PATCH 17/20] Implement /delete in rest client

---
 docs/rest-api.md          | 43 +++++++++++++++++++++------------------
 docs/telegram-usage.md    |  1 +
 freqtrade/rpc/telegram.py |  2 +-
 scripts/rest_client.py    | 12 +++++++++++
 4 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/docs/rest-api.md b/docs/rest-api.md
index a8d902b53..2887a9ffc 100644
--- a/docs/rest-api.md
+++ b/docs/rest-api.md
@@ -106,26 +106,29 @@ python3 scripts/rest_client.py --config rest_config.json  [optional par
 
 ## Available commands
 
-|  Command | Default | Description |
-|----------|---------|-------------|
-| `start` | | Starts the trader
-| `stop` | | Stops the trader
-| `stopbuy` | | Stops the trader from opening new trades. Gracefully closes open trades according to their rules.
-| `reload_config` | | 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
-| `forcesell ` | | Instantly sells the given trade  (Ignoring `minimum_roi`).
-| `forcesell all` | | Instantly sells all open trades (Ignoring `minimum_roi`).
-| `forcebuy  [rate]` | | Instantly buys the given pair. Rate is optional. (`forcebuy_enable` must be set to True)
-| `performance` | | Show performance of each finished trade grouped by pair
-| `balance` | | Show account balance per currency
-| `daily ` | 7 | Shows profit or loss per day, over the last n days
-| `whitelist` | | Show the current whitelist
-| `blacklist [pair]` | | Show the current blacklist, or adds a pair to the blacklist.
-| `edge` | | Show validated pairs by Edge if it is enabled.
-| `version` | | Show version
+|  Command | Description |
+|----------|-------------|
+| `ping` | Simple command testing the API Readiness - requires no authentication.
+| `start` | Starts the trader
+| `stop` | Stops the trader
+| `stopbuy` | Stops the trader from opening new trades. Gracefully closes open trades according to their rules.
+| `reload_config` | Reloads the configuration file
+| `trades` | List last trades.
+| `delete_trade ` | Remove trade from the database. Tries to close open orders. Requires manual handling of this trade on the exchange.
+| `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
+| `forcesell ` | Instantly sells the given trade  (Ignoring `minimum_roi`).
+| `forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`).
+| `forcebuy  [rate]` | Instantly buys the given pair. Rate is optional. (`forcebuy_enable` must be set to True)
+| `performance` | Show performance of each finished trade grouped by pair
+| `balance` | Show account balance per currency
+| `daily ` | Shows profit or loss per day, over the last n days (n defaults to 7)
+| `whitelist` | Show the current whitelist
+| `blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
+| `edge` | Show validated pairs by Edge if it is enabled.
+| `version` | Show version
 
 Possible commands can be listed from the rest-client script using the `help` command.
 
diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md
index 250293d25..b81ef012b 100644
--- a/docs/telegram-usage.md
+++ b/docs/telegram-usage.md
@@ -57,6 +57,7 @@ official commands. You can ask at any moment for help with `/help`.
 | `/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.
+| `/delete ` | | Delete a specific trade from the Database. Tries to close open orders. Requires manual handling of this trade on the exchange.
 | `/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 dde19fddb..f1d3cde21 100644
--- a/freqtrade/rpc/telegram.py
+++ b/freqtrade/rpc/telegram.py
@@ -548,7 +548,7 @@ class Telegram(RPC):
         try:
             msg = self._rpc_delete(trade_id)
             self._send_msg((
-                'Delete Result: `{result_msg}`'
+                '`{result_msg}`\n'
                 'Please make sure to take care of this asset on the exchange manually.'
             ).format(**msg))
 
diff --git a/scripts/rest_client.py b/scripts/rest_client.py
index 1f96bcb69..51ea596f6 100755
--- a/scripts/rest_client.py
+++ b/scripts/rest_client.py
@@ -62,6 +62,9 @@ class FtRestClient():
     def _get(self, apipath, params: dict = None):
         return self._call("GET", apipath, params=params)
 
+    def _delete(self, apipath, params: dict = None):
+        return self._call("DELETE", apipath, params=params)
+
     def _post(self, apipath, params: dict = None, data: dict = None):
         return self._call("POST", apipath, params=params, data=data)
 
@@ -164,6 +167,15 @@ class FtRestClient():
         """
         return self._get("trades", params={"limit": limit} if limit else 0)
 
+    def delete_trade(self, trade_id):
+        """Delete trade from the database.
+        Tries to close open orders. Requires manual handling of this asset on the exchange.
+
+        :param trade_id: Deletes the trade with this ID from the database.
+        :return: json object
+        """
+        return self._delete("trades/{}".format(trade_id))
+
     def whitelist(self):
         """Show the current whitelist.
 

From 5082acc33f1220f95490c56c4fa1d8571ae6faf4 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Thu, 6 Aug 2020 07:54:54 +0200
Subject: [PATCH 18/20] Fix typos in documentation

---
 docs/rest-api.md       | 2 +-
 docs/telegram-usage.md | 8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/docs/rest-api.md b/docs/rest-api.md
index 2887a9ffc..68754f79a 100644
--- a/docs/rest-api.md
+++ b/docs/rest-api.md
@@ -46,7 +46,7 @@ secrets.token_hex()
 
 ### Configuration with docker
 
-If you run your bot using docker, you'll need to have the bot listen to incomming connections. The security is then handled by docker.
+If you run your bot using docker, you'll need to have the bot listen to incoming connections. The security is then handled by docker.
 
 ``` json
     "api_server": {
diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md
index b81ef012b..b050a7a60 100644
--- a/docs/telegram-usage.md
+++ b/docs/telegram-usage.md
@@ -9,7 +9,7 @@ Telegram user id.
 
 Start a chat with the [Telegram BotFather](https://telegram.me/BotFather)
 
-Send the message `/newbot`. 
+Send the message `/newbot`.
 
 *BotFather response:*
 
@@ -115,6 +115,7 @@ For each open trade, the bot will send you the following message.
 ### /status table
 
 Return the status of all open trades in a table format.
+
 ```
    ID  Pair      Since    Profit
 ----  --------  -------  --------
@@ -125,6 +126,7 @@ Return the status of all open trades in a table format.
 ### /count
 
 Return the number of trades used and available.
+
 ```
 current    max
 ---------  -----
@@ -210,7 +212,7 @@ Shows the current whitelist
 
 Shows the current blacklist.
 If Pair is set, then this pair will be added to the pairlist.
-Also supports multiple pairs, seperated by a space.
+Also supports multiple pairs, separated by a space.
 Use `/reload_config` to reset the blacklist.
 
 > Using blacklist `StaticPairList` with 2 pairs  
@@ -218,7 +220,7 @@ Use `/reload_config` to reset the blacklist.
 
 ### /edge
 
-Shows pairs validated by Edge along with their corresponding winrate, expectancy and stoploss values.
+Shows pairs validated by Edge along with their corresponding win-rate, expectancy and stoploss values.
 
 > **Edge only validated following pairs:**
 ```

From eba73307e42ce6b94d5bed393c40c0bfbbafd05c Mon Sep 17 00:00:00 2001
From: Fredrik81 
Date: Fri, 7 Aug 2020 01:13:36 +0200
Subject: [PATCH 19/20] Update strategy_methods_advanced.j2

Fix def confirm_trade_exit arguments
---
 freqtrade/templates/subtemplates/strategy_methods_advanced.j2 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2
index c7ce41bb7..5ca6e6971 100644
--- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2
+++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2
@@ -34,7 +34,7 @@ def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: f
     """
     return True
 
-def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float,
+def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: float,
                        rate: float, time_in_force: str, sell_reason: str, **kwargs) -> bool:
     """
     Called right before placing a regular sell order.

From f3ce54150e92f66c70b82f91276f10fab7e801a4 Mon Sep 17 00:00:00 2001
From: Matthias 
Date: Sat, 8 Aug 2020 15:06:13 +0200
Subject: [PATCH 20/20] Simplify Telegram table

---
 docs/telegram-usage.md | 48 +++++++++++++++++++++---------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md
index b050a7a60..9776b26ba 100644
--- a/docs/telegram-usage.md
+++ b/docs/telegram-usage.md
@@ -47,30 +47,30 @@ Per default, the Telegram bot shows predefined commands. Some commands
 are only available by sending them to the bot. The table below list the
 official commands. You can ask at any moment for help with `/help`.
 
-|  Command | Default | Description |
-|----------|---------|-------------|
-| `/start` | | Starts the trader
-| `/stop` | | Stops the trader
-| `/stopbuy` | | Stops the trader from opening new trades. Gracefully closes open trades according to their rules.
-| `/reload_config` | | 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. 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.
-| `/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`).
-| `/forcesell all` | | Instantly sells all open trades (Ignoring `minimum_roi`).
-| `/forcebuy  [rate]` | | Instantly buys the given pair. Rate is optional. (`forcebuy_enable` must be set to True)
-| `/performance` | | Show performance of each finished trade grouped by pair
-| `/balance` | | Show account balance per currency
-| `/daily ` | 7 | Shows profit or loss per day, over the last n days
-| `/whitelist` | | Show the current whitelist
-| `/blacklist [pair]` | | Show the current blacklist, or adds a pair to the blacklist.
-| `/edge` | | Show validated pairs by Edge if it is enabled.
-| `/help` | | Show help message
-| `/version` | | Show version
+|  Command | Description |
+|----------|-------------|
+| `/start` | Starts the trader
+| `/stop` | Stops the trader
+| `/stopbuy` | Stops the trader from opening new trades. Gracefully closes open trades according to their rules.
+| `/reload_config` | 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. 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.
+| `/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`).
+| `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`).
+| `/forcebuy  [rate]` | Instantly buys the given pair. Rate is optional. (`forcebuy_enable` must be set to True)
+| `/performance` | Show performance of each finished trade grouped by pair
+| `/balance` | Show account balance per currency
+| `/daily ` | Shows profit or loss per day, over the last n days (n defaults to 7)
+| `/whitelist` | Show the current whitelist
+| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
+| `/edge` | Show validated pairs by Edge if it is enabled.
+| `/help` | Show help message
+| `/version` | Show version
 
 ## Telegram commands in action