diff --git a/README.md b/README.md index 059e80cd9..0cc2364e5 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,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. +- `/stopentry`: Stop entering new trades. - `/status |[table]`: Lists all or specific open trades. - `/profit []`: Lists cumulative profit from all finished trades, over the last n days. - `/forceexit |all`: Instantly exits the given trade (Ignoring `minimum_roi`). diff --git a/docs/faq.md b/docs/faq.md index f1542d08e..381bbceb5 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -77,9 +77,9 @@ Freqtrade will not provide incomplete candles to strategies. Using incomplete ca You can use "current" market data by using the [dataprovider](strategy-customization.md#orderbookpair-maximum)'s orderbook or ticker methods - which however cannot be used during backtesting. -### Is there a setting to only SELL the coins being held and not perform anymore BUYS? +### Is there a setting to only Exit the trades being held and not perform any new Entries? -You can use the `/stopbuy` command in Telegram to prevent future buys, followed by `/forceexit all` (sell all open trades). +You can use the `/stopentry` command in Telegram to prevent future trade entry, followed by `/forceexit all` (sell all open trades). ### I want to run multiple bots on the same machine diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 32ad1b288..0b8403414 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -654,7 +654,7 @@ Position adjustments will always be applied in the direction of the trade, so a Stoploss is still calculated from the initial opening price, not averaged price. Regular stoploss rules still apply (cannot move down). - While `/stopbuy` command stops the bot from entering new trades, the position adjustment feature will continue buying new orders on existing trades. + While `/stopentry` command stops the bot from entering new trades, the position adjustment feature will continue buying new orders on existing trades. !!! Warning "Backtesting" During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so run-time performance will be affected. diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index add889681..ece8700de 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -149,7 +149,7 @@ You can create your own keyboard in `config.json`: !!! Note "Supported Commands" Only the following commands are allowed. Command arguments are not supported! - `/start`, `/stop`, `/status`, `/status table`, `/trades`, `/profit`, `/performance`, `/daily`, `/stats`, `/count`, `/locks`, `/balance`, `/stopbuy`, `/reload_config`, `/show_config`, `/logs`, `/whitelist`, `/blacklist`, `/edge`, `/help`, `/version` + `/start`, `/stop`, `/status`, `/status table`, `/trades`, `/profit`, `/performance`, `/daily`, `/stats`, `/count`, `/locks`, `/balance`, `/stopentry`, `/reload_config`, `/show_config`, `/logs`, `/whitelist`, `/blacklist`, `/edge`, `/help`, `/version` ## Telegram commands @@ -161,7 +161,7 @@ official commands. You can ask at any moment for help with `/help`. |----------|-------------| | `/start` | Starts the trader | `/stop` | Stops the trader -| `/stopbuy` | Stops the trader from opening new trades. Gracefully closes open trades according to their rules. +| `/stopbuy | /stopentry` | 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 | `/logs [limit]` | Show last log messages. diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index d84d50b7c..35ba6bab2 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -239,7 +239,7 @@ class FreqtradeBot(LoggingMixin): 'status': f"{len(open_trades)} open trades active.\n\n" f"Handle these trades manually on {self.exchange.name}, " - f"or '/start' the bot again and use '/stopbuy' " + f"or '/start' the bot again and use '/stopentry' " f"to handle open trades gracefully. \n" f"{'Note: Trades are simulated (dry run).' if self.config['dry_run'] else ''}", } diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index e0fef7be8..bf21715b7 100644 --- a/freqtrade/rpc/api_server/api_v1.py +++ b/freqtrade/rpc/api_server/api_v1.py @@ -216,9 +216,10 @@ def stop(rpc: RPC = Depends(get_rpc)): return rpc._rpc_stop() +@router.post('/stopentry', response_model=StatusMsg, tags=['botcontrol']) @router.post('/stopbuy', response_model=StatusMsg, tags=['botcontrol']) def stop_buy(rpc: RPC = Depends(get_rpc)): - return rpc._rpc_stopbuy() + return rpc._rpc_stopentry() @router.post('/reload_config', response_model=StatusMsg, tags=['botcontrol']) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index ed7f13a96..11311f671 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -657,7 +657,7 @@ class RPC: self._freqtrade.state = State.RELOAD_CONFIG return {'status': 'Reloading config ...'} - def _rpc_stopbuy(self) -> Dict[str, str]: + def _rpc_stopentry(self) -> Dict[str, str]: """ Handler to stop buying, but handle open trades gracefully. """ @@ -665,7 +665,7 @@ class RPC: # Set 'max_open_trades' to 0 self._freqtrade.config['max_open_trades'] = 0 - return {'status': 'No more buy will occur from now. Run /reload_config to reset.'} + return {'status': 'No more entries will occur from now. Run /reload_config to reset.'} def __exec_force_exit(self, trade: Trade, ordertype: Optional[str], amount: Optional[float] = None) -> None: diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 8ce2fa2e4..8c988d570 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -114,18 +114,20 @@ class Telegram(RPCHandler): # TODO: DRY! - its not good to list all valid cmds here. But otherwise # this needs refactoring of the whole telegram module (same # problem in _help()). - valid_keys: List[str] = [r'/start$', r'/stop$', r'/status$', r'/status table$', - r'/trades$', r'/performance$', r'/buys', r'/entries', - r'/sells', r'/exits', r'/mix_tags', - r'/daily$', r'/daily \d+$', r'/profit$', r'/profit \d+', - r'/stats$', r'/count$', r'/locks$', r'/balance$', - r'/stopbuy$', r'/reload_config$', r'/show_config$', - r'/logs$', r'/whitelist$', r'/whitelist(\ssorted|\sbaseonly)+$', - r'/blacklist$', r'/bl_delete$', - r'/weekly$', r'/weekly \d+$', r'/monthly$', r'/monthly \d+$', - r'/forcebuy$', r'/forcelong$', r'/forceshort$', - r'/forcesell$', r'/forceexit$', - r'/edge$', r'/health$', r'/help$', r'/version$'] + valid_keys: List[str] = [ + r'/start$', r'/stop$', r'/status$', r'/status table$', + r'/trades$', r'/performance$', r'/buys', r'/entries', + r'/sells', r'/exits', r'/mix_tags', + r'/daily$', r'/daily \d+$', r'/profit$', r'/profit \d+', + r'/stats$', r'/count$', r'/locks$', r'/balance$', + r'/stopbuy$', r'/stopentry$', r'/reload_config$', r'/show_config$', + r'/logs$', r'/whitelist$', r'/whitelist(\ssorted|\sbaseonly)+$', + r'/blacklist$', r'/bl_delete$', + r'/weekly$', r'/weekly \d+$', r'/monthly$', r'/monthly \d+$', + r'/forcebuy$', r'/forcelong$', r'/forceshort$', + r'/forcesell$', r'/forceexit$', + r'/edge$', r'/health$', r'/help$', r'/version$' + ] # Create keys for generation valid_keys_print = [k.replace('$', '') for k in valid_keys] @@ -182,7 +184,7 @@ class Telegram(RPCHandler): CommandHandler(['unlock', 'delete_locks'], self._delete_locks), CommandHandler(['reload_config', 'reload_conf'], self._reload_config), CommandHandler(['show_config', 'show_conf'], self._show_config), - CommandHandler('stopbuy', self._stopbuy), + CommandHandler(['stopbuy', 'stopentry'], self._stopentry), CommandHandler('whitelist', self._whitelist), CommandHandler('blacklist', self._blacklist), CommandHandler(['blacklist_delete', 'bl_delete'], self._blacklist_delete), @@ -984,7 +986,7 @@ class Telegram(RPCHandler): self._send_msg(f"Status: `{msg['status']}`") @authorized_only - def _stopbuy(self, update: Update, context: CallbackContext) -> None: + def _stopentry(self, update: Update, context: CallbackContext) -> None: """ Handler for /stop_buy. Sets max_open_trades to 0 and gracefully sells all open trades @@ -992,7 +994,7 @@ class Telegram(RPCHandler): :param update: message update :return: None """ - msg = self._rpc._rpc_stopbuy() + msg = self._rpc._rpc_stopentry() self._send_msg(f"Status: `{msg['status']}`") @authorized_only @@ -1488,7 +1490,7 @@ class Telegram(RPCHandler): "------------\n" "*/start:* `Starts the trader`\n" "*/stop:* Stops the trader\n" - "*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" + "*/stopentry:* `Stops entering, but handles open trades gracefully` \n" "*/forceexit |all:* `Instantly exits the given trade or all trades, " "regardless of profit`\n" "*/fx |all:* `Alias to /forceexit`\n" diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 7b42bf083..8bbf75a32 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -663,7 +663,7 @@ def test_rpc_stop(mocker, default_conf) -> None: assert freqtradebot.state == State.STOPPED -def test_rpc_stopbuy(mocker, default_conf) -> None: +def test_rpc_stopentry(mocker, default_conf) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -676,8 +676,8 @@ def test_rpc_stopbuy(mocker, default_conf) -> None: freqtradebot.state = State.RUNNING assert freqtradebot.config['max_open_trades'] != 0 - result = rpc._rpc_stopbuy() - assert {'status': 'No more buy will occur from now. Run /reload_config to reset.'} == result + result = rpc._rpc_stopentry() + assert {'status': 'No more entries will occur from now. Run /reload_config to reset.'} == result assert freqtradebot.config['max_open_trades'] == 0 diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 9aa965da2..5dfa77d8b 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -422,13 +422,20 @@ def test_api_reloadconf(botclient): assert ftbot.state == State.RELOAD_CONFIG -def test_api_stopbuy(botclient): +def test_api_stopentry(botclient): ftbot, client = botclient assert ftbot.config['max_open_trades'] != 0 rc = client_post(client, f"{BASE_URI}/stopbuy") assert_response(rc) - assert rc.json() == {'status': 'No more buy will occur from now. Run /reload_config to reset.'} + assert rc.json() == { + 'status': 'No more entries will occur from now. Run /reload_config to reset.'} + assert ftbot.config['max_open_trades'] == 0 + + rc = client_post(client, f"{BASE_URI}/stopentry") + assert_response(rc) + assert rc.json() == { + 'status': 'No more entries will occur from now. Run /reload_config to reset.'} assert ftbot.config['max_open_trades'] == 0 diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index a30115bd9..cde7025a7 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -103,7 +103,8 @@ def test_telegram_init(default_conf, mocker, caplog) -> None: "['stats'], ['daily'], ['weekly'], ['monthly'], " "['count'], ['locks'], ['unlock', 'delete_locks'], " "['reload_config', 'reload_conf'], ['show_config', 'show_conf'], " - "['stopbuy'], ['whitelist'], ['blacklist'], ['blacklist_delete', 'bl_delete'], " + "['stopbuy', 'stopentry'], ['whitelist'], ['blacklist'], " + "['blacklist_delete', 'bl_delete'], " "['logs'], ['edge'], ['health'], ['help'], ['version']" "]") @@ -896,10 +897,10 @@ def test_stopbuy_handle(default_conf, update, mocker) -> None: telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) assert freqtradebot.config['max_open_trades'] != 0 - telegram._stopbuy(update=update, context=MagicMock()) + telegram._stopentry(update=update, context=MagicMock()) assert freqtradebot.config['max_open_trades'] == 0 assert msg_mock.call_count == 1 - assert 'No more buy will occur from now. Run /reload_config to reset.' \ + assert 'No more entries will occur from now. Run /reload_config to reset.' \ in msg_mock.call_args_list[0][0][0]