Merge pull request #6854 from eSeR1805/feat_bt_cancel_entry_reporting
BT: Reporting canceled/replaced entry orders
This commit is contained in:
commit
7b9439f2e4
@ -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',
|
||||||
|
Loading…
Reference in New Issue
Block a user