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             | | ||||
| | Rejected Entry signals      | 3089                | | ||||
| | 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      | | ||||
| | 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             | | ||||
| | Rejected Entry signals      | 3089                | | ||||
| | 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      | | ||||
| | 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. | ||||
| - `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 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. | ||||
| - `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)`. | ||||
|   | ||||
| @@ -298,6 +298,8 @@ class Backtesting: | ||||
|         self.timedout_entry_orders = 0 | ||||
|         self.timedout_exit_orders = 0 | ||||
|         self.canceled_trade_entries = 0 | ||||
|         self.canceled_entry_orders = 0 | ||||
|         self.replaced_entry_orders = 0 | ||||
|         self.dataprovider.clear_cache() | ||||
|         if enable_protections: | ||||
|             self._load_protections(self.strategy) | ||||
| @@ -935,6 +937,7 @@ class Backtesting: | ||||
|                 return False | ||||
|             else: | ||||
|                 del trade.orders[trade.orders.index(order)] | ||||
|                 self.canceled_entry_orders += 1 | ||||
|  | ||||
|             # place new order if result was not None | ||||
|             if requested_rate: | ||||
| @@ -942,6 +945,7 @@ class Backtesting: | ||||
|                                   requested_rate=requested_rate, | ||||
|                                   requested_stake=(order.remaining * order.price), | ||||
|                                   direction='short' if trade.is_short else 'long') | ||||
|                 self.replaced_entry_orders += 1 | ||||
|             else: | ||||
|                 # assumption: there can't be multiple open entry orders at any given time | ||||
|                 return (trade.nr_of_successful_entries == 0) | ||||
| @@ -1090,6 +1094,8 @@ class Backtesting: | ||||
|             'timedout_entry_orders': self.timedout_entry_orders, | ||||
|             'timedout_exit_orders': self.timedout_exit_orders, | ||||
|             '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']), | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -469,6 +469,8 @@ def generate_strategy_stats(pairlist: List[str], | ||||
|         'timedout_entry_orders': content['timedout_entry_orders'], | ||||
|         'timedout_exit_orders': content['timedout_exit_orders'], | ||||
|         '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_setting': (config['max_open_trades'] | ||||
|                                     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']), | ||||
|         ]) | ||||
|  | ||||
|         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 | ||||
|         # command stores these results and newer version of freqtrade must be able to handle old | ||||
|         # results with missing new fields. | ||||
| @@ -802,7 +810,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: | ||||
|             ('Entry/Exit Timeouts', | ||||
|              f"{strat_results.get('timedout_entry_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 | ||||
|  | ||||
|             ('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_exit_orders': 0, | ||||
|         'canceled_trade_entries': 0, | ||||
|         'canceled_entry_orders': 0, | ||||
|         'replaced_entry_orders': 0, | ||||
|         'final_balance': 1000, | ||||
|     }) | ||||
|     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_exit_orders': 0, | ||||
|             'canceled_trade_entries': 0, | ||||
|             'canceled_entry_orders': 0, | ||||
|             'replaced_entry_orders': 0, | ||||
|             'final_balance': 1000, | ||||
|         }, | ||||
|         { | ||||
| @@ -1292,6 +1296,8 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat | ||||
|             'timedout_entry_orders': 0, | ||||
|             'timedout_exit_orders': 0, | ||||
|             'canceled_trade_entries': 0, | ||||
|             'canceled_entry_orders': 0, | ||||
|             'replaced_entry_orders': 0, | ||||
|             'final_balance': 1000, | ||||
|         } | ||||
|     ]) | ||||
| @@ -1435,6 +1441,8 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, | ||||
|             'timedout_entry_orders': 0, | ||||
|             'timedout_exit_orders': 0, | ||||
|             'canceled_trade_entries': 0, | ||||
|             'canceled_entry_orders': 0, | ||||
|             'replaced_entry_orders': 0, | ||||
|             'final_balance': 1000, | ||||
|         }, | ||||
|         { | ||||
| @@ -1445,6 +1453,8 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, | ||||
|             'timedout_entry_orders': 0, | ||||
|             'timedout_exit_orders': 0, | ||||
|             'canceled_trade_entries': 0, | ||||
|             'canceled_entry_orders': 0, | ||||
|             'replaced_entry_orders': 0, | ||||
|             'final_balance': 1000, | ||||
|         } | ||||
|     ]) | ||||
| @@ -1540,6 +1550,8 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, | ||||
|             'timedout_entry_orders': 0, | ||||
|             'timedout_exit_orders': 0, | ||||
|             'canceled_trade_entries': 0, | ||||
|             'canceled_entry_orders': 0, | ||||
|             'replaced_entry_orders': 0, | ||||
|             'final_balance': 1000, | ||||
|         }, | ||||
|         { | ||||
| @@ -1550,6 +1562,8 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, | ||||
|             'timedout_entry_orders': 0, | ||||
|             'timedout_exit_orders': 0, | ||||
|             'canceled_trade_entries': 0, | ||||
|             'canceled_entry_orders': 0, | ||||
|             'replaced_entry_orders': 0, | ||||
|             'final_balance': 1000, | ||||
|         } | ||||
|     ]) | ||||
| @@ -1614,6 +1628,8 @@ def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testda | ||||
|         'timedout_entry_orders': 0, | ||||
|         'timedout_exit_orders': 0, | ||||
|         'canceled_trade_entries': 0, | ||||
|         'canceled_entry_orders': 0, | ||||
|         'replaced_entry_orders': 0, | ||||
|         'final_balance': 1000, | ||||
|     }) | ||||
|     mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist', | ||||
|   | ||||
| @@ -369,6 +369,8 @@ def test_hyperopt_format_results(hyperopt): | ||||
|         'timedout_entry_orders': 0, | ||||
|         'timedout_exit_orders': 0, | ||||
|         'canceled_trade_entries': 0, | ||||
|         'canceled_entry_orders': 0, | ||||
|         'replaced_entry_orders': 0, | ||||
|         'backtest_start_time': 1619718665, | ||||
|         'backtest_end_time': 1619718665, | ||||
|     } | ||||
| @@ -440,6 +442,8 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None: | ||||
|         'timedout_entry_orders': 0, | ||||
|         'timedout_exit_orders': 0, | ||||
|         'canceled_trade_entries': 0, | ||||
|         'canceled_entry_orders': 0, | ||||
|         'replaced_entry_orders': 0, | ||||
|         'final_balance': 1000, | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -88,6 +88,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir): | ||||
|         'timedout_entry_orders': 0, | ||||
|         'timedout_exit_orders': 0, | ||||
|         'canceled_trade_entries': 0, | ||||
|         'canceled_entry_orders': 0, | ||||
|         'replaced_entry_orders': 0, | ||||
|         'backtest_start_time': Arrow.utcnow().int_timestamp, | ||||
|         'backtest_end_time': Arrow.utcnow().int_timestamp, | ||||
|         'run_id': '123', | ||||
| @@ -141,6 +143,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir): | ||||
|         'timedout_entry_orders': 0, | ||||
|         'timedout_exit_orders': 0, | ||||
|         'canceled_trade_entries': 0, | ||||
|         'canceled_entry_orders': 0, | ||||
|         'replaced_entry_orders': 0, | ||||
|         'backtest_start_time': Arrow.utcnow().int_timestamp, | ||||
|         'backtest_end_time': Arrow.utcnow().int_timestamp, | ||||
|         'run_id': '124', | ||||
|   | ||||
		Reference in New Issue
	
	Block a user