Merge pull request #6854 from eSeR1805/feat_bt_cancel_entry_reporting
BT: Reporting canceled/replaced entry orders
This commit is contained in:
		| @@ -320,7 +320,9 @@ A backtesting result will look like that: | |||||||
| | Avg. Duration Loser         | 6:55:00             | | | Avg. Duration Loser         | 6:55:00             | | ||||||
| | Rejected Entry signals      | 3089                | | | Rejected Entry signals      | 3089                | | ||||||
| | Entry/Exit Timeouts         | 0 / 0               | | | Entry/Exit Timeouts         | 0 / 0               | | ||||||
| | Canceled Trade Entries      | 123                 | | | Canceled Trade Entries      | 34                  | | ||||||
|  | | Canceled Entry Orders       | 123                 | | ||||||
|  | | Replaced Entry Orders       | 89                  | | ||||||
| |                             |                     | | |                             |                     | | ||||||
| | Min balance                 | 0.00945123 BTC      | | | Min balance                 | 0.00945123 BTC      | | ||||||
| | Max balance                 | 0.01846651 BTC      | | | Max balance                 | 0.01846651 BTC      | | ||||||
| @@ -417,7 +419,9 @@ It contains some useful key metrics about performance of your strategy on backte | |||||||
| | Avg. Duration Loser         | 6:55:00             | | | Avg. Duration Loser         | 6:55:00             | | ||||||
| | Rejected Entry signals      | 3089                | | | Rejected Entry signals      | 3089                | | ||||||
| | Entry/Exit Timeouts         | 0 / 0               | | | Entry/Exit Timeouts         | 0 / 0               | | ||||||
| | Canceled Trade Entries      | 123                 | | | Canceled Trade Entries      | 34                  | | ||||||
|  | | Canceled Entry Orders       | 123                 | | ||||||
|  | | Replaced Entry Orders       | 89                  | | ||||||
| |                             |                     | | |                             |                     | | ||||||
| | Min balance                 | 0.00945123 BTC      | | | Min balance                 | 0.00945123 BTC      | | ||||||
| | Max balance                 | 0.01846651 BTC      | | | Max balance                 | 0.01846651 BTC      | | ||||||
| @@ -450,6 +454,8 @@ It contains some useful key metrics about performance of your strategy on backte | |||||||
| - `Rejected Entry signals`: Trade entry signals that could not be acted upon due to `max_open_trades` being reached. | - `Rejected Entry signals`: Trade entry signals that could not be acted upon due to `max_open_trades` being reached. | ||||||
| - `Entry/Exit Timeouts`: Entry/exit orders which did not fill (only applicable if custom pricing is used). | - `Entry/Exit Timeouts`: Entry/exit orders which did not fill (only applicable if custom pricing is used). | ||||||
| - `Canceled Trade Entries`: Number of trades that have been canceled by user request via `adjust_entry_price`. | - `Canceled Trade Entries`: Number of trades that have been canceled by user request via `adjust_entry_price`. | ||||||
|  | - `Canceled Entry Orders`: Number of entry orders that have been canceled by user request via `adjust_entry_price`. | ||||||
|  | - `Replaced Entry Orders`: Number of entry orders that have been replaced by user request via `adjust_entry_price`. | ||||||
| - `Min balance` / `Max balance`: Lowest and Highest Wallet balance during the backtest period. | - `Min balance` / `Max balance`: Lowest and Highest Wallet balance during the backtest period. | ||||||
| - `Max % of account underwater`: Maximum percentage your account has decreased from the top since the simulation started. | - `Max % of account underwater`: Maximum percentage your account has decreased from the top since the simulation started. | ||||||
| Calculated as the maximum of `(Max Balance - Current Balance) / (Max Balance)`. | Calculated as the maximum of `(Max Balance - Current Balance) / (Max Balance)`. | ||||||
|   | |||||||
| @@ -298,6 +298,8 @@ class Backtesting: | |||||||
|         self.timedout_entry_orders = 0 |         self.timedout_entry_orders = 0 | ||||||
|         self.timedout_exit_orders = 0 |         self.timedout_exit_orders = 0 | ||||||
|         self.canceled_trade_entries = 0 |         self.canceled_trade_entries = 0 | ||||||
|  |         self.canceled_entry_orders = 0 | ||||||
|  |         self.replaced_entry_orders = 0 | ||||||
|         self.dataprovider.clear_cache() |         self.dataprovider.clear_cache() | ||||||
|         if enable_protections: |         if enable_protections: | ||||||
|             self._load_protections(self.strategy) |             self._load_protections(self.strategy) | ||||||
| @@ -935,6 +937,7 @@ class Backtesting: | |||||||
|                 return False |                 return False | ||||||
|             else: |             else: | ||||||
|                 del trade.orders[trade.orders.index(order)] |                 del trade.orders[trade.orders.index(order)] | ||||||
|  |                 self.canceled_entry_orders += 1 | ||||||
|  |  | ||||||
|             # place new order if result was not None |             # place new order if result was not None | ||||||
|             if requested_rate: |             if requested_rate: | ||||||
| @@ -942,6 +945,7 @@ class Backtesting: | |||||||
|                                   requested_rate=requested_rate, |                                   requested_rate=requested_rate, | ||||||
|                                   requested_stake=(order.remaining * order.price), |                                   requested_stake=(order.remaining * order.price), | ||||||
|                                   direction='short' if trade.is_short else 'long') |                                   direction='short' if trade.is_short else 'long') | ||||||
|  |                 self.replaced_entry_orders += 1 | ||||||
|             else: |             else: | ||||||
|                 # assumption: there can't be multiple open entry orders at any given time |                 # assumption: there can't be multiple open entry orders at any given time | ||||||
|                 return (trade.nr_of_successful_entries == 0) |                 return (trade.nr_of_successful_entries == 0) | ||||||
| @@ -1090,6 +1094,8 @@ class Backtesting: | |||||||
|             'timedout_entry_orders': self.timedout_entry_orders, |             'timedout_entry_orders': self.timedout_entry_orders, | ||||||
|             'timedout_exit_orders': self.timedout_exit_orders, |             'timedout_exit_orders': self.timedout_exit_orders, | ||||||
|             'canceled_trade_entries': self.canceled_trade_entries, |             'canceled_trade_entries': self.canceled_trade_entries, | ||||||
|  |             'canceled_entry_orders': self.canceled_entry_orders, | ||||||
|  |             'replaced_entry_orders': self.replaced_entry_orders, | ||||||
|             'final_balance': self.wallets.get_total(self.strategy.config['stake_currency']), |             'final_balance': self.wallets.get_total(self.strategy.config['stake_currency']), | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -469,6 +469,8 @@ def generate_strategy_stats(pairlist: List[str], | |||||||
|         'timedout_entry_orders': content['timedout_entry_orders'], |         'timedout_entry_orders': content['timedout_entry_orders'], | ||||||
|         'timedout_exit_orders': content['timedout_exit_orders'], |         'timedout_exit_orders': content['timedout_exit_orders'], | ||||||
|         'canceled_trade_entries': content['canceled_trade_entries'], |         'canceled_trade_entries': content['canceled_trade_entries'], | ||||||
|  |         'canceled_entry_orders': content['canceled_entry_orders'], | ||||||
|  |         'replaced_entry_orders': content['replaced_entry_orders'], | ||||||
|         'max_open_trades': max_open_trades, |         'max_open_trades': max_open_trades, | ||||||
|         'max_open_trades_setting': (config['max_open_trades'] |         'max_open_trades_setting': (config['max_open_trades'] | ||||||
|                                     if config['max_open_trades'] != float('inf') else -1), |                                     if config['max_open_trades'] != float('inf') else -1), | ||||||
| @@ -754,6 +756,12 @@ def text_table_add_metrics(strat_results: Dict) -> str: | |||||||
|             ('Drawdown End', strat_results['drawdown_end']), |             ('Drawdown End', strat_results['drawdown_end']), | ||||||
|         ]) |         ]) | ||||||
|  |  | ||||||
|  |         entry_adjustment_metrics = [ | ||||||
|  |             ('Canceled Trade Entries', strat_results.get('canceled_trade_entries', 'N/A')), | ||||||
|  |             ('Canceled Entry Orders', strat_results.get('canceled_entry_orders', 'N/A')), | ||||||
|  |             ('Replaced Entry Orders', strat_results.get('replaced_entry_orders', 'N/A')), | ||||||
|  |         ] if strat_results.get('canceled_entry_orders', 0) > 0 else [] | ||||||
|  |  | ||||||
|         # Newly added fields should be ignored if they are missing in strat_results. hyperopt-show |         # Newly added fields should be ignored if they are missing in strat_results. hyperopt-show | ||||||
|         # command stores these results and newer version of freqtrade must be able to handle old |         # command stores these results and newer version of freqtrade must be able to handle old | ||||||
|         # results with missing new fields. |         # results with missing new fields. | ||||||
| @@ -802,7 +810,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: | |||||||
|             ('Entry/Exit Timeouts', |             ('Entry/Exit Timeouts', | ||||||
|              f"{strat_results.get('timedout_entry_orders', 'N/A')} / " |              f"{strat_results.get('timedout_entry_orders', 'N/A')} / " | ||||||
|              f"{strat_results.get('timedout_exit_orders', 'N/A')}"), |              f"{strat_results.get('timedout_exit_orders', 'N/A')}"), | ||||||
|             ('Canceled Trade Entries', strat_results.get('canceled_trade_entries', 'N/A')), |             *entry_adjustment_metrics, | ||||||
|             ('', ''),  # Empty line to improve readability |             ('', ''),  # Empty line to improve readability | ||||||
|  |  | ||||||
|             ('Min balance', round_coin_value(strat_results['csum_min'], |             ('Min balance', round_coin_value(strat_results['csum_min'], | ||||||
|   | |||||||
| @@ -1169,6 +1169,8 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir): | |||||||
|         'timedout_entry_orders': 0, |         'timedout_entry_orders': 0, | ||||||
|         'timedout_exit_orders': 0, |         'timedout_exit_orders': 0, | ||||||
|         'canceled_trade_entries': 0, |         'canceled_trade_entries': 0, | ||||||
|  |         'canceled_entry_orders': 0, | ||||||
|  |         'replaced_entry_orders': 0, | ||||||
|         'final_balance': 1000, |         'final_balance': 1000, | ||||||
|     }) |     }) | ||||||
|     mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', |     mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', | ||||||
| @@ -1282,6 +1284,8 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat | |||||||
|             'timedout_entry_orders': 0, |             'timedout_entry_orders': 0, | ||||||
|             'timedout_exit_orders': 0, |             'timedout_exit_orders': 0, | ||||||
|             'canceled_trade_entries': 0, |             'canceled_trade_entries': 0, | ||||||
|  |             'canceled_entry_orders': 0, | ||||||
|  |             'replaced_entry_orders': 0, | ||||||
|             'final_balance': 1000, |             'final_balance': 1000, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
| @@ -1292,6 +1296,8 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat | |||||||
|             'timedout_entry_orders': 0, |             'timedout_entry_orders': 0, | ||||||
|             'timedout_exit_orders': 0, |             'timedout_exit_orders': 0, | ||||||
|             'canceled_trade_entries': 0, |             'canceled_trade_entries': 0, | ||||||
|  |             'canceled_entry_orders': 0, | ||||||
|  |             'replaced_entry_orders': 0, | ||||||
|             'final_balance': 1000, |             'final_balance': 1000, | ||||||
|         } |         } | ||||||
|     ]) |     ]) | ||||||
| @@ -1435,6 +1441,8 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, | |||||||
|             'timedout_entry_orders': 0, |             'timedout_entry_orders': 0, | ||||||
|             'timedout_exit_orders': 0, |             'timedout_exit_orders': 0, | ||||||
|             'canceled_trade_entries': 0, |             'canceled_trade_entries': 0, | ||||||
|  |             'canceled_entry_orders': 0, | ||||||
|  |             'replaced_entry_orders': 0, | ||||||
|             'final_balance': 1000, |             'final_balance': 1000, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
| @@ -1445,6 +1453,8 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, | |||||||
|             'timedout_entry_orders': 0, |             'timedout_entry_orders': 0, | ||||||
|             'timedout_exit_orders': 0, |             'timedout_exit_orders': 0, | ||||||
|             'canceled_trade_entries': 0, |             'canceled_trade_entries': 0, | ||||||
|  |             'canceled_entry_orders': 0, | ||||||
|  |             'replaced_entry_orders': 0, | ||||||
|             'final_balance': 1000, |             'final_balance': 1000, | ||||||
|         } |         } | ||||||
|     ]) |     ]) | ||||||
| @@ -1540,6 +1550,8 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, | |||||||
|             'timedout_entry_orders': 0, |             'timedout_entry_orders': 0, | ||||||
|             'timedout_exit_orders': 0, |             'timedout_exit_orders': 0, | ||||||
|             'canceled_trade_entries': 0, |             'canceled_trade_entries': 0, | ||||||
|  |             'canceled_entry_orders': 0, | ||||||
|  |             'replaced_entry_orders': 0, | ||||||
|             'final_balance': 1000, |             'final_balance': 1000, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
| @@ -1550,6 +1562,8 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, | |||||||
|             'timedout_entry_orders': 0, |             'timedout_entry_orders': 0, | ||||||
|             'timedout_exit_orders': 0, |             'timedout_exit_orders': 0, | ||||||
|             'canceled_trade_entries': 0, |             'canceled_trade_entries': 0, | ||||||
|  |             'canceled_entry_orders': 0, | ||||||
|  |             'replaced_entry_orders': 0, | ||||||
|             'final_balance': 1000, |             'final_balance': 1000, | ||||||
|         } |         } | ||||||
|     ]) |     ]) | ||||||
| @@ -1614,6 +1628,8 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda | |||||||
|         'timedout_entry_orders': 0, |         'timedout_entry_orders': 0, | ||||||
|         'timedout_exit_orders': 0, |         'timedout_exit_orders': 0, | ||||||
|         'canceled_trade_entries': 0, |         'canceled_trade_entries': 0, | ||||||
|  |         'canceled_entry_orders': 0, | ||||||
|  |         'replaced_entry_orders': 0, | ||||||
|         'final_balance': 1000, |         'final_balance': 1000, | ||||||
|     }) |     }) | ||||||
|     mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', |     mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', | ||||||
|   | |||||||
| @@ -369,6 +369,8 @@ def test_hyperopt_format_results(hyperopt): | |||||||
|         'timedout_entry_orders': 0, |         'timedout_entry_orders': 0, | ||||||
|         'timedout_exit_orders': 0, |         'timedout_exit_orders': 0, | ||||||
|         'canceled_trade_entries': 0, |         'canceled_trade_entries': 0, | ||||||
|  |         'canceled_entry_orders': 0, | ||||||
|  |         'replaced_entry_orders': 0, | ||||||
|         'backtest_start_time': 1619718665, |         'backtest_start_time': 1619718665, | ||||||
|         'backtest_end_time': 1619718665, |         'backtest_end_time': 1619718665, | ||||||
|     } |     } | ||||||
| @@ -440,6 +442,8 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None: | |||||||
|         'timedout_entry_orders': 0, |         'timedout_entry_orders': 0, | ||||||
|         'timedout_exit_orders': 0, |         'timedout_exit_orders': 0, | ||||||
|         'canceled_trade_entries': 0, |         'canceled_trade_entries': 0, | ||||||
|  |         'canceled_entry_orders': 0, | ||||||
|  |         'replaced_entry_orders': 0, | ||||||
|         'final_balance': 1000, |         'final_balance': 1000, | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -88,6 +88,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir): | |||||||
|         'timedout_entry_orders': 0, |         'timedout_entry_orders': 0, | ||||||
|         'timedout_exit_orders': 0, |         'timedout_exit_orders': 0, | ||||||
|         'canceled_trade_entries': 0, |         'canceled_trade_entries': 0, | ||||||
|  |         'canceled_entry_orders': 0, | ||||||
|  |         'replaced_entry_orders': 0, | ||||||
|         'backtest_start_time': Arrow.utcnow().int_timestamp, |         'backtest_start_time': Arrow.utcnow().int_timestamp, | ||||||
|         'backtest_end_time': Arrow.utcnow().int_timestamp, |         'backtest_end_time': Arrow.utcnow().int_timestamp, | ||||||
|         'run_id': '123', |         'run_id': '123', | ||||||
| @@ -141,6 +143,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir): | |||||||
|         'timedout_entry_orders': 0, |         'timedout_entry_orders': 0, | ||||||
|         'timedout_exit_orders': 0, |         'timedout_exit_orders': 0, | ||||||
|         'canceled_trade_entries': 0, |         'canceled_trade_entries': 0, | ||||||
|  |         'canceled_entry_orders': 0, | ||||||
|  |         'replaced_entry_orders': 0, | ||||||
|         'backtest_start_time': Arrow.utcnow().int_timestamp, |         'backtest_start_time': Arrow.utcnow().int_timestamp, | ||||||
|         'backtest_end_time': Arrow.utcnow().int_timestamp, |         'backtest_end_time': Arrow.utcnow().int_timestamp, | ||||||
|         'run_id': '124', |         'run_id': '124', | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user