stable/freqtrade/plugins/protections/iprotection.py

68 lines
2.1 KiB
Python
Raw Normal View History

import logging
from abc import ABC, abstractmethod, abstractproperty
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, List, Optional, Tuple
2020-10-15 05:38:00 +00:00
from freqtrade.mixins import LoggingMixin
from freqtrade.persistence import Trade
2020-10-15 05:38:00 +00:00
logger = logging.getLogger(__name__)
2020-10-15 06:07:09 +00:00
ProtectionReturn = Tuple[bool, Optional[datetime], Optional[str]]
2020-10-15 05:38:00 +00:00
class IProtection(LoggingMixin, ABC):
# Can globally stop the bot
has_global_stop: bool = False
# Can stop trading for one pair
has_local_stop: bool = False
2020-10-14 05:40:44 +00:00
def __init__(self, config: Dict[str, Any], protection_config: Dict[str, Any]) -> None:
self._config = config
2020-10-14 05:40:44 +00:00
self._protection_config = protection_config
2020-10-15 05:38:00 +00:00
LoggingMixin.__init__(self, logger)
@property
def name(self) -> str:
return self.__class__.__name__
@abstractmethod
def short_desc(self) -> str:
"""
Short method description - used for startup-messages
-> Please overwrite in subclasses
"""
2020-10-14 05:40:44 +00:00
@abstractmethod
2020-10-15 06:07:09 +00:00
def global_stop(self, date_now: datetime) -> ProtectionReturn:
2020-10-14 05:40:44 +00:00
"""
Stops trading (position entering) for all pairs
This must evaluate to true for the whole period of the "cooldown period".
"""
2020-10-24 14:52:26 +00:00
@abstractmethod
def stop_per_pair(self, pair: str, date_now: datetime) -> 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>
"""
@staticmethod
def calculate_lock_end(trades: List[Trade], stop_minutes: int) -> datetime:
"""
Get lock end time
"""
max_date: datetime = max([trade.close_date for trade in trades])
# comming 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)
return until