Use Order object for ft_timeout check
This commit is contained in:
parent
1e603985c5
commit
4ea79a32e4
@ -987,18 +987,20 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
|
|
||||||
fully_cancelled = self.update_trade_state(trade, trade.open_order_id, order)
|
fully_cancelled = self.update_trade_state(trade, trade.open_order_id, order)
|
||||||
|
|
||||||
|
order_obj = trade.select_order_by_order_id(trade.open_order_id)
|
||||||
|
|
||||||
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.strategy.ft_check_timed_out(
|
or (order_obj and self.strategy.ft_check_timed_out(
|
||||||
'buy', trade, order, datetime.now(timezone.utc))
|
'buy', trade, order_obj, datetime.now(timezone.utc))
|
||||||
)):
|
))):
|
||||||
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.strategy.ft_check_timed_out(
|
or (order_obj and self.strategy.ft_check_timed_out(
|
||||||
'sell', trade, order, datetime.now(timezone.utc)))
|
'sell', trade, order_obj, datetime.now(timezone.utc))
|
||||||
):
|
))):
|
||||||
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)
|
||||||
|
@ -593,7 +593,7 @@ class Backtesting:
|
|||||||
if pos_adjust and self._get_order_filled(order.price, row):
|
if pos_adjust and self._get_order_filled(order.price, row):
|
||||||
order.close_bt_order(current_time)
|
order.close_bt_order(current_time)
|
||||||
else:
|
else:
|
||||||
trade.open_order_id = self.order_id_counter
|
trade.open_order_id = str(self.order_id_counter)
|
||||||
trade.orders.append(order)
|
trade.orders.append(order)
|
||||||
trade.recalc_trade_from_orders()
|
trade.recalc_trade_from_orders()
|
||||||
|
|
||||||
@ -642,7 +642,7 @@ class Backtesting:
|
|||||||
"""
|
"""
|
||||||
for order in [o for o in trade.orders if o.ft_is_open]:
|
for order in [o for o in trade.orders if o.ft_is_open]:
|
||||||
|
|
||||||
timedout = self.strategy.ft_check_timed_out(order.side, trade, {}, current_time)
|
timedout = self.strategy.ft_check_timed_out(order.side, trade, order, current_time)
|
||||||
if timedout:
|
if timedout:
|
||||||
if order.side == 'buy':
|
if order.side == 'buy':
|
||||||
if trade.nr_of_successful_buys == 0:
|
if trade.nr_of_successful_buys == 0:
|
||||||
|
@ -132,6 +132,10 @@ class Order(_DECL_BASE):
|
|||||||
order_filled_date = Column(DateTime, nullable=True)
|
order_filled_date = Column(DateTime, nullable=True)
|
||||||
order_update_date = Column(DateTime, nullable=True)
|
order_update_date = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def order_date_utc(self):
|
||||||
|
return self.order_date.replace(tzinfo=timezone.utc)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
||||||
return (f'Order(id={self.id}, order_id={self.order_id}, trade_id={self.ft_trade_id}, '
|
return (f'Order(id={self.id}, order_id={self.order_id}, trade_id={self.ft_trade_id}, '
|
||||||
@ -641,6 +645,16 @@ class LocalTrade():
|
|||||||
if self.stop_loss_pct is not None and self.open_rate is not None:
|
if self.stop_loss_pct is not None and self.open_rate is not None:
|
||||||
self.adjust_stop_loss(self.open_rate, self.stop_loss_pct)
|
self.adjust_stop_loss(self.open_rate, self.stop_loss_pct)
|
||||||
|
|
||||||
|
def select_order_by_order_id(self, order_id: str) -> Optional[Order]:
|
||||||
|
"""
|
||||||
|
Finds order object by Order id.
|
||||||
|
:param order_id: Exchange order id
|
||||||
|
"""
|
||||||
|
orders = [o for o in self.orders if o.order_id == order_id]
|
||||||
|
if orders:
|
||||||
|
return orders[0]
|
||||||
|
return None
|
||||||
|
|
||||||
def select_order(
|
def select_order(
|
||||||
self, order_side: str = None, is_open: Optional[bool] = None) -> Optional[Order]:
|
self, order_side: str = None, is_open: Optional[bool] = None) -> Optional[Order]:
|
||||||
"""
|
"""
|
||||||
|
@ -18,6 +18,7 @@ from freqtrade.exceptions import OperationalException, StrategyError
|
|||||||
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
|
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
|
||||||
from freqtrade.exchange.exchange import timeframe_to_next_date
|
from freqtrade.exchange.exchange import timeframe_to_next_date
|
||||||
from freqtrade.persistence import PairLocks, Trade
|
from freqtrade.persistence import PairLocks, Trade
|
||||||
|
from freqtrade.persistence.models import LocalTrade, Order
|
||||||
from freqtrade.strategy.hyper import HyperStrategyMixin
|
from freqtrade.strategy.hyper import HyperStrategyMixin
|
||||||
from freqtrade.strategy.informative_decorator import (InformativeData, PopulateIndicators,
|
from freqtrade.strategy.informative_decorator import (InformativeData, PopulateIndicators,
|
||||||
_create_and_merge_informative_pair,
|
_create_and_merge_informative_pair,
|
||||||
@ -862,23 +863,22 @@ 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,
|
def ft_check_timed_out(self, side: str, trade: LocalTrade, order: Order,
|
||||||
current_time: datetime) -> bool:
|
current_time: datetime) -> bool:
|
||||||
"""
|
"""
|
||||||
FT Internal method.
|
FT Internal method.
|
||||||
Check if timeout is active, and if the order is still open and timed out
|
Check if timeout is active, and if the order is still open and timed out
|
||||||
"""
|
"""
|
||||||
timeout = self.config.get('unfilledtimeout', {}).get(side)
|
timeout = self.config.get('unfilledtimeout', {}).get(side)
|
||||||
ordertime = arrow.get(order['datetime']).datetime
|
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
timeout_unit = self.config.get('unfilledtimeout', {}).get('unit', 'minutes')
|
timeout_unit = self.config.get('unfilledtimeout', {}).get('unit', 'minutes')
|
||||||
timeout_kwargs = {timeout_unit: -timeout}
|
timeout_kwargs = {timeout_unit: -timeout}
|
||||||
timeout_threshold = current_time + timedelta(**timeout_kwargs)
|
timeout_threshold = current_time + timedelta(**timeout_kwargs)
|
||||||
timedout = (order['status'] == 'open' and order['side'] == side
|
timedout = (order.status == 'open' and order.side == side
|
||||||
and ordertime < timeout_threshold)
|
and order.order_date_utc < timeout_threshold)
|
||||||
if timedout:
|
if timedout:
|
||||||
return True
|
return True
|
||||||
time_method = self.check_sell_timeout if order['side'] == 'sell' else self.check_buy_timeout
|
time_method = self.check_sell_timeout if order.side == 'sell' else self.check_buy_timeout
|
||||||
|
|
||||||
return strategy_safe_wrapper(time_method,
|
return strategy_safe_wrapper(time_method,
|
||||||
default_retval=False)(
|
default_retval=False)(
|
||||||
|
Loading…
Reference in New Issue
Block a user