diff --git a/freqtrade/plugins/protections/cooldown_period.py b/freqtrade/plugins/protections/cooldown_period.py index 3391d175a..9608a51cc 100644 --- a/freqtrade/plugins/protections/cooldown_period.py +++ b/freqtrade/plugins/protections/cooldown_period.py @@ -43,11 +43,7 @@ class CooldownPeriod(IProtection): # Ignore type error as we know we only get closed trades. trade = sorted(trades, key=lambda t: t.close_date)[-1] # type: ignore self.log_once(f"Cooldown for {pair} for {self.stop_duration_str}.", logger.info) - - if self._unlock_at is not None: - until = self.calculate_unlock_at() - else: - until = self.calculate_lock_end([trade], self._stop_duration) + until = self.calculate_lock_end([trade]) return ProtectionReturn( lock=True, diff --git a/freqtrade/plugins/protections/iprotection.py b/freqtrade/plugins/protections/iprotection.py index c02fedfb2..f4278be77 100644 --- a/freqtrade/plugins/protections/iprotection.py +++ b/freqtrade/plugins/protections/iprotection.py @@ -103,20 +103,6 @@ class IProtection(LoggingMixin, ABC): else: return f"for {self.stop_duration_str}" - def calculate_unlock_at(self) -> datetime: - """ - Calculate and update the unlock time based on the unlock at config. - """ - now_time = datetime.now(timezone.utc) - unlock_at = datetime.strptime( - str(self._protection_config.get("unlock_at")), "%H:%M" - ).replace(day=now_time.day, year=now_time.year, month=now_time.month) - - if unlock_at.time() < now_time.time(): - unlock_at = unlock_at.replace(day=now_time.day + 1) - - return unlock_at.replace(tzinfo=timezone.utc) - @abstractmethod def short_desc(self) -> str: """ @@ -142,15 +128,24 @@ class IProtection(LoggingMixin, ABC): If true, this pair will be locked with until """ - @staticmethod - def calculate_lock_end(trades: List[LocalTrade], stop_minutes: int) -> datetime: + def calculate_lock_end(self, trades: List[LocalTrade]) -> datetime: """ Get lock end time + Implicitly uses `self._stop_duration` or `self._unlock_at` depending on the configuration. """ max_date: datetime = max([trade.close_date for trade in trades if trade.close_date]) # coming from Database, tzinfo is not set. if max_date.tzinfo is None: max_date = max_date.replace(tzinfo=timezone.utc) - until = max_date + timedelta(minutes=stop_minutes) + if self._unlock_at is not None: + # unlock_at case with fixed hour of the day + until = self._unlock_at + hour, minutes = self._unlock_at.split(":") + unlock_at = max_date.replace(hour=int(hour), minute=int(minutes)) + if unlock_at < max_date: + unlock_at += timedelta(days=1) + return unlock_at + + until = max_date + timedelta(minutes=self._stop_duration) return until diff --git a/freqtrade/plugins/protections/low_profit_pairs.py b/freqtrade/plugins/protections/low_profit_pairs.py index 518a20c0f..f0023646a 100644 --- a/freqtrade/plugins/protections/low_profit_pairs.py +++ b/freqtrade/plugins/protections/low_profit_pairs.py @@ -70,11 +70,7 @@ class LowProfitPairs(IProtection): f"within {self._lookback_period} minutes.", logger.info, ) - - if self._unlock_at is not None: - until = self.calculate_unlock_at() - else: - until = self.calculate_lock_end(trades, self._stop_duration) + until = self.calculate_lock_end(trades) return ProtectionReturn( lock=True, diff --git a/freqtrade/plugins/protections/max_drawdown_protection.py b/freqtrade/plugins/protections/max_drawdown_protection.py index 6f1c1ebf8..5939ee9f0 100644 --- a/freqtrade/plugins/protections/max_drawdown_protection.py +++ b/freqtrade/plugins/protections/max_drawdown_protection.py @@ -71,10 +71,7 @@ class MaxDrawdown(IProtection): logger.info, ) - if self._unlock_at is not None: - until = self.calculate_unlock_at() - else: - until = self.calculate_lock_end(trades, self._stop_duration) + until = self.calculate_lock_end(trades) return ProtectionReturn( lock=True, diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index 21e883bbd..da7437178 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -78,12 +78,7 @@ class StoplossGuard(IProtection): f"stoplosses within {self._lookback_period} minutes.", logger.info, ) - - if self._unlock_at is not None: - until = self.calculate_unlock_at() - else: - until = self.calculate_lock_end(trades, self._stop_duration) - + until = self.calculate_lock_end(trades) return ProtectionReturn( lock=True, until=until,