TratingTime periods protection

This commit is contained in:
farmage 2022-07-04 10:18:45 +03:00
parent 3c1380fbc6
commit ffca4623e7
2 changed files with 83 additions and 1 deletions

View File

@ -1,4 +1,5 @@
# pragma pylint: disable=too-few-public-methods # pragma pylint: disable=too-few-public-methods
# flake8: noqa: E501
""" """
bot constants bot constants
@ -34,7 +35,7 @@ AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
'AgeFilter', 'OffsetFilter', 'PerformanceFilter', 'AgeFilter', 'OffsetFilter', 'PerformanceFilter',
'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter', 'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter',
'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter'] 'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter']
AVAILABLE_PROTECTIONS = ['CooldownPeriod', 'LowProfitPairs', 'MaxDrawdown', 'StoplossGuard'] AVAILABLE_PROTECTIONS = ['CooldownPeriod', 'LowProfitPairs', 'MaxDrawdown', 'StoplossGuard', 'TradingTime']
AVAILABLE_DATAHANDLERS = ['json', 'jsongz', 'hdf5'] AVAILABLE_DATAHANDLERS = ['json', 'jsongz', 'hdf5']
BACKTEST_BREAKDOWNS = ['day', 'week', 'month'] BACKTEST_BREAKDOWNS = ['day', 'week', 'month']
BACKTEST_CACHE_AGE = ['none', 'day', 'week', 'month'] BACKTEST_CACHE_AGE = ['none', 'day', 'week', 'month']

View File

@ -0,0 +1,81 @@
# flake8: noqa: E501
import logging
from datetime import datetime, timedelta
from typing import Any, Dict, Optional
from freqtrade.constants import LongShort
from freqtrade.plugins.protections import IProtection, ProtectionReturn
logger = logging.getLogger(__name__)
class TradingTime(IProtection):
has_global_stop: bool = True
has_local_stop: bool = False
def __init__(self, config: Dict[str, Any], protection_config: Dict[str, Any]) -> None:
super().__init__(config, protection_config)
self._start_time = datetime.strptime(protection_config.get('start_time', '00:00'), "%H:%M")
self._end_time = datetime.strptime(protection_config.get('end_time', '23:59'), "%H:%M")
self._update_trading_period()
def _update_trading_period(self) -> None:
now = datetime.now()
self.trade_start, self.trade_end = (
now.replace(hour=self._start_time.hour, minute=self._start_time.minute, second=0),
now.replace(hour=self._end_time.hour, minute=self._end_time.minute, second=0)
)
self.next_trading_day = self.trade_start + timedelta(days=1)
def short_desc(self) -> str:
"""
Short method description - used for startup-messages
"""
return (f"{self.name} - Limit trading to time period")
def _reason(self) -> str:
"""
LockReason to use
"""
return (f'Current time is not in Allowed time period {self.trade_start}-{self.trade_end}'
f'trading locked until {self.next_trading_day}.')
def _allowed_trading_period(self, date_now: datetime) -> Optional[ProtectionReturn]:
"""
Evaluate recent trades for drawdown ...
"""
self._update_trading_period()
now = datetime.now()
if not (self.trade_start < now < self.trade_end):
return ProtectionReturn(
lock=True,
until=self.next_trading_day,
reason=self._reason()
)
return None
def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]:
"""
Stops trading (position entering) for all pairs
This must evaluate to true for the whole period of the "cooldown period".
:return: Tuple of [bool, until, reason].
If true, all pairs will be locked with <reason> until <until>
"""
return self._allowed_trading_period(date_now)
def stop_per_pair(
self, pair: str, date_now: datetime, side: LongShort) -> Optional[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 None