diff --git a/docs/strategy-advanced.md b/docs/strategy-advanced.md index 74de614f6..374c675a2 100644 --- a/docs/strategy-advanced.md +++ b/docs/strategy-advanced.md @@ -49,7 +49,7 @@ from freqtrade.exchange import timeframe_to_prev_date class AwesomeStrategy(IStrategy): def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: float, - rate: float, time_in_force: str, sell_reason: str, + rate: float, time_in_force: str, exit_reason: str, current_time: 'datetime', **kwargs) -> bool: # Obtain pair dataframe. dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) @@ -125,7 +125,7 @@ def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame The provided exit-tag is then used as sell-reason - and shown as such in backtest results. !!! Note - `sell_reason` is limited to 100 characters, remaining data will be truncated. + `exit_reason` is limited to 100 characters, remaining data will be truncated. ## Strategy version diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 7f819d5d0..6474ffcaa 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -546,7 +546,7 @@ class AwesomeStrategy(IStrategy): # ... populate_* methods def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, - rate: float, time_in_force: str, sell_reason: str, + rate: float, time_in_force: str, exit_reason: str, current_time: datetime, **kwargs) -> bool: """ Called right before placing a regular sell order. @@ -562,7 +562,7 @@ class AwesomeStrategy(IStrategy): :param amount: Amount in quote currency. :param rate: Rate that's going to be used when using limit orders :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). - :param sell_reason: Sell reason. + :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', 'sell_signal', 'force_sell', 'emergency_sell'] :param current_time: datetime object, containing the current datetime @@ -570,7 +570,7 @@ class AwesomeStrategy(IStrategy): :return bool: When True is returned, then the sell-order is placed on the exchange. False aborts the process """ - if sell_reason == 'force_sell' and trade.calc_profit_ratio(rate) < 0: + if exit_reason == 'force_sell' and trade.calc_profit_ratio(rate) < 0: # Reject force-sells with negative profit # This is just a sample, please adjust to your needs # (this does not necessarily make sense, assuming you know when you're force-selling) diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index 4d6de440f..3a66ae9b3 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -20,6 +20,7 @@ If you intend on using markets other than spot markets, please migrate your stra * New `side` argument to callbacks without trade object * `custom_stake_amount` * `confirm_trade_entry` +* Changed argument name in `confirm_trade_exit` * Renamed `trade.nr_of_successful_buys` to `trade.nr_of_successful_entries` (mostly relevant for `adjust_trade_position()`). * Introduced new [`leverage` callback](strategy-callbacks.md#leverage-callback). * Informative pairs can now pass a 3rd element in the Tuple, defining the candle type. @@ -149,16 +150,17 @@ class AwesomeStrategy(IStrategy): New string argument `side` - which can be either `"long"` or `"short"`. -``` python hl_lines="5" +``` python hl_lines="4" class AwesomeStrategy(IStrategy): def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, current_time: datetime, entry_tag: Optional[str], **kwargs) -> bool: return True ``` + After: -``` python hl_lines="5" +``` python hl_lines="4" class AwesomeStrategy(IStrategy): def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float, time_in_force: str, current_time: datetime, entry_tag: Optional[str], @@ -166,6 +168,29 @@ class AwesomeStrategy(IStrategy): return True ``` +### `confirm_trade_exit` + +Changed argument `sell_reason` to `exit_reason`. +For compatibility, `sell_reason` will still be provided for a limited time. + +``` python hl_lines="3" +class AwesomeStrategy(IStrategy): + def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, + rate: float, time_in_force: str, sell_reason: str, + current_time: datetime, **kwargs) -> bool: + return True +``` + +After: + +``` python hl_lines="3" +class AwesomeStrategy(IStrategy): + def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, + rate: float, time_in_force: str, exit_reason: str, + current_time: datetime, **kwargs) -> bool: + return True +``` + ### Adjust trade position changes While adjust-trade-position itself did not change, you should no longer use `trade.nr_of_successful_buys` - and instead use `trade.nr_of_successful_entries`, which will also include short entries. diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 0d87ca706..534fa8425 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1385,7 +1385,8 @@ class FreqtradeBot(LoggingMixin): if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit, - time_in_force=time_in_force, sell_reason=sell_reason.sell_reason, + time_in_force=time_in_force, exit_reason=sell_reason.sell_reason, + sell_reason=sell_reason.sell_reason, # sellreason -> compatibility current_time=datetime.now(timezone.utc)): logger.info(f"User requested abortion of exiting {trade.pair}") return False diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 7d482ba99..b4726f753 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -553,7 +553,8 @@ class Backtesting: pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=closerate, time_in_force=time_in_force, - sell_reason=sell.sell_reason, + sell_reason=sell.sell_reason, # deprecated + exit_reason=sell.sell_reason, current_time=sell_candle_time): return None diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 69dc80128..7b07d82c1 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -290,7 +290,7 @@ class IStrategy(ABC, HyperStrategyMixin): return True def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, - rate: float, time_in_force: str, sell_reason: str, + rate: float, time_in_force: str, exit_reason: str, current_time: datetime, **kwargs) -> bool: """ Called right before placing a regular exit order. @@ -307,7 +307,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param amount: Amount in quote currency. :param rate: Rate that's going to be used when using limit orders :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). - :param sell_reason: Exit reason. + :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', 'sell_signal', 'force_sell', 'emergency_sell'] :param current_time: datetime object, containing the current datetime diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index d98adfa07..0ceeca982 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -143,7 +143,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, - rate: float, time_in_force: str, sell_reason: str, + rate: float, time_in_force: str, exit_reason: str, current_time: 'datetime', **kwargs) -> bool: """ Called right before placing a regular sell order. @@ -160,7 +160,7 @@ def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: :param amount: Amount in quote currency. :param rate: Rate that's going to be used when using limit orders :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). - :param sell_reason: Sell reason. + :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', 'sell_signal', 'force_sell', 'emergency_sell'] :param current_time: datetime object, containing the current datetime diff --git a/tests/strategy/test_default_strategy.py b/tests/strategy/test_default_strategy.py index a9d11e52f..5cb8fce16 100644 --- a/tests/strategy/test_default_strategy.py +++ b/tests/strategy/test_default_strategy.py @@ -46,7 +46,8 @@ def test_strategy_test_v3(result, fee, is_short, side): current_time=datetime.utcnow(), side=side, entry_tag=None) is True assert strategy.confirm_trade_exit(pair='ETH/BTC', trade=trade, order_type='limit', amount=0.1, - rate=20000, time_in_force='gtc', sell_reason='roi', + rate=20000, time_in_force='gtc', exit_reason='roi', + sell_reason='roi', current_time=datetime.utcnow(), side=side) is True