Extract timeout handling from freqtradebot class

This commit is contained in:
Matthias 2022-01-22 15:59:10 +01:00
parent a35b0b519a
commit 7bef9a9b3e
2 changed files with 28 additions and 26 deletions

View File

@ -9,8 +9,6 @@ from math import isclose
from threading import Lock from threading import Lock
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
import arrow
from freqtrade import __version__, constants from freqtrade import __version__, constants
from freqtrade.configuration import validate_config_consistency from freqtrade.configuration import validate_config_consistency
from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.converter import order_book_to_dataframe
@ -959,20 +957,6 @@ class FreqtradeBot(LoggingMixin):
return True return True
return False return False
def _check_timed_out(self, side: str, order: dict) -> bool:
"""
Check if timeout is active, and if the order is still open and timed out
"""
timeout = self.config.get('unfilledtimeout', {}).get(side)
ordertime = arrow.get(order['datetime']).datetime
if timeout is not None:
timeout_unit = self.config.get('unfilledtimeout', {}).get('unit', 'minutes')
timeout_kwargs = {timeout_unit: -timeout}
timeout_threshold = arrow.utcnow().shift(**timeout_kwargs).datetime
return (order['status'] == 'open' and order['side'] == side
and ordertime < timeout_threshold)
return False
def check_handle_timedout(self) -> None: def check_handle_timedout(self) -> None:
""" """
Check if any orders are timed out and cancel if necessary Check if any orders are timed out and cancel if necessary
@ -993,20 +977,16 @@ class FreqtradeBot(LoggingMixin):
if (order['side'] == 'buy' and (order['status'] == 'open' or fully_cancelled) and ( if (order['side'] == 'buy' and (order['status'] == 'open' or fully_cancelled) and (
fully_cancelled fully_cancelled
or self._check_timed_out('buy', order) or self.strategy.ft_check_timed_out(
or strategy_safe_wrapper(self.strategy.check_buy_timeout, 'buy', trade, order, datetime.now(timezone.utc))
default_retval=False)(pair=trade.pair, )):
trade=trade,
order=order))):
self.handle_cancel_enter(trade, order, constants.CANCEL_REASON['TIMEOUT']) self.handle_cancel_enter(trade, order, constants.CANCEL_REASON['TIMEOUT'])
elif (order['side'] == 'sell' and (order['status'] == 'open' or fully_cancelled) and ( elif (order['side'] == 'sell' and (order['status'] == 'open' or fully_cancelled) and (
fully_cancelled fully_cancelled
or self._check_timed_out('sell', order) or self.strategy.ft_check_timed_out(
or strategy_safe_wrapper(self.strategy.check_sell_timeout, 'sell', trade, order, datetime.now(timezone.utc)))
default_retval=False)(pair=trade.pair, ):
trade=trade,
order=order))):
self.handle_cancel_exit(trade, order, constants.CANCEL_REASON['TIMEOUT']) self.handle_cancel_exit(trade, order, constants.CANCEL_REASON['TIMEOUT'])
canceled_count = trade.get_exit_order_count() canceled_count = trade.get_exit_order_count()
max_timeouts = self.config.get('unfilledtimeout', {}).get('exit_timeout_count', 0) max_timeouts = self.config.get('unfilledtimeout', {}).get('exit_timeout_count', 0)

View File

@ -852,6 +852,28 @@ class IStrategy(ABC, HyperStrategyMixin):
else: else:
return current_profit > roi return current_profit > roi
def ft_check_timed_out(self, side: str, trade: Trade, order: Dict,
current_time: datetime) -> bool:
"""
FT Internal method.
Check if timeout is active, and if the order is still open and timed out
"""
timeout = self.config.get('unfilledtimeout', {}).get(side)
ordertime = arrow.get(order['datetime']).datetime
if timeout is not None:
timeout_unit = self.config.get('unfilledtimeout', {}).get('unit', 'minutes')
timeout_kwargs = {timeout_unit: -timeout}
timeout_threshold = current_time + timedelta(**timeout_kwargs)
timedout = (order['status'] == 'open' and order['side'] == side
and ordertime < timeout_threshold)
if timedout:
return True
time_method = 'check_sell_timeout' if order['side'] == 'sell' else 'check_buy_timeout'
return strategy_safe_wrapper(getattr(self, time_method),
default_retval=False)(
pair=trade.pair, trade=trade, order=order)
def advise_all_indicators(self, data: Dict[str, DataFrame]) -> Dict[str, DataFrame]: def advise_all_indicators(self, data: Dict[str, DataFrame]) -> Dict[str, DataFrame]:
""" """
Populates indicators for given candle (OHLCV) data (for multiple pairs) Populates indicators for given candle (OHLCV) data (for multiple pairs)