diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index c8d281852..15aa3416c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -519,8 +519,7 @@ class FreqtradeBot: # reserve some percent defined in config (5% default) + stoploss amount_reserve_percent = 1.0 - self.config.get('amount_reserve_percent', constants.DEFAULT_AMOUNT_RESERVE_PERCENT) - if self.strategy.stoploss is not None: - amount_reserve_percent += self.strategy.stoploss + amount_reserve_percent += self.strategy.stoploss # it should not be more than 50% amount_reserve_percent = max(amount_reserve_percent, 0.5) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 63a3f784e..73af00fee 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -88,9 +88,6 @@ class StrategyResolver(IResolver): StrategyResolver._override_attribute_helper(strategy, config, attribute, default) - # Assign deprecated variable - to not break users code relying on this. - strategy.ticker_interval = strategy.timeframe - # Loop this list again to have output combined for attribute, _, subkey in attributes: if subkey and attribute in config[subkey]: @@ -98,11 +95,7 @@ class StrategyResolver(IResolver): elif attribute in config: logger.info("Strategy using %s: %s", attribute, config[attribute]) - # Sort and apply type conversions - strategy.minimal_roi = OrderedDict(sorted( - {int(key): value for (key, value) in strategy.minimal_roi.items()}.items(), - key=lambda t: t[0])) - strategy.stoploss = float(strategy.stoploss) + StrategyResolver._normalize_attributes(strategy) StrategyResolver._strategy_sanity_validations(strategy) return strategy @@ -131,6 +124,24 @@ class StrategyResolver(IResolver): setattr(strategy, attribute, default) config[attribute] = default + @staticmethod + def _normalize_attributes(strategy: IStrategy) -> IStrategy: + """ + Normalize attributes to have the correct type. + """ + # Assign deprecated variable - to not break users code relying on this. + if hasattr(strategy, 'timeframe'): + strategy.ticker_interval = strategy.timeframe + + # Sort and apply type conversions + if hasattr(strategy, 'minimal_roi'): + strategy.minimal_roi = OrderedDict(sorted( + {int(key): value for (key, value) in strategy.minimal_roi.items()}.items(), + key=lambda t: t[0])) + if hasattr(strategy, 'stoploss'): + strategy.stoploss = float(strategy.stoploss) + return strategy + @staticmethod def _strategy_sanity_validations(strategy): if not all(k in strategy.order_types for k in REQUIRED_ORDERTYPES): diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 81f4e7651..125211a85 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -551,8 +551,7 @@ class IStrategy(ABC): # evaluate if the stoploss was hit if stoploss is not on exchange # in Dry-Run, this handles stoploss logic as well, as the logic will not be different to # regular stoploss handling. - if ((self.stoploss is not None) and - (trade.stop_loss >= current_rate) and + if ((trade.stop_loss >= current_rate) and (not self.order_types.get('stoploss_on_exchange') or self.config['dry_run'])): sell_type = SellType.STOP_LOSS