From 6856963aef37303b40fd29a0745e22ff312dc11c Mon Sep 17 00:00:00 2001 From: rextea Date: Tue, 23 Mar 2021 10:09:41 +0200 Subject: [PATCH 1/8] Add confirm_trade_exit and confirm_trade_entry to backtesting --- freqtrade/optimize/backtesting.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 0b884dae5..1dcf6428b 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -30,7 +30,6 @@ from freqtrade.strategy.interface import IStrategy, SellCheckTuple, SellType from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper from freqtrade.wallets import Wallets - logger = logging.getLogger(__name__) # Indexes for backtest tuples @@ -252,8 +251,17 @@ class Backtesting: sell = self.strategy.should_sell(trade, sell_row[OPEN_IDX], # type: ignore sell_row[DATE_IDX], sell_row[BUY_IDX], sell_row[SELL_IDX], low=sell_row[LOW_IDX], high=sell_row[HIGH_IDX]) - if sell.sell_flag: + time_in_force = self.strategy.order_time_in_force['sell'] + + # confirm_trade_exit + if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=False)( + pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=sell_row[LOW_IDX], + time_in_force=time_in_force, + sell_reason=sell.sell_type.value): + return None + + if sell.sell_flag: trade.close_date = sell_row[DATE_IDX] trade.sell_reason = sell.sell_type.value trade_dur = int((trade.close_date_utc - trade.open_date_utc).total_seconds() // 60) @@ -271,6 +279,15 @@ class Backtesting: except DependencyException: return None min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, row[OPEN_IDX], -0.05) + + order_type = self.strategy.order_types['buy'] + time_in_force = self.strategy.order_time_in_force['sell'] + # confirm_trade_entry + if not strategy_safe_wrapper(self.strategy.confirm_trade_entry, default_retval=True)( + pair=pair, order_type=order_type, amount=stake_amount, rate=row[OPEN_IDX], + time_in_force=time_in_force): + return None + if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount): # Enter trade trade = LocalTrade( From eb5d69dcd486305d3448caf3eab1152dbd9cf59f Mon Sep 17 00:00:00 2001 From: rextea Date: Tue, 23 Mar 2021 10:12:08 +0200 Subject: [PATCH 2/8] Add confirm_trade_exit and confirm_trade_entry to backtesting --- freqtrade/optimize/backtesting.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 1dcf6428b..080e6b1a2 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -253,7 +253,6 @@ class Backtesting: low=sell_row[LOW_IDX], high=sell_row[HIGH_IDX]) time_in_force = self.strategy.order_time_in_force['sell'] - # confirm_trade_exit if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=False)( pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=sell_row[LOW_IDX], From dc4ea604dd6d1fc8bd6af7a68e5fba36f3e7c517 Mon Sep 17 00:00:00 2001 From: rextea Date: Tue, 23 Mar 2021 10:19:16 +0200 Subject: [PATCH 3/8] Add confirm_trade_exit and confirm_trade_entry to backtesting --- freqtrade/optimize/backtesting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 080e6b1a2..321b60ecd 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -254,7 +254,7 @@ class Backtesting: time_in_force = self.strategy.order_time_in_force['sell'] # confirm_trade_exit - if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=False)( + if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=sell_row[LOW_IDX], time_in_force=time_in_force, sell_reason=sell.sell_type.value): From f51f4b1817efd2451d4877478312f22d9acabefe Mon Sep 17 00:00:00 2001 From: rextea Date: Tue, 23 Mar 2021 10:35:46 +0200 Subject: [PATCH 4/8] Add confirm_trade_exit and confirm_trade_entry to backtesting --- freqtrade/optimize/backtesting.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 321b60ecd..d858acc1a 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -255,7 +255,8 @@ class Backtesting: time_in_force = self.strategy.order_time_in_force['sell'] # confirm_trade_exit if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( - pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, rate=sell_row[LOW_IDX], + pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, + rate=sell_row[LOW_IDX], time_in_force=time_in_force, sell_reason=sell.sell_type.value): return None From d795febf9243e667de70d06a8c2ff30e951f847a Mon Sep 17 00:00:00 2001 From: rextea Date: Wed, 24 Mar 2021 18:26:03 +0200 Subject: [PATCH 5/8] Add info to documantation --- docs/bot-basics.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/bot-basics.md b/docs/bot-basics.md index 13694c316..943af0362 100644 --- a/docs/bot-basics.md +++ b/docs/bot-basics.md @@ -53,6 +53,7 @@ This loop will be repeated again and again until the bot is stopped. * Calls `bot_loop_start()` once. * Calculate indicators (calls `populate_indicators()` once per pair). * Calculate buy / sell signals (calls `populate_buy_trend()` and `populate_sell_trend()` once per pair) +* Confirm trade buy / sell (calls `confirm_trade_entry()` and `confirm_trade_exit()` if implemented in the strategy) * Loops per candle simulating entry and exit points. * Generate backtest report output From ec15610bff2314e8f47620e410097106878ffd18 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 24 Mar 2021 19:21:07 +0100 Subject: [PATCH 6/8] Fix isort issue --- freqtrade/optimize/backtesting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index d858acc1a..7de5b171c 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -30,6 +30,7 @@ from freqtrade.strategy.interface import IStrategy, SellCheckTuple, SellType from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper from freqtrade.wallets import Wallets + logger = logging.getLogger(__name__) # Indexes for backtest tuples From 0ca95aa0c2035b41c9835f2291020222f9ed690d Mon Sep 17 00:00:00 2001 From: rextea Date: Thu, 25 Mar 2021 10:25:25 +0200 Subject: [PATCH 7/8] Change rate to acctual close rate --- freqtrade/optimize/backtesting.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 7de5b171c..00b2f278d 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -30,7 +30,6 @@ from freqtrade.strategy.interface import IStrategy, SellCheckTuple, SellType from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper from freqtrade.wallets import Wallets - logger = logging.getLogger(__name__) # Indexes for backtest tuples @@ -253,20 +252,21 @@ class Backtesting: sell_row[DATE_IDX], sell_row[BUY_IDX], sell_row[SELL_IDX], low=sell_row[LOW_IDX], high=sell_row[HIGH_IDX]) - time_in_force = self.strategy.order_time_in_force['sell'] - # confirm_trade_exit - if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( - pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, - rate=sell_row[LOW_IDX], - time_in_force=time_in_force, - sell_reason=sell.sell_type.value): - return None - if sell.sell_flag: trade.close_date = sell_row[DATE_IDX] trade.sell_reason = sell.sell_type.value trade_dur = int((trade.close_date_utc - trade.open_date_utc).total_seconds() // 60) closerate = self._get_close_rate(sell_row, trade, sell, trade_dur) + + # Confirm trade exit: + time_in_force = self.strategy.order_time_in_force['sell'] + if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( + pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, + rate=closerate, + time_in_force=time_in_force, + sell_reason=sell.sell_type.value): + return None + trade.close(closerate, show_msg=False) return trade @@ -283,7 +283,7 @@ class Backtesting: order_type = self.strategy.order_types['buy'] time_in_force = self.strategy.order_time_in_force['sell'] - # confirm_trade_entry + # Confirm trade entry: if not strategy_safe_wrapper(self.strategy.confirm_trade_entry, default_retval=True)( pair=pair, order_type=order_type, amount=stake_amount, rate=row[OPEN_IDX], time_in_force=time_in_force): From 292ea8c1d03b0ecf100d9a1935f0718f4c316cae Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 25 Mar 2021 09:34:33 +0100 Subject: [PATCH 8/8] Update backtesting.py --- freqtrade/optimize/backtesting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 00b2f278d..765e2844a 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -30,6 +30,7 @@ from freqtrade.strategy.interface import IStrategy, SellCheckTuple, SellType from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper from freqtrade.wallets import Wallets + logger = logging.getLogger(__name__) # Indexes for backtest tuples