diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index b80442ca0..c6e676df8 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -2421,7 +2421,9 @@ class FreqtradeBot(LoggingMixin): def handle_protections(self, pair: str, side: LongShort) -> None: # Lock pair for one candle to prevent immediate re-entries self.strategy.lock_pair(pair, datetime.now(UTC), reason="Auto lock", side=side) - prot_trig = self.protections.stop_per_pair(pair, side=side) + starting_balance = self.wallets.get_starting_balance() + prot_trig = self.protections.stop_per_pair( + pair, side=side, starting_balance=starting_balance) if prot_trig: msg: RPCProtectionMsg = { "type": RPCMessageType.PROTECTION_TRIGGER, @@ -2430,7 +2432,7 @@ class FreqtradeBot(LoggingMixin): } self.rpc.send_msg(msg) - prot_trig_glb = self.protections.global_stop(side=side) + prot_trig_glb = self.protections.global_stop(side=side, starting_balance=starting_balance) if prot_trig_glb: msg = { "type": RPCMessageType.PROTECTION_TRIGGER_GLOBAL, diff --git a/freqtrade/plugins/protectionmanager.py b/freqtrade/plugins/protectionmanager.py index 0eda8422f..12732b86d 100644 --- a/freqtrade/plugins/protectionmanager.py +++ b/freqtrade/plugins/protectionmanager.py @@ -47,13 +47,17 @@ class ProtectionManager: """ return [{p.name: p.short_desc()} for p in self._protection_handlers] - def global_stop(self, now: datetime | None = None, side: LongShort = "long") -> PairLock | None: + def global_stop( + self, now: datetime | None = None, side: LongShort = "long", starting_balance: float = 0.0 + ) -> PairLock | None: if not now: now = datetime.now(UTC) result = None for protection_handler in self._protection_handlers: if protection_handler.has_global_stop: - lock = protection_handler.global_stop(date_now=now, side=side) + lock = protection_handler.global_stop( + date_now=now, side=side, starting_balance=starting_balance + ) if lock and lock.until: if not PairLocks.is_global_lock(lock.until, side=lock.lock_side): result = PairLocks.lock_pair( @@ -62,14 +66,17 @@ class ProtectionManager: return result def stop_per_pair( - self, pair, now: datetime | None = None, side: LongShort = "long" + self, pair, now: datetime | None = None, side: LongShort = "long", + starting_balance: float = 0.0 ) -> PairLock | None: if not now: now = datetime.now(UTC) result = None for protection_handler in self._protection_handlers: if protection_handler.has_local_stop: - lock = protection_handler.stop_per_pair(pair=pair, date_now=now, side=side) + lock = protection_handler.stop_per_pair( + pair=pair, date_now=now, side=side, starting_balance=starting_balance + ) if lock and lock.until: if not PairLocks.is_pair_locked(pair, lock.until, lock.lock_side): result = PairLocks.lock_pair( diff --git a/freqtrade/plugins/protections/cooldown_period.py b/freqtrade/plugins/protections/cooldown_period.py index 0f6aaa79a..40c7b1aee 100644 --- a/freqtrade/plugins/protections/cooldown_period.py +++ b/freqtrade/plugins/protections/cooldown_period.py @@ -52,7 +52,9 @@ class CooldownPeriod(IProtection): return None - def global_stop(self, date_now: datetime, side: LongShort) -> ProtectionReturn | None: + def global_stop( + self, date_now: datetime, side: LongShort, starting_balance: float = 0.0 + ) -> ProtectionReturn | None: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -63,7 +65,7 @@ class CooldownPeriod(IProtection): return None def stop_per_pair( - self, pair: str, date_now: datetime, side: LongShort + self, pair: str, date_now: datetime, side: LongShort, starting_balance: float = 0.0 ) -> ProtectionReturn | None: """ Stops trading (position entering) for this pair diff --git a/freqtrade/plugins/protections/iprotection.py b/freqtrade/plugins/protections/iprotection.py index 8f2f51729..35c5e02bc 100644 --- a/freqtrade/plugins/protections/iprotection.py +++ b/freqtrade/plugins/protections/iprotection.py @@ -102,7 +102,9 @@ class IProtection(LoggingMixin, ABC): """ @abstractmethod - def global_stop(self, date_now: datetime, side: LongShort) -> ProtectionReturn | None: + def global_stop( + self, date_now: datetime, side: LongShort, starting_balance: float = 0.0 + ) -> ProtectionReturn | None: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -110,7 +112,7 @@ class IProtection(LoggingMixin, ABC): @abstractmethod def stop_per_pair( - self, pair: str, date_now: datetime, side: LongShort + self, pair: str, date_now: datetime, side: LongShort, starting_balance: float = 0.0 ) -> ProtectionReturn | None: """ Stops trading (position entering) for this pair diff --git a/freqtrade/plugins/protections/low_profit_pairs.py b/freqtrade/plugins/protections/low_profit_pairs.py index 84934f394..6e4ee6942 100644 --- a/freqtrade/plugins/protections/low_profit_pairs.py +++ b/freqtrade/plugins/protections/low_profit_pairs.py @@ -81,7 +81,9 @@ class LowProfitPairs(IProtection): return None - def global_stop(self, date_now: datetime, side: LongShort) -> ProtectionReturn | None: + def global_stop( + self, date_now: datetime, side: LongShort, starting_balance: float = 0.0 + ) -> ProtectionReturn | None: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -91,7 +93,7 @@ class LowProfitPairs(IProtection): return None def stop_per_pair( - self, pair: str, date_now: datetime, side: LongShort + self, pair: str, date_now: datetime, side: LongShort, starting_balance: float = 0.0 ) -> ProtectionReturn | None: """ Stops trading (position entering) for this pair diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index a429a2f80..d7b267b5c 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -86,7 +86,9 @@ class StoplossGuard(IProtection): lock_side=(side if self._only_per_side else "*"), ) - def global_stop(self, date_now: datetime, side: LongShort) -> ProtectionReturn | None: + def global_stop( + self, date_now: datetime, side: LongShort, starting_balance: float = 0.0 + ) -> ProtectionReturn | None: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -98,7 +100,7 @@ class StoplossGuard(IProtection): return self._stoploss_guard(date_now, None, side) def stop_per_pair( - self, pair: str, date_now: datetime, side: LongShort + self, pair: str, date_now: datetime, side: LongShort, starting_balance: float = 0.0 ) -> ProtectionReturn | None: """ Stops trading (position entering) for this pair