sell_signal -> exit_signal
This commit is contained in:
		| @@ -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", | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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', | ||||
|         } | ||||
|   | ||||
| @@ -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 "")) | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|                         ): | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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)] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user