diff --git a/config_examples/config_full.example.json b/config_examples/config_full.example.json index d361b5b00..f62f46293 100644 --- a/config_examples/config_full.example.json +++ b/config_examples/config_full.example.json @@ -145,7 +145,7 @@ "roi": "off", "emergency_exit": "off", "force_exit": "off", - "sell_signal": "off", + "exit_signal": "off", "trailing_stop_loss": "off", "stop_loss": "off", "stoploss_on_exchange": "off", diff --git a/docs/backtesting.md b/docs/backtesting.md index 9b5a410a3..96f52d160 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -279,7 +279,7 @@ A backtesting result will look like that: |:-------------------|--------:|------:|-------:|--------:| | trailing_stop_loss | 205 | 150 | 0 | 55 | | stop_loss | 166 | 0 | 0 | 166 | -| sell_signal | 56 | 36 | 0 | 20 | +| exit_signal | 56 | 36 | 0 | 20 | | force_exit | 2 | 0 | 0 | 2 | ====================================================== LEFT OPEN TRADES REPORT ====================================================== | Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Win Draw Loss Win% | @@ -362,7 +362,7 @@ Hence, keep in mind that your performance is an integral mix of all different el ### Exit reasons table The 2nd table contains a recap of exit reasons. -This table can tell you which area needs some additional work (e.g. all or many of the `sell_signal` trades are losses, so you should work on improving the sell signal, or consider disabling it). +This table can tell you which area needs some additional work (e.g. all or many of the `exit_signal` trades are losses, so you should work on improving the sell signal, or consider disabling it). ### Left open trades table diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 8897bddbb..583d4c037 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -393,7 +393,7 @@ class AwesomeStrategy(IStrategy): !!! Warning "Backtesting" Custom prices are supported in backtesting (starting with 2021.12), and orders will fill if the price falls within the candle's low/high range. Orders that don't fill immediately are subject to regular timeout handling, which happens once per (detail) candle. - `custom_exit_price()` is only called for sells of type Sell_signal and Custom exit. All other exit-types will use regular backtesting prices. + `custom_exit_price()` is only called for sells of type exit_signal and Custom exit. All other exit-types will use regular backtesting prices. ## Custom order timeout rules @@ -564,7 +564,7 @@ class AwesomeStrategy(IStrategy): :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_exit', 'emergency_exit'] + 'exit_signal', 'force_exit', 'emergency_exit'] :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return bool: When True is returned, then the exit-order is placed on the exchange. diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 5433fe23b..739c830bc 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -86,7 +86,7 @@ Example configuration showing the different settings: "roi": "silent", "emergency_exit": "on", "force_exit": "on", - "sell_signal": "silent", + "exit_signal": "silent", "trailing_stop_loss": "on", "stop_loss": "on", "stoploss_on_exchange": "on", diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index 8116949cf..2fe41a17b 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -470,7 +470,7 @@ class Edge: if len(ohlc_columns) - 1 < exit_index: break - exit_type = ExitType.SELL_SIGNAL + exit_type = ExitType.EXIT_SIGNAL exit_price = ohlc_columns[exit_index, 0] trade = {'pair': pair, diff --git a/freqtrade/enums/exittype.py b/freqtrade/enums/exittype.py index a2aa89305..b2c5b62ea 100644 --- a/freqtrade/enums/exittype.py +++ b/freqtrade/enums/exittype.py @@ -9,7 +9,7 @@ class ExitType(Enum): STOP_LOSS = "stop_loss" STOPLOSS_ON_EXCHANGE = "stoploss_on_exchange" TRAILING_STOP_LOSS = "trailing_stop_loss" - SELL_SIGNAL = "sell_signal" + EXIT_SIGNAL = "exit_signal" FORCE_EXIT = "force_exit" EMERGENCY_EXIT = "emergency_exit" CUSTOM_EXIT = "custom_exit" diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 332f0c499..bb185aaae 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -529,7 +529,7 @@ class Backtesting: # call the custom exit price,with default value as previous closerate current_profit = trade.calc_profit_ratio(closerate) order_type = self.strategy.order_types['exit'] - if sell.exit_type in (ExitType.SELL_SIGNAL, ExitType.CUSTOM_EXIT): + if sell.exit_type in (ExitType.EXIT_SIGNAL, ExitType.CUSTOM_EXIT): # Custom exit pricing only for sell-signals if order_type == 'limit': closerate = strategy_safe_wrapper(self.strategy.custom_exit_price, diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 5215c0ab2..43f6ce61d 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -768,7 +768,7 @@ class Telegram(RPCHandler): 'stop_loss': 'Stoploss', 'trailing_stop_loss': 'Trail. Stop', 'stoploss_on_exchange': 'Stoploss', - 'sell_signal': 'Sell Signal', + 'exit_signal': 'Exit Signal', 'force_exit': 'Force Exit', 'emergency_exit': 'Emergency Exit', } diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index f9f04f5b5..e9304deee 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -308,7 +308,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_exit', 'emergency_exit'] + 'exit_signal', 'force_exit', 'emergency_exit'] :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return bool: When True, then the exit-order is placed on the exchange. @@ -888,7 +888,7 @@ class IStrategy(ABC, HyperStrategyMixin): pass elif self.use_sell_signal and not enter: if exit_: - exit_signal = ExitType.SELL_SIGNAL + exit_signal = ExitType.EXIT_SIGNAL else: trade_type = "exit_short" if trade.is_short else "sell" custom_reason = strategy_safe_wrapper(self.custom_exit, default_retval=False)( @@ -904,7 +904,7 @@ class IStrategy(ABC, HyperStrategyMixin): custom_reason = custom_reason[:CUSTOM_EXIT_MAX_LENGTH] else: custom_reason = None - if exit_signal in (ExitType.CUSTOM_EXIT, ExitType.SELL_SIGNAL): + if exit_signal in (ExitType.CUSTOM_EXIT, ExitType.EXIT_SIGNAL): logger.debug(f"{trade.pair} - Sell signal received. " f"exit_type=ExitType.{exit_signal.name}" + (f", custom_reason={custom_reason}" if custom_reason else "")) diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index bf995ddfe..17dfa0873 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -162,7 +162,7 @@ def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_exit', 'emergency_exit'] + 'exit_signal', 'force_exit', 'emergency_exit'] :param current_time: datetime object, containing the current datetime :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return bool: When True is returned, then the exit-order is placed on the exchange. diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index 76005c734..a43e82b22 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -95,8 +95,8 @@ tc1 = BTContainer(data=[ [6, 5000, 5025, 4975, 4987, 6172, 0, 0], # should sell ], stop_loss=-0.99, roi={"0": float('inf')}, profit_perc=0.00, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=2), - BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=4, close_tick=6)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=2), + BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=4, close_tick=6)] ) # 3) Entered, sl 1%, candle drops 8% => Trade closed, 1% loss @@ -391,7 +391,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc 'trade_duration': '', 'open_rate': 17, 'close_rate': 17, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, @@ -402,7 +402,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc 'trade_duration': '', 'open_rate': 20, 'close_rate': 20, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, @@ -413,7 +413,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc 'trade_duration': '', 'open_rate': 26, 'close_rate': 34, - 'exit_type': 'sell_signal'} + 'exit_type': 'exit_signal'} ] trades_df = DataFrame(trades) diff --git a/tests/optimize/test_backtest_detail.py b/tests/optimize/test_backtest_detail.py index f4b4e2cc2..c2b41af80 100644 --- a/tests/optimize/test_backtest_detail.py +++ b/tests/optimize/test_backtest_detail.py @@ -23,7 +23,7 @@ tc0 = BTContainer(data=[ [4, 5010, 5011, 4977, 4995, 6172, 0, 0], [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_exit_signal=True, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 1: Stop-Loss Triggered 1% loss @@ -424,7 +424,7 @@ tc26 = BTContainer(data=[ [4, 5010, 5010, 4855, 4995, 6172, 0, 0], # Triggers stoploss + sellsignal acted on [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_exit_signal=True, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 27: (copy of test26 with leverage) @@ -441,7 +441,7 @@ tc27 = BTContainer(data=[ [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_exit_signal=True, leverage=5.0, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 28: (copy of test26 with leverage and as short) @@ -458,7 +458,7 @@ tc28 = BTContainer(data=[ [5, 4995, 4995, 4950, 4950, 6172, 0, 0, 0, 0]], stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_exit_signal=True, leverage=5.0, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4, is_short=True)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4, is_short=True)] ) # Test 29: Sell with signal sell in candle 3 (ROI at signal candle) # Stoploss at 10% (irrelevant), ROI at 5% (will trigger) @@ -486,7 +486,7 @@ tc30 = BTContainer(data=[ [4, 5010, 5251, 4855, 4995, 6172, 0, 0], # Triggers ROI, sell-signal acted on [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.05}, profit_perc=0.002, use_exit_signal=True, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 31: trailing_stop should raise so candle 3 causes a stoploss @@ -708,7 +708,7 @@ tc44 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.01, use_exit_signal=True, custom_exit_price=4552, - trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=3)] ) # Test 45: Custom exit price above all candles diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 023f46ef7..6b69f5481 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -11,7 +11,7 @@ from tests.conftest import get_patched_freqtradebot, log_has_re def generate_mock_trade(pair: str, fee: float, is_open: bool, - sell_reason: str = ExitType.SELL_SIGNAL, + sell_reason: str = ExitType.EXIT_SIGNAL, min_ago_open: int = None, min_ago_close: int = None, profit_rate: float = 0.9 ): diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index e098cd144..53801335d 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2310,7 +2310,7 @@ def test_handle_trade_use_sell_signal( else: patch_get_signal(freqtrade, enter_long=False, exit_long=True) assert freqtrade.handle_trade(trade) - assert log_has("ETH/USDT - Sell signal received. exit_type=ExitType.SELL_SIGNAL", + assert log_has("ETH/USDT - Sell signal received. exit_type=ExitType.EXIT_SIGNAL", caplog) @@ -3221,7 +3221,7 @@ def test_execute_trade_exit_custom_exit_price( freqtrade.execute_trade_exit( trade=trade, limit=ticker_usdt_sell_up()['ask' if is_short else 'bid'], - exit_check=ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL) + exit_check=ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL) ) # Sell price must be different to default bid price @@ -3249,8 +3249,8 @@ def test_execute_trade_exit_custom_exit_price( 'profit_ratio': profit_ratio, 'stake_currency': 'USDT', 'fiat_currency': 'USD', - 'sell_reason': ExitType.SELL_SIGNAL.value, - 'exit_reason': ExitType.SELL_SIGNAL.value, + 'sell_reason': ExitType.EXIT_SIGNAL.value, + 'exit_reason': ExitType.EXIT_SIGNAL.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, @@ -3630,18 +3630,18 @@ def test_execute_trade_exit_insufficient_funds_error(default_conf_usdt, ticker_u @pytest.mark.parametrize('profit_only,bid,ask,handle_first,handle_second,exit_type,is_short', [ # Enable profit - (True, 2.18, 2.2, False, True, ExitType.SELL_SIGNAL.value, False), - (True, 2.18, 2.2, False, True, ExitType.SELL_SIGNAL.value, True), + (True, 2.18, 2.2, False, True, ExitType.EXIT_SIGNAL.value, False), + (True, 2.18, 2.2, False, True, ExitType.EXIT_SIGNAL.value, True), # # Disable profit - (False, 3.19, 3.2, True, False, ExitType.SELL_SIGNAL.value, False), - (False, 3.19, 3.2, True, False, ExitType.SELL_SIGNAL.value, True), + (False, 3.19, 3.2, True, False, ExitType.EXIT_SIGNAL.value, False), + (False, 3.19, 3.2, True, False, ExitType.EXIT_SIGNAL.value, True), # # Enable loss # # * Shouldn't this be ExitType.STOP_LOSS.value (True, 0.21, 0.22, False, False, None, False), (True, 2.41, 2.42, False, False, None, True), # Disable loss - (False, 0.10, 0.22, True, False, ExitType.SELL_SIGNAL.value, False), - (False, 0.10, 0.22, True, False, ExitType.SELL_SIGNAL.value, True), + (False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, False), + (False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, True), ]) def test_sell_profit_only( default_conf_usdt, limit_order, limit_order_open, is_short, @@ -3669,7 +3669,7 @@ def test_sell_profit_only( }) freqtrade = FreqtradeBot(default_conf_usdt) patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short) - if exit_type == ExitType.SELL_SIGNAL.value: + if exit_type == ExitType.EXIT_SIGNAL.value: freqtrade.strategy.min_roi_reached = MagicMock(return_value=False) else: freqtrade.strategy.stop_loss_reached = MagicMock(return_value=ExitCheckTuple( diff --git a/tests/test_integration.py b/tests/test_integration.py index 9b689f2eb..c73157afd 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -53,7 +53,7 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, # Sell 3rd trade (not called for the first trade) should_sell_mock = MagicMock(side_effect=[ ExitCheckTuple(exit_type=ExitType.NONE), - ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL)] + ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL)] ) cancel_order_mock = MagicMock() mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss) @@ -123,7 +123,7 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, assert trade.is_open trade = trades[2] - assert trade.exit_reason == ExitType.SELL_SIGNAL.value + assert trade.exit_reason == ExitType.EXIT_SIGNAL.value assert not trade.is_open @@ -161,7 +161,7 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, mocker, balance_rati ) should_sell_mock = MagicMock(side_effect=[ ExitCheckTuple(exit_type=ExitType.NONE), - ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL), + ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL), ExitCheckTuple(exit_type=ExitType.NONE), ExitCheckTuple(exit_type=ExitType.NONE), ExitCheckTuple(exit_type=ExitType.NONE)]