TratingTime periods protection
This commit is contained in:
parent
3c1380fbc6
commit
ffca4623e7
@ -1,4 +1,5 @@
|
||||
# pragma pylint: disable=too-few-public-methods
|
||||
# flake8: noqa: E501
|
||||
|
||||
"""
|
||||
bot constants
|
||||
@ -34,7 +35,7 @@ AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
|
||||
'AgeFilter', 'OffsetFilter', 'PerformanceFilter',
|
||||
'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter',
|
||||
'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter']
|
||||
AVAILABLE_PROTECTIONS = ['CooldownPeriod', 'LowProfitPairs', 'MaxDrawdown', 'StoplossGuard']
|
||||
AVAILABLE_PROTECTIONS = ['CooldownPeriod', 'LowProfitPairs', 'MaxDrawdown', 'StoplossGuard', 'TradingTime']
|
||||
AVAILABLE_DATAHANDLERS = ['json', 'jsongz', 'hdf5']
|
||||
BACKTEST_BREAKDOWNS = ['day', 'week', 'month']
|
||||
BACKTEST_CACHE_AGE = ['none', 'day', 'week', 'month']
|
||||
|
81
freqtrade/plugins/protections/trading_time.py
Normal file
81
freqtrade/plugins/protections/trading_time.py
Normal 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
|
Loading…
Reference in New Issue
Block a user