first updated proposition of handle_stoploss_on_exchange, add sl_orders helper
This commit is contained in:
+60
-40
@@ -1215,27 +1215,30 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
logger.debug('Handling stoploss on exchange %s ...', trade)
|
logger.debug('Handling stoploss on exchange %s ...', trade)
|
||||||
stoploss_order = None
|
|
||||||
|
|
||||||
try:
|
stoploss_orders = []
|
||||||
# First we check if there is already a stoploss on exchange
|
for slo in trade.sl_orders:
|
||||||
stoploss_order = self.exchange.fetch_stoploss_order(
|
stoploss_order = None
|
||||||
trade.stoploss_order_id, trade.pair) if trade.stoploss_order_id else None
|
try:
|
||||||
except InvalidOrderException as exception:
|
# First we check if there is already a stoploss on exchange
|
||||||
logger.warning('Unable to fetch stoploss order: %s', exception)
|
stoploss_order = self.exchange.fetch_stoploss_order(
|
||||||
|
slo.order_id, trade.pair) if slo.order_id else None
|
||||||
|
except InvalidOrderException as exception:
|
||||||
|
logger.warning('Unable to fetch stoploss order: %s', exception)
|
||||||
|
|
||||||
if stoploss_order:
|
if stoploss_order:
|
||||||
self.update_trade_state(trade, trade.stoploss_order_id, stoploss_order,
|
stoploss_orders.append(stoploss_order)
|
||||||
stoploss_order=True)
|
self.update_trade_state(trade, slo.order_id, stoploss_order,
|
||||||
|
stoploss_order=True)
|
||||||
|
|
||||||
# We check if stoploss order is fulfilled
|
# We check if stoploss order is fulfilled
|
||||||
if stoploss_order and stoploss_order['status'] in ('closed', 'triggered'):
|
if stoploss_order and stoploss_order['status'] in ('closed', 'triggered'):
|
||||||
trade.exit_reason = ExitType.STOPLOSS_ON_EXCHANGE.value
|
trade.exit_reason = ExitType.STOPLOSS_ON_EXCHANGE.value
|
||||||
self.update_trade_state(trade, trade.stoploss_order_id, stoploss_order,
|
self.update_trade_state(trade, slo.order_id, stoploss_order,
|
||||||
stoploss_order=True)
|
stoploss_order=True)
|
||||||
self._notify_exit(trade, "stoploss", True)
|
self._notify_exit(trade, "stoploss", True)
|
||||||
self.handle_protections(trade.pair, trade.trade_direction)
|
self.handle_protections(trade.pair, trade.trade_direction)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if trade.has_open_orders or not trade.is_open:
|
if trade.has_open_orders or not trade.is_open:
|
||||||
# Trade has an open Buy or Sell order, Stoploss-handling can't happen in this case
|
# Trade has an open Buy or Sell order, Stoploss-handling can't happen in this case
|
||||||
@@ -1244,7 +1247,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# If enter order is fulfilled but there is no stoploss, we add a stoploss on exchange
|
# If enter order is fulfilled but there is no stoploss, we add a stoploss on exchange
|
||||||
if not stoploss_order:
|
if len(stoploss_orders) == 0:
|
||||||
stop_price = trade.stoploss_or_liquidation
|
stop_price = trade.stoploss_or_liquidation
|
||||||
if self.edge:
|
if self.edge:
|
||||||
stoploss = self.edge.get_stoploss(pair=trade.pair)
|
stoploss = self.edge.get_stoploss(pair=trade.pair)
|
||||||
@@ -1258,27 +1261,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
# in which case the trade will be closed - which we must check below.
|
# in which case the trade will be closed - which we must check below.
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# If stoploss order is canceled for some reason we add it again
|
self.manage_trade_stoploss_orders(trade, stoploss_orders)
|
||||||
if (trade.is_open
|
|
||||||
and stoploss_order
|
|
||||||
and stoploss_order['status'] in ('canceled', 'cancelled')):
|
|
||||||
if self.create_stoploss_order(trade=trade, stop_price=trade.stoploss_or_liquidation):
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
logger.warning('Stoploss order was cancelled, but unable to recreate one.')
|
|
||||||
|
|
||||||
# Finally we check if stoploss on exchange should be moved up because of trailing.
|
|
||||||
# Triggered Orders are now real orders - so don't replace stoploss anymore
|
|
||||||
if (
|
|
||||||
trade.is_open and stoploss_order
|
|
||||||
and stoploss_order.get('status_stop') != 'triggered'
|
|
||||||
and (self.config.get('trailing_stop', False)
|
|
||||||
or self.config.get('use_custom_stoploss', False))
|
|
||||||
):
|
|
||||||
# if trailing stoploss is enabled we check if stoploss value has changed
|
|
||||||
# in which case we cancel stoploss order and put another one with new
|
|
||||||
# value immediately
|
|
||||||
self.handle_trailing_stoploss_on_exchange(trade, stoploss_order)
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -1314,6 +1297,43 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
logger.warning(f"Could not create trailing stoploss order "
|
logger.warning(f"Could not create trailing stoploss order "
|
||||||
f"for pair {trade.pair}.")
|
f"for pair {trade.pair}.")
|
||||||
|
|
||||||
|
def manage_trade_stoploss_orders(self, trade, stoploss_orders):
|
||||||
|
"""
|
||||||
|
Check to see if stoploss on exchange should be updated
|
||||||
|
in case of trailing stoploss on exchange
|
||||||
|
:param trade: Corresponding Trade
|
||||||
|
:param stoploss_orders: Current on exchange stoploss orders
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
# If all stoploss orderd are canceled for some reason we add it again
|
||||||
|
canceled_sl_orders = [o for o in stoploss_orders if o.status in ['canceled', 'cancelled']]
|
||||||
|
if (
|
||||||
|
trade.is_open and
|
||||||
|
len(stoploss_orders) > 0 and
|
||||||
|
len(stoploss_orders) == len(canceled_sl_orders)
|
||||||
|
):
|
||||||
|
if self.create_stoploss_order(trade=trade, stop_price=trade.stoploss_or_liquidation):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
logger.warning('All Stoploss orders are cancelled, but unable to recreate one.')
|
||||||
|
|
||||||
|
active_sl_orders = [o for o in stoploss_orders if o not in canceled_sl_orders]
|
||||||
|
if len(active_sl_orders) > 0:
|
||||||
|
last_active_sl_order = active_sl_orders[-1]
|
||||||
|
# Finally we check if stoploss on exchange should be moved up because of trailing.
|
||||||
|
# Triggered Orders are now real orders - so don't replace stoploss anymore
|
||||||
|
if (trade.is_open and
|
||||||
|
last_active_sl_order.get('status_stop') != 'triggered' and
|
||||||
|
(self.config.get('trailing_stop', False) or
|
||||||
|
self.config.get('use_custom_stoploss', False))):
|
||||||
|
# if trailing stoploss is enabled we check if stoploss value has changed
|
||||||
|
# in which case we cancel stoploss order and put another one with new
|
||||||
|
# value immediately
|
||||||
|
self.handle_trailing_stoploss_on_exchange(trade, last_active_sl_order)
|
||||||
|
|
||||||
|
# TODO cancel remaining_active_sl_orders active_sl_orders[:-1]
|
||||||
|
return
|
||||||
|
|
||||||
def manage_open_orders(self) -> None:
|
def manage_open_orders(self) -> None:
|
||||||
"""
|
"""
|
||||||
Management of open orders on exchange. Unfilled orders might be cancelled if timeout
|
Management of open orders on exchange. Unfilled orders might be cancelled if timeout
|
||||||
|
|||||||
@@ -544,6 +544,16 @@ class LocalTrade:
|
|||||||
]
|
]
|
||||||
return len(open_sl_orders) > 0
|
return len(open_sl_orders) > 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sl_orders(self) -> List[Order]:
|
||||||
|
"""
|
||||||
|
All stoploss orders for this trade
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
o for o in self.orders
|
||||||
|
if o.ft_order_side in ['stoploss']
|
||||||
|
]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def open_orders_ids(self) -> List[str]:
|
def open_orders_ids(self) -> List[str]:
|
||||||
open_orders_ids_wo_sl = [
|
open_orders_ids_wo_sl = [
|
||||||
|
|||||||
Reference in New Issue
Block a user