Merge pull request #4047 from freqtrade/strategy_manatory

Ensure non-defined attributes fail correctly
This commit is contained in:
Matthias 2020-12-09 10:27:29 +01:00 committed by GitHub
commit 7126aa9514
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 12 deletions

View File

@ -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)

View File

@ -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):

View File

@ -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