Add duration_explanation functions
This commit is contained in:
parent
c993831a04
commit
0e2a43ab4d
@ -22,13 +22,13 @@ class CooldownPeriod(IProtection):
|
|||||||
"""
|
"""
|
||||||
LockReason to use
|
LockReason to use
|
||||||
"""
|
"""
|
||||||
return (f'Cooldown period for {self._stop_duration} min.')
|
return (f'Cooldown period for {self.stop_duration_str}.')
|
||||||
|
|
||||||
def short_desc(self) -> str:
|
def short_desc(self) -> str:
|
||||||
"""
|
"""
|
||||||
Short method description - used for startup-messages
|
Short method description - used for startup-messages
|
||||||
"""
|
"""
|
||||||
return (f"{self.name} - Cooldown period of {self._stop_duration} min.")
|
return (f"{self.name} - Cooldown period of {self.stop_duration_str}.")
|
||||||
|
|
||||||
def _cooldown_period(self, pair: str, date_now: datetime, ) -> ProtectionReturn:
|
def _cooldown_period(self, pair: str, date_now: datetime, ) -> ProtectionReturn:
|
||||||
"""
|
"""
|
||||||
@ -42,7 +42,7 @@ class CooldownPeriod(IProtection):
|
|||||||
]
|
]
|
||||||
trade = Trade.get_trades(filters).first()
|
trade = Trade.get_trades(filters).first()
|
||||||
if trade:
|
if trade:
|
||||||
self.log_once(f"Cooldown for {pair} for {self._stop_duration}.", logger.info)
|
self.log_once(f"Cooldown for {pair} for {self.stop_duration_str}.", logger.info)
|
||||||
until = self.calculate_lock_end([trade], self._stop_duration)
|
until = self.calculate_lock_end([trade], self._stop_duration)
|
||||||
|
|
||||||
return True, until, self._reason()
|
return True, until, self._reason()
|
||||||
|
@ -5,6 +5,7 @@ from datetime import datetime, timedelta, timezone
|
|||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from freqtrade.exchange import timeframe_to_minutes
|
from freqtrade.exchange import timeframe_to_minutes
|
||||||
|
from freqtrade.misc import plural
|
||||||
from freqtrade.mixins import LoggingMixin
|
from freqtrade.mixins import LoggingMixin
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
|
|
||||||
@ -26,12 +27,16 @@ class IProtection(LoggingMixin, ABC):
|
|||||||
self._protection_config = protection_config
|
self._protection_config = protection_config
|
||||||
tf_in_min = timeframe_to_minutes(config['timeframe'])
|
tf_in_min = timeframe_to_minutes(config['timeframe'])
|
||||||
if 'stop_duration_candles' in protection_config:
|
if 'stop_duration_candles' in protection_config:
|
||||||
self._stop_duration = (tf_in_min * protection_config.get('stop_duration_candles'))
|
self._stop_duration_candles = protection_config.get('stop_duration_candles', 1)
|
||||||
|
self._stop_duration = (tf_in_min * self._stop_duration_candles)
|
||||||
else:
|
else:
|
||||||
|
self._stop_duration_candles = None
|
||||||
self._stop_duration = protection_config.get('stop_duration', 60)
|
self._stop_duration = protection_config.get('stop_duration', 60)
|
||||||
if 'lookback_period_candles' in protection_config:
|
if 'lookback_period_candles' in protection_config:
|
||||||
self._lookback_period = tf_in_min * protection_config.get('lookback_period_candles', 60)
|
self._lookback_period_candles = protection_config.get('lookback_period_candles', 1)
|
||||||
|
self._lookback_period = tf_in_min * self._lookback_period_candles
|
||||||
else:
|
else:
|
||||||
|
self._lookback_period_candles = None
|
||||||
self._lookback_period = protection_config.get('lookback_period', 60)
|
self._lookback_period = protection_config.get('lookback_period', 60)
|
||||||
|
|
||||||
LoggingMixin.__init__(self, logger)
|
LoggingMixin.__init__(self, logger)
|
||||||
@ -40,6 +45,30 @@ class IProtection(LoggingMixin, ABC):
|
|||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stop_duration_str(self) -> str:
|
||||||
|
"""
|
||||||
|
Output configured stop duration in either candles or minutes
|
||||||
|
"""
|
||||||
|
if self._stop_duration_candles:
|
||||||
|
return (f"{self._stop_duration_candles} "
|
||||||
|
f"{plural(self._stop_duration_candles, 'candle', 'candles')}")
|
||||||
|
else:
|
||||||
|
return (f"{self._stop_duration} "
|
||||||
|
f"{plural(self._stop_duration, 'minute', 'minutes')}")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lookback_period_str(self) -> str:
|
||||||
|
"""
|
||||||
|
Output configured lookback period in either candles or minutes
|
||||||
|
"""
|
||||||
|
if self._lookback_period_candles:
|
||||||
|
return (f"{self._lookback_period_candles} "
|
||||||
|
f"{plural(self._lookback_period_candles, 'candle', 'candles')}")
|
||||||
|
else:
|
||||||
|
return (f"{self._lookback_period} "
|
||||||
|
f"{plural(self._lookback_period, 'minute', 'minutes')}")
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def short_desc(self) -> str:
|
def short_desc(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -26,14 +26,14 @@ class LowProfitPairs(IProtection):
|
|||||||
Short method description - used for startup-messages
|
Short method description - used for startup-messages
|
||||||
"""
|
"""
|
||||||
return (f"{self.name} - Low Profit Protection, locks pairs with "
|
return (f"{self.name} - Low Profit Protection, locks pairs with "
|
||||||
f"profit < {self._required_profit} within {self._lookback_period} minutes.")
|
f"profit < {self._required_profit} within {self.lookback_period_str}.")
|
||||||
|
|
||||||
def _reason(self, profit: float) -> str:
|
def _reason(self, profit: float) -> str:
|
||||||
"""
|
"""
|
||||||
LockReason to use
|
LockReason to use
|
||||||
"""
|
"""
|
||||||
return (f'{profit} < {self._required_profit} in {self._lookback_period} min, '
|
return (f'{profit} < {self._required_profit} in {self.lookback_period_str}, '
|
||||||
f'locking for {self._stop_duration} min.')
|
f'locking for {self.stop_duration_str}.')
|
||||||
|
|
||||||
def _low_profit(self, date_now: datetime, pair: str) -> ProtectionReturn:
|
def _low_profit(self, date_now: datetime, pair: str) -> ProtectionReturn:
|
||||||
"""
|
"""
|
||||||
|
@ -30,14 +30,14 @@ class MaxDrawdown(IProtection):
|
|||||||
Short method description - used for startup-messages
|
Short method description - used for startup-messages
|
||||||
"""
|
"""
|
||||||
return (f"{self.name} - Max drawdown protection, stop trading if drawdown is > "
|
return (f"{self.name} - Max drawdown protection, stop trading if drawdown is > "
|
||||||
f"{self._max_allowed_drawdown} within {self._lookback_period} minutes.")
|
f"{self._max_allowed_drawdown} within {self.lookback_period_str}.")
|
||||||
|
|
||||||
def _reason(self, drawdown: float) -> str:
|
def _reason(self, drawdown: float) -> str:
|
||||||
"""
|
"""
|
||||||
LockReason to use
|
LockReason to use
|
||||||
"""
|
"""
|
||||||
return (f'{drawdown} > {self._max_allowed_drawdown} in {self._lookback_period} min, '
|
return (f'{drawdown} > {self._max_allowed_drawdown} in {self.lookback_period_str}, '
|
||||||
f'locking for {self._stop_duration} min.')
|
f'locking for {self.stop_duration_str}.')
|
||||||
|
|
||||||
def _max_drawdown(self, date_now: datetime) -> ProtectionReturn:
|
def _max_drawdown(self, date_now: datetime) -> ProtectionReturn:
|
||||||
"""
|
"""
|
||||||
@ -62,7 +62,7 @@ class MaxDrawdown(IProtection):
|
|||||||
if drawdown > self._max_allowed_drawdown:
|
if drawdown > self._max_allowed_drawdown:
|
||||||
self.log_once(
|
self.log_once(
|
||||||
f"Trading stopped due to Max Drawdown {drawdown:.2f} < {self._max_allowed_drawdown}"
|
f"Trading stopped due to Max Drawdown {drawdown:.2f} < {self._max_allowed_drawdown}"
|
||||||
f" within {self._lookback_period} minutes.", logger.info)
|
f" within {self.lookback_period_str}.", logger.info)
|
||||||
until = self.calculate_lock_end(trades, self._stop_duration)
|
until = self.calculate_lock_end(trades, self._stop_duration)
|
||||||
|
|
||||||
return True, until, self._reason(drawdown)
|
return True, until, self._reason(drawdown)
|
||||||
|
@ -29,7 +29,7 @@ class StoplossGuard(IProtection):
|
|||||||
Short method description - used for startup-messages
|
Short method description - used for startup-messages
|
||||||
"""
|
"""
|
||||||
return (f"{self.name} - Frequent Stoploss Guard, {self._trade_limit} stoplosses "
|
return (f"{self.name} - Frequent Stoploss Guard, {self._trade_limit} stoplosses "
|
||||||
f"within {self._lookback_period} minutes.")
|
f"within {self.lookback_period_str}.")
|
||||||
|
|
||||||
def _reason(self) -> str:
|
def _reason(self) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -350,7 +350,7 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog):
|
|||||||
None
|
None
|
||||||
),
|
),
|
||||||
({"method": "CooldownPeriod", "stop_duration": 60},
|
({"method": "CooldownPeriod", "stop_duration": 60},
|
||||||
"[{'CooldownPeriod': 'CooldownPeriod - Cooldown period of 60 min.'}]",
|
"[{'CooldownPeriod': 'CooldownPeriod - Cooldown period of 60 minutes.'}]",
|
||||||
None
|
None
|
||||||
),
|
),
|
||||||
({"method": "LowProfitPairs", "lookback_period": 60, "stop_duration": 60},
|
({"method": "LowProfitPairs", "lookback_period": 60, "stop_duration": 60},
|
||||||
@ -363,6 +363,26 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog):
|
|||||||
"within 60 minutes.'}]",
|
"within 60 minutes.'}]",
|
||||||
None
|
None
|
||||||
),
|
),
|
||||||
|
({"method": "StoplossGuard", "lookback_period_candles": 12, "trade_limit": 2,
|
||||||
|
"stop_duration": 60},
|
||||||
|
"[{'StoplossGuard': 'StoplossGuard - Frequent Stoploss Guard, "
|
||||||
|
"2 stoplosses within 12 candles.'}]",
|
||||||
|
None
|
||||||
|
),
|
||||||
|
({"method": "CooldownPeriod", "stop_duration_candles": 5},
|
||||||
|
"[{'CooldownPeriod': 'CooldownPeriod - Cooldown period of 5 candles.'}]",
|
||||||
|
None
|
||||||
|
),
|
||||||
|
({"method": "LowProfitPairs", "lookback_period_candles": 11, "stop_duration": 60},
|
||||||
|
"[{'LowProfitPairs': 'LowProfitPairs - Low Profit Protection, locks pairs with "
|
||||||
|
"profit < 0.0 within 11 candles.'}]",
|
||||||
|
None
|
||||||
|
),
|
||||||
|
({"method": "MaxDrawdown", "lookback_period_candles": 20, "stop_duration": 60},
|
||||||
|
"[{'MaxDrawdown': 'MaxDrawdown - Max drawdown protection, stop trading if drawdown is > 0.0 "
|
||||||
|
"within 20 candles.'}]",
|
||||||
|
None
|
||||||
|
),
|
||||||
])
|
])
|
||||||
def test_protection_manager_desc(mocker, default_conf, protectionconf,
|
def test_protection_manager_desc(mocker, default_conf, protectionconf,
|
||||||
desc_expected, exception_expected):
|
desc_expected, exception_expected):
|
||||||
|
Loading…
Reference in New Issue
Block a user