Update protection-interface to support per-side locks
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Dict
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from freqtrade.enums import ExitType
|
||||
from freqtrade.persistence import Trade
|
||||
@@ -21,6 +21,7 @@ class StoplossGuard(IProtection):
|
||||
|
||||
self._trade_limit = protection_config.get('trade_limit', 10)
|
||||
self._disable_global_stop = protection_config.get('only_per_pair', False)
|
||||
self._only_per_side = protection_config.get('only_per_side', False)
|
||||
|
||||
def short_desc(self) -> str:
|
||||
"""
|
||||
@@ -36,7 +37,8 @@ class StoplossGuard(IProtection):
|
||||
return (f'{self._trade_limit} stoplosses in {self._lookback_period} min, '
|
||||
f'locking for {self._stop_duration} min.')
|
||||
|
||||
def _stoploss_guard(self, date_now: datetime, pair: str = None) -> ProtectionReturn:
|
||||
def _stoploss_guard(
|
||||
self, date_now: datetime, pair: Optional[str], side: str) -> ProtectionReturn:
|
||||
"""
|
||||
Evaluate recent trades
|
||||
"""
|
||||
@@ -48,15 +50,19 @@ class StoplossGuard(IProtection):
|
||||
ExitType.STOPLOSS_ON_EXCHANGE.value)
|
||||
and trade.close_profit and trade.close_profit < 0)]
|
||||
|
||||
if self._only_per_side and side:
|
||||
# Long or short trades only
|
||||
trades = [trade for trade in trades if trade.trade_direction == side]
|
||||
|
||||
if len(trades) < self._trade_limit:
|
||||
return False, None, None
|
||||
return False, None, None, None
|
||||
|
||||
self.log_once(f"Trading stopped due to {self._trade_limit} "
|
||||
f"stoplosses within {self._lookback_period} minutes.", logger.info)
|
||||
until = self.calculate_lock_end(trades, self._stop_duration)
|
||||
return True, until, self._reason()
|
||||
return True, until, self._reason(), (side if self._only_per_side else None)
|
||||
|
||||
def global_stop(self, date_now: datetime) -> ProtectionReturn:
|
||||
def global_stop(self, date_now: datetime, side: str) -> ProtectionReturn:
|
||||
"""
|
||||
Stops trading (position entering) for all pairs
|
||||
This must evaluate to true for the whole period of the "cooldown period".
|
||||
@@ -64,14 +70,14 @@ class StoplossGuard(IProtection):
|
||||
If true, all pairs will be locked with <reason> until <until>
|
||||
"""
|
||||
if self._disable_global_stop:
|
||||
return False, None, None
|
||||
return self._stoploss_guard(date_now, None)
|
||||
return False, None, None, None
|
||||
return self._stoploss_guard(date_now, None, side)
|
||||
|
||||
def stop_per_pair(self, pair: str, date_now: datetime) -> ProtectionReturn:
|
||||
def stop_per_pair(self, pair: str, date_now: datetime, side: str) -> ProtectionReturn:
|
||||
"""
|
||||
Stops trading (position entering) for this pair
|
||||
This must evaluate to true for the whole period of the "cooldown period".
|
||||
:return: Tuple of [bool, until, reason].
|
||||
If true, this pair will be locked with <reason> until <until>
|
||||
"""
|
||||
return self._stoploss_guard(date_now, pair)
|
||||
return self._stoploss_guard(date_now, pair, side)
|
||||
|
||||
Reference in New Issue
Block a user