mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
implement pairlock side further
This commit is contained in:
parent
420836b1b2
commit
fc201bb4ff
|
@ -1445,7 +1445,7 @@ class PairLock(_DECL_BASE):
|
|||
f'lock_end_time={lock_end_time}, reason={self.reason}, active={self.active})')
|
||||
|
||||
@staticmethod
|
||||
def query_pair_locks(pair: Optional[str], now: datetime) -> Query:
|
||||
def query_pair_locks(pair: Optional[str], now: datetime, side: str = '*') -> Query:
|
||||
"""
|
||||
Get all currently active locks for this pair
|
||||
:param pair: Pair to check for. Returns all current locks if pair is empty
|
||||
|
@ -1456,6 +1456,9 @@ class PairLock(_DECL_BASE):
|
|||
PairLock.active.is_(True), ]
|
||||
if pair:
|
||||
filters.append(PairLock.pair == pair)
|
||||
if side != '*':
|
||||
filters.append(PairLock.direction == side)
|
||||
|
||||
return PairLock.query.filter(
|
||||
*filters
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ class PairLocks():
|
|||
|
||||
@staticmethod
|
||||
def lock_pair(pair: str, until: datetime, reason: str = None, *,
|
||||
now: datetime = None) -> PairLock:
|
||||
now: datetime = None, side: str) -> PairLock:
|
||||
"""
|
||||
Create PairLock from now to "until".
|
||||
Uses database by default, unless PairLocks.use_db is set to False,
|
||||
|
@ -40,12 +40,14 @@ class PairLocks():
|
|||
:param until: End time of the lock. Will be rounded up to the next candle.
|
||||
:param reason: Reason string that will be shown as reason for the lock
|
||||
:param now: Current timestamp. Used to determine lock start time.
|
||||
:param side: Side to lock pair, can be 'long', 'short' or '*'
|
||||
"""
|
||||
lock = PairLock(
|
||||
pair=pair,
|
||||
lock_time=now or datetime.now(timezone.utc),
|
||||
lock_end_time=timeframe_to_next_date(PairLocks.timeframe, until),
|
||||
reason=reason,
|
||||
direction=side,
|
||||
active=True
|
||||
)
|
||||
if PairLocks.use_db:
|
||||
|
@ -56,7 +58,8 @@ class PairLocks():
|
|||
return lock
|
||||
|
||||
@staticmethod
|
||||
def get_pair_locks(pair: Optional[str], now: Optional[datetime] = None) -> List[PairLock]:
|
||||
def get_pair_locks(
|
||||
pair: Optional[str], now: Optional[datetime] = None, side: str = '*') -> List[PairLock]:
|
||||
"""
|
||||
Get all currently active locks for this pair
|
||||
:param pair: Pair to check for. Returns all current locks if pair is empty
|
||||
|
@ -67,12 +70,13 @@ class PairLocks():
|
|||
now = datetime.now(timezone.utc)
|
||||
|
||||
if PairLocks.use_db:
|
||||
return PairLock.query_pair_locks(pair, now).all()
|
||||
return PairLock.query_pair_locks(pair, now, side).all()
|
||||
else:
|
||||
locks = [lock for lock in PairLocks.locks if (
|
||||
lock.lock_end_time >= now
|
||||
and lock.active is True
|
||||
and (pair is None or lock.pair == pair)
|
||||
and (side == '*' or lock.direction == side)
|
||||
)]
|
||||
return locks
|
||||
|
||||
|
@ -134,7 +138,7 @@ class PairLocks():
|
|||
lock.active = False
|
||||
|
||||
@staticmethod
|
||||
def is_global_lock(now: Optional[datetime] = None) -> bool:
|
||||
def is_global_lock(now: Optional[datetime] = None, side: str = '*') -> bool:
|
||||
"""
|
||||
:param now: Datetime object (generated via datetime.now(timezone.utc)).
|
||||
defaults to datetime.now(timezone.utc)
|
||||
|
@ -142,10 +146,10 @@ class PairLocks():
|
|||
if not now:
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
return len(PairLocks.get_pair_locks('*', now)) > 0
|
||||
return len(PairLocks.get_pair_locks('*', now, side)) > 0
|
||||
|
||||
@staticmethod
|
||||
def is_pair_locked(pair: str, now: Optional[datetime] = None) -> bool:
|
||||
def is_pair_locked(pair: str, now: Optional[datetime] = None, side: str = '*') -> bool:
|
||||
"""
|
||||
:param pair: Pair to check for
|
||||
:param now: Datetime object (generated via datetime.now(timezone.utc)).
|
||||
|
@ -154,7 +158,10 @@ class PairLocks():
|
|||
if not now:
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
return len(PairLocks.get_pair_locks(pair, now)) > 0 or PairLocks.is_global_lock(now)
|
||||
return (
|
||||
len(PairLocks.get_pair_locks(pair, now, side)) > 0
|
||||
or PairLocks.is_global_lock(now, side)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_all_locks() -> List[PairLock]:
|
||||
|
|
|
@ -54,8 +54,9 @@ class ProtectionManager():
|
|||
if protection_handler.has_global_stop:
|
||||
lock = protection_handler.global_stop(date_now=now, side=side)
|
||||
if lock and lock.until:
|
||||
if not PairLocks.is_global_lock(lock.until):
|
||||
result = PairLocks.lock_pair('*', lock.until, lock.reason, now=now)
|
||||
if not PairLocks.is_global_lock(lock.until, lock.lock_side):
|
||||
result = PairLocks.lock_pair(
|
||||
'*', lock.until, lock.reason, now=now, side=lock.lock_side)
|
||||
return result
|
||||
|
||||
def stop_per_pair(self, pair, now: Optional[datetime] = None,
|
||||
|
@ -68,6 +69,7 @@ class ProtectionManager():
|
|||
lock = protection_handler.stop_per_pair(
|
||||
pair=pair, date_now=now, side=side)
|
||||
if lock and lock.until:
|
||||
if not PairLocks.is_pair_locked(pair, lock.until):
|
||||
result = PairLocks.lock_pair(pair, lock.until, lock.reason, now=now)
|
||||
if not PairLocks.is_pair_locked(pair, lock.until, lock.lock_side):
|
||||
result = PairLocks.lock_pair(
|
||||
pair, lock.until, lock.reason, now=now, side=lock.lock_side)
|
||||
return result
|
||||
|
|
|
@ -20,7 +20,7 @@ class ProtectionReturn:
|
|||
lock: bool
|
||||
until: datetime
|
||||
reason: Optional[str]
|
||||
lock_side: Optional[str] = None
|
||||
lock_side: str = '*'
|
||||
|
||||
|
||||
class IProtection(LoggingMixin, ABC):
|
||||
|
|
|
@ -65,7 +65,7 @@ class StoplossGuard(IProtection):
|
|||
lock=True,
|
||||
until=until,
|
||||
reason=self._reason(),
|
||||
lock_side=(side if self._only_per_side else None)
|
||||
lock_side=(side if self._only_per_side else '*')
|
||||
)
|
||||
|
||||
def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]:
|
||||
|
|
|
@ -541,7 +541,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||
"""
|
||||
return self.__class__.__name__
|
||||
|
||||
def lock_pair(self, pair: str, until: datetime, reason: str = None) -> None:
|
||||
def lock_pair(self, pair: str, until: datetime, reason: str = None, side: str = '*') -> None:
|
||||
"""
|
||||
Locks pair until a given timestamp happens.
|
||||
Locked pairs are not analyzed, and are prevented from opening new trades.
|
||||
|
@ -552,7 +552,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||
Needs to be timezone aware `datetime.now(timezone.utc)`
|
||||
:param reason: Optional string explaining why the pair was locked.
|
||||
"""
|
||||
PairLocks.lock_pair(pair, until, reason)
|
||||
PairLocks.lock_pair(pair, until, reason, side=side)
|
||||
|
||||
def unlock_pair(self, pair: str) -> None:
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user