diff --git a/docs/backtesting.md b/docs/backtesting.md index 813d339c9..7dd1f8f0b 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -275,7 +275,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_sell | 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% | @@ -357,7 +357,7 @@ Hence, keep in mind that your performance is an integral mix of all different el ### Sell reasons table The 2nd table contains a recap of sell 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-advanced.md b/docs/strategy-advanced.md index f6517331f..c9d0e5f9d 100644 --- a/docs/strategy-advanced.md +++ b/docs/strategy-advanced.md @@ -98,7 +98,7 @@ def custom_sell(self, pair: str, trade: Trade, current_time: datetime, current_r dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1].squeeze() if trade.enter_tag == 'buy_signal_rsi' and last_candle['rsi'] > 80: - return 'sell_signal_rsi' + return 'exit_signal_rsi' return None ``` diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 752f3f7b8..aac881fcd 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -557,7 +557,7 @@ class AwesomeStrategy(IStrategy): :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Sell reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_sell', 'emergency_sell'] + 'exit_signal', 'force_sell', 'emergency_sell'] :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 sell-order is placed on the exchange. diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 54e6f50cb..80dfb0ba9 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -86,7 +86,7 @@ Example configuration showing the different settings: "roi": "silent", "emergency_sell": "on", "force_sell": "on", - "sell_signal": "silent", + "exit_signal": "silent", "trailing_stop_loss": "on", "stop_loss": "on", "stoploss_on_exchange": "on", diff --git a/freqtrade/enums/exittype.py b/freqtrade/enums/exittype.py index a1e5e21e2..25d90a859 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" - EXIT_SIGNAL = "sell_signal" + EXIT_SIGNAL = "exit_signal" FORCE_SELL = "force_sell" EMERGENCY_SELL = "emergency_sell" CUSTOM_SELL = "custom_sell" diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index b8663ee6e..37102d396 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -346,7 +346,7 @@ class PairHistory(BaseModel): data: List[Any] length: int buy_signals: int - sell_signals: int + exit_signals: int enter_long_signals: int exit_long_signals: int enter_short_signals: int diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 56031df71..0800dde5c 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -958,7 +958,7 @@ class RPC: 'data': dataframe.values.tolist(), 'length': len(dataframe), 'buy_signals': signals['enter_long'], # Deprecated - 'sell_signals': signals['exit_long'], # Deprecated + 'exit_signals': signals['exit_long'], # Deprecated 'enter_long_signals': signals['enter_long'], 'exit_long_signals': signals['exit_long'], 'enter_short_signals': signals['enter_short'], diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 9a8ddd32b..900be0cac 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -693,7 +693,7 @@ class Telegram(RPCHandler): 'stop_loss': 'Stoploss', 'trailing_stop_loss': 'Trail. Stop', 'stoploss_on_exchange': 'Stoploss', - 'sell_signal': 'Sell Signal', + 'exit_signal': 'Sell Signal', 'force_sell': 'Forcesell', 'emergency_sell': 'Emergency Sell', } diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index eaf830fa1..a74c113b1 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -275,7 +275,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_sell', 'emergency_sell'] + 'exit_signal', 'force_sell', 'emergency_sell'] :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 sell-order/exit_short-order is placed on the exchange. @@ -784,7 +784,7 @@ class IStrategy(ABC, HyperStrategyMixin): and self.min_roi_reached(trade=trade, current_profit=current_profit, current_time=date)) - sell_signal = ExitType.NONE + exit_signal = ExitType.NONE custom_reason = '' # use provided rate in backtesting, not high/low. current_rate = rate @@ -795,14 +795,14 @@ class IStrategy(ABC, HyperStrategyMixin): pass elif self.use_exit_signal and not enter: if exit_: - sell_signal = ExitType.EXIT_SIGNAL + exit_signal = ExitType.EXIT_SIGNAL else: trade_type = "exit_short" if trade.is_short else "sell" custom_reason = strategy_safe_wrapper(self.custom_sell, default_retval=False)( pair=trade.pair, trade=trade, current_time=date, current_rate=current_rate, current_profit=current_profit) if custom_reason: - sell_signal = ExitType.CUSTOM_SELL + exit_signal = ExitType.CUSTOM_SELL if isinstance(custom_reason, str): if len(custom_reason) > CUSTOM_SELL_MAX_LENGTH: logger.warning(f'Custom {trade_type} reason returned from ' @@ -811,11 +811,11 @@ class IStrategy(ABC, HyperStrategyMixin): custom_reason = custom_reason[:CUSTOM_SELL_MAX_LENGTH] else: custom_reason = None - if sell_signal in (ExitType.CUSTOM_SELL, ExitType.EXIT_SIGNAL): + if exit_signal in (ExitType.CUSTOM_SELL, ExitType.EXIT_SIGNAL): logger.debug(f"{trade.pair} - Sell signal received. " - f"exit_type=ExitType.{sell_signal.name}" + + f"exit_type=ExitType.{exit_signal.name}" + (f", custom_reason={custom_reason}" if custom_reason else "")) - return SellCheckTuple(exit_type=sell_signal, exit_reason=custom_reason) + return SellCheckTuple(exit_type=exit_signal, exit_reason=custom_reason) # Sequence: # Exit-signal diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index 247159006..57a06782c 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -122,7 +122,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: Sell reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_sell', 'emergency_sell'] + 'exit_signal', 'force_sell', 'emergency_sell'] :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 sell-order is placed on the exchange. diff --git a/tests/conftest_trades.py b/tests/conftest_trades.py index 13e8a0d5a..9a7525975 100644 --- a/tests/conftest_trades.py +++ b/tests/conftest_trades.py @@ -103,7 +103,7 @@ def mock_trade_2(fee, is_short: bool): strategy='StrategyTestV3', timeframe=5, enter_tag='TEST1', - exit_reason='sell_signal', + exit_reason='exit_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2), is_short=is_short @@ -400,7 +400,7 @@ def short_trade(fee): open_order_id='dry_run_exit_short_12345', strategy='DefaultStrategy', timeframe=5, - exit_reason='sell_signal', # TODO-lev: Update to exit/close reason + exit_reason='exit_signal', # TODO-lev: Update to exit/close reason open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), # close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2), is_short=True @@ -489,7 +489,7 @@ def leverage_trade(fee): open_order_id='dry_run_leverage_buy_12368', strategy='DefaultStrategy', timeframe=5, - exit_reason='sell_signal', + exit_reason='exit_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300), close_date=datetime.now(tz=timezone.utc), interest_rate=0.0005 diff --git a/tests/conftest_trades_usdt.py b/tests/conftest_trades_usdt.py index 803e093da..2ca7caec3 100644 --- a/tests/conftest_trades_usdt.py +++ b/tests/conftest_trades_usdt.py @@ -89,7 +89,7 @@ def mock_trade_usdt_2(fee): open_order_id='dry_run_sell_12345', strategy='StrategyTestV2', timeframe=5, - exit_reason='sell_signal', + exit_reason='exit_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2), ) diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index 4554a80a0..3b3e417ff 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -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) @@ -457,7 +457,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 17, 'close_rate': 15, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, @@ -470,7 +470,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 20, 'close_rate': 10, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, 'profit_percent': '', @@ -482,7 +482,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 20, 'close_rate': 10, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, 'profit_percent': '', @@ -494,7 +494,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 20, 'close_rate': 10, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, 'profit_percent': '', @@ -506,7 +506,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 20, 'close_rate': 10, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, @@ -519,7 +519,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 26, 'close_rate': 134, - 'exit_type': 'sell_signal'} + 'exit_type': 'exit_signal'} ] trades_df = DataFrame(trades) @@ -551,7 +551,7 @@ def test_process_expectancy_only_wins(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 15, 'close_rate': 17, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, 'profit_percent': '', @@ -563,7 +563,7 @@ def test_process_expectancy_only_wins(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 10, 'close_rate': 20, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, 'profit_percent': '', @@ -575,7 +575,7 @@ def test_process_expectancy_only_wins(mocker, edge_conf, fee,): 'trade_duration': '', 'open_rate': 26, 'close_rate': 134, - 'exit_type': 'sell_signal'} + 'exit_type': 'exit_signal'} ] trades_df = DataFrame(trades) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 468431c1a..558faea59 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -973,7 +973,7 @@ def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee): res = rpc._rpc_exit_reason_performance(None) assert len(res) == 2 - assert res[0]['exit_reason'] == 'sell_signal' + assert res[0]['exit_reason'] == 'exit_signal' assert res[0]['count'] == 1 assert prec_satoshi(res[0]['profit_pct'], 0.5) assert res[1]['exit_reason'] == 'roi' @@ -984,7 +984,7 @@ def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee): res = rpc._rpc_exit_reason_performance('ETC/BTC') assert len(res) == 1 assert res[0]['count'] == 1 - assert res[0]['exit_reason'] == 'sell_signal' + assert res[0]['exit_reason'] == 'exit_signal' assert prec_satoshi(res[0]['profit_pct'], 0.5) @@ -1046,7 +1046,7 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee): res = rpc._rpc_mix_tag_performance(None) assert len(res) == 2 - assert res[0]['mix_tag'] == 'TEST1 sell_signal' + assert res[0]['mix_tag'] == 'TEST1 exit_signal' assert res[0]['count'] == 1 assert prec_satoshi(res[0]['profit_pct'], 0.5) assert res[1]['mix_tag'] == 'Other roi' @@ -1058,7 +1058,7 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee): assert len(res) == 1 assert res[0]['count'] == 1 - assert res[0]['mix_tag'] == 'TEST1 sell_signal' + assert res[0]['mix_tag'] == 'TEST1 exit_signal' assert prec_satoshi(res[0]['profit_pct'], 0.5) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 9dc7eccf4..df793c5ca 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2091,7 +2091,7 @@ def test_send_msg_sell_notification_no_fiat( ({'profit_percent': 1.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), ({'profit_percent': 0.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), ({'profit_percent': -5.0, 'exit_reason': 'stop_loss'}, "\N{WARNING SIGN}"), - ({'profit_percent': -2.0, 'exit_reason': 'sell_signal'}, "\N{CROSS MARK}"), + ({'profit_percent': -2.0, 'exit_reason': 'exit_signal'}, "\N{CROSS MARK}"), ]) def test__sell_emoji(default_conf, mocker, msg, expected): del default_conf['fiat_display_currency'] diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index bd21a0726..cba6d245e 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -69,22 +69,22 @@ def test_returns_latest_signal(ohlcv_history): mocked_history.loc[1, 'enter_long'] = 0 mocked_history.loc[1, 'enter_short'] = 1 mocked_history.loc[1, 'exit_short'] = 0 - mocked_history.loc[1, 'enter_tag'] = 'sell_signal_01' + mocked_history.loc[1, 'enter_tag'] = 'exit_signal_01' assert _STRATEGY.get_entry_signal( - 'ETH/BTC', '5m', mocked_history) == (SignalDirection.SHORT, 'sell_signal_01') + 'ETH/BTC', '5m', mocked_history) == (SignalDirection.SHORT, 'exit_signal_01') assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (False, False, None) assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (True, False, None) mocked_history.loc[1, 'enter_short'] = 0 mocked_history.loc[1, 'exit_short'] = 1 - mocked_history.loc[1, 'exit_tag'] = 'sell_signal_02' + mocked_history.loc[1, 'exit_tag'] = 'exit_signal_02' assert _STRATEGY.get_entry_signal( 'ETH/BTC', '5m', mocked_history) == (None, None) assert _STRATEGY.get_exit_signal( - 'ETH/BTC', '5m', mocked_history) == (False, False, 'sell_signal_02') + 'ETH/BTC', '5m', mocked_history) == (False, False, 'exit_signal_02') assert _STRATEGY.get_exit_signal( - 'ETH/BTC', '5m', mocked_history, True) == (False, True, 'sell_signal_02') + 'ETH/BTC', '5m', mocked_history, True) == (False, True, 'exit_signal_02') def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history): diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 07beac7f6..f601792d4 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -1966,7 +1966,7 @@ def test_handle_trade( freqtrade.wallets.update() patch_get_signal(freqtrade, enter_long=False, exit_short=is_short, - exit_long=not is_short, exit_tag='sell_signal1') + exit_long=not is_short, exit_tag='exit_signal1') assert freqtrade.handle_trade(trade) is True assert trade.open_order_id == exit_order['id'] @@ -1977,7 +1977,7 @@ def test_handle_trade( assert trade.close_profit == close_profit assert trade.calc_profit() == 5.685 assert trade.close_date is not None - assert trade.exit_reason == 'sell_signal1' + assert trade.exit_reason == 'exit_signal1' @pytest.mark.parametrize("is_short", [False, True])