max_open_trades should be an integer

Max open trades will be always an integer in the strategy (-1 for infinity), but in the config -1 will be parsed as infinity
This commit is contained in:
Antonio Della Fortuna 2023-01-04 16:09:27 +01:00
parent 1c5e172683
commit f2fa476dc6
8 changed files with 27 additions and 16 deletions

View File

@ -332,7 +332,7 @@ def analyze_trade_parallelism(results: pd.DataFrame, timeframe: str) -> pd.DataF
def evaluate_result_multi(results: pd.DataFrame, timeframe: str, def evaluate_result_multi(results: pd.DataFrame, timeframe: str,
max_open_trades: int | float) -> pd.DataFrame: max_open_trades: int) -> pd.DataFrame:
""" """
Find overlapping trades by expanding each trade once per period it was open Find overlapping trades by expanding each trade once per period it was open
and then counting overlaps and then counting overlaps

View File

@ -521,7 +521,7 @@ class FreqtradeBot(LoggingMixin):
self.log_once(f"Pair {pair} is currently locked.", logger.info) self.log_once(f"Pair {pair} is currently locked.", logger.info)
return False return False
stake_amount = self.wallets.get_trade_stake_amount( stake_amount = self.wallets.get_trade_stake_amount(
pair, self.edge, self.config['max_open_trades']) pair, self.edge)
bid_check_dom = self.config.get('entry_pricing', {}).get('check_depth_of_market', {}) bid_check_dom = self.config.get('entry_pricing', {}).get('check_depth_of_market', {})
if ((bid_check_dom.get('enabled', False)) and if ((bid_check_dom.get('enabled', False)) and

View File

@ -920,7 +920,7 @@ class Backtesting:
trade.close(exit_row[OPEN_IDX], show_msg=False) trade.close(exit_row[OPEN_IDX], show_msg=False)
LocalTrade.close_bt_trade(trade) LocalTrade.close_bt_trade(trade)
def trade_slot_available(self, max_open_trades: int | float, open_trade_count: int) -> bool: def trade_slot_available(self, max_open_trades: int, open_trade_count: int) -> bool:
# Always allow trades when max_open_trades is enabled. # Always allow trades when max_open_trades is enabled.
if max_open_trades <= 0 or open_trade_count < max_open_trades: if max_open_trades <= 0 or open_trade_count < max_open_trades:
return True return True
@ -1051,7 +1051,7 @@ class Backtesting:
def backtest_loop( def backtest_loop(
self, row: Tuple, pair: str, current_time: datetime, end_date: datetime, self, row: Tuple, pair: str, current_time: datetime, end_date: datetime,
max_open_trades: int | float, max_open_trades: int,
open_trade_count_start: int, is_first: bool = True) -> int: open_trade_count_start: int, is_first: bool = True) -> int:
""" """
NOTE: This method is used by Hyperopt at each iteration. Please keep it optimized. NOTE: This method is used by Hyperopt at each iteration. Please keep it optimized.
@ -1123,7 +1123,7 @@ class Backtesting:
def backtest(self, processed: Dict, def backtest(self, processed: Dict,
start_date: datetime, end_date: datetime, start_date: datetime, end_date: datetime,
max_open_trades: int | float = 0) -> Dict[str, Any]: max_open_trades: int = 0) -> Dict[str, Any]:
""" """
Implement backtesting functionality Implement backtesting functionality
@ -1228,7 +1228,8 @@ class Backtesting:
# Use max_open_trades in backtesting, except --disable-max-market-positions is set # Use max_open_trades in backtesting, except --disable-max-market-positions is set
if self.config.get('use_max_market_positions', True): if self.config.get('use_max_market_positions', True):
# Must come from strategy config, as the strategy may modify this setting. # Must come from strategy config, as the strategy may modify this setting.
max_open_trades = self.strategy.config['max_open_trades'] max_open_trades = self.strategy.config['max_open_trades'] \
if self.strategy.config['max_open_trades'] != float('inf') else -1
else: else:
logger.info( logger.info(
'Ignoring max_open_trades (--disable-max-market-positions was used) ...') 'Ignoring max_open_trades (--disable-max-market-positions was used) ...')

View File

@ -119,11 +119,14 @@ class Hyperopt:
# Use max_open_trades for hyperopt as well, except --disable-max-market-positions is set # Use max_open_trades for hyperopt as well, except --disable-max-market-positions is set
if self.config.get('use_max_market_positions', True): if self.config.get('use_max_market_positions', True):
self.max_open_trades = self.config['max_open_trades'] self.max_open_trades = self.config['max_open_trades'] \
if self.config['max_open_trades'] != float('inf') else -1
else: else:
logger.debug('Ignoring max_open_trades (--disable-max-market-positions was used) ...') logger.debug('Ignoring max_open_trades (--disable-max-market-positions was used) ...')
self.max_open_trades = 0 self.max_open_trades = 0
print("Strategy max open trades", self.max_open_trades)
if HyperoptTools.has_space(self.config, 'sell'): if HyperoptTools.has_space(self.config, 'sell'):
# Make sure use_exit_signal is enabled # Make sure use_exit_signal is enabled
self.config['use_exit_signal'] = True self.config['use_exit_signal'] = True

View File

@ -191,7 +191,7 @@ def generate_tag_metrics(tag_type: str,
return [] return []
def generate_exit_reason_stats(max_open_trades: int | float, results: DataFrame) -> List[Dict]: def generate_exit_reason_stats(max_open_trades: int, results: DataFrame) -> List[Dict]:
""" """
Generate small table outlining Backtest results Generate small table outlining Backtest results
:param max_open_trades: Max_open_trades parameter :param max_open_trades: Max_open_trades parameter

View File

@ -104,13 +104,21 @@ class StrategyResolver(IResolver):
if (attribute in config if (attribute in config
and not isinstance(getattr(type(strategy), attribute, None), property)): and not isinstance(getattr(type(strategy), attribute, None), property)):
# Ensure Properties are not overwritten # Ensure Properties are not overwritten
setattr(strategy, attribute, config[attribute]) val = config[attribute]
# max_open_trades set to float('inf') in the config will be copied as -1 in the strategy
if attribute == 'max_open_trades' and val == float('inf'):
val = -1
setattr(strategy, attribute, val)
logger.info("Override strategy '%s' with value in config file: %s.", logger.info("Override strategy '%s' with value in config file: %s.",
attribute, config[attribute]) attribute, config[attribute])
elif hasattr(strategy, attribute): elif hasattr(strategy, attribute):
val = getattr(strategy, attribute) val = getattr(strategy, attribute)
# None's cannot exist in the config, so do not copy them # None's cannot exist in the config, so do not copy them
if val is not None: if val is not None:
# max_open_trades set to -1 in the strategy will be copied as infinity in the config
if attribute == 'max_open_trades' and val == -1:
config[attribute] = float('inf')
else:
config[attribute] = val config[attribute] = val
# Explicitly check for None here as other "falsy" values are possible # Explicitly check for None here as other "falsy" values are possible
elif default is not None: elif default is not None:
@ -129,8 +137,6 @@ class StrategyResolver(IResolver):
key=lambda t: t[0])) key=lambda t: t[0]))
if hasattr(strategy, 'stoploss'): if hasattr(strategy, 'stoploss'):
strategy.stoploss = float(strategy.stoploss) strategy.stoploss = float(strategy.stoploss)
if hasattr(strategy, 'max_open_trades') and strategy.max_open_trades == -1:
strategy.max_open_trades = float('inf')
return strategy return strategy
@staticmethod @staticmethod

View File

@ -55,7 +55,7 @@ class IStrategy(ABC, HyperStrategyMixin):
stoploss: float stoploss: float
# max open trades for the strategy # max open trades for the strategy
max_open_trades: int | float max_open_trades: int
# trailing stoploss # trailing stoploss
trailing_stop: bool = False trailing_stop: bool = False

View File

@ -371,19 +371,20 @@ def test_strategy_max_open_trades_infinity_from_strategy(caplog, default_conf):
strategy = StrategyResolver.load_strategy(default_conf) strategy = StrategyResolver.load_strategy(default_conf)
# this test assumes -1 set to 'max_open_trades' in CURRENT_TEST_STRATEGY # this test assumes -1 set to 'max_open_trades' in CURRENT_TEST_STRATEGY
assert strategy.max_open_trades == float('inf') assert strategy.max_open_trades == -1
assert default_conf['max_open_trades'] == float('inf')
def test_strategy_max_open_trades_infinity_from_config(caplog, default_conf): def test_strategy_max_open_trades_infinity_from_config(caplog, default_conf):
caplog.set_level(logging.INFO) caplog.set_level(logging.INFO)
default_conf.update({ default_conf.update({
'strategy': CURRENT_TEST_STRATEGY, 'strategy': CURRENT_TEST_STRATEGY,
'max_open_trades': -1 'max_open_trades': float('inf')
}) })
strategy = StrategyResolver.load_strategy(default_conf) strategy = StrategyResolver.load_strategy(default_conf)
assert strategy.max_open_trades == float('inf') assert strategy.max_open_trades == -1
@ pytest.mark.filterwarnings("ignore:deprecated") @ pytest.mark.filterwarnings("ignore:deprecated")