Abstract creating stoploss-orders from stoploss-logic

This commit is contained in:
Matthias 2019-08-31 16:11:04 +02:00
parent a7e45c5a73
commit f0c0f5618b
2 changed files with 33 additions and 36 deletions

View File

@ -617,6 +617,26 @@ class FreqtradeBot(object):
logger.debug('Found no sell signal for %s.', trade) logger.debug('Found no sell signal for %s.', trade)
return False return False
def create_stoploss_order(self, trade: Trade, stop_price: float, rate: float) -> bool:
"""
Abstracts creating stoploss orders from the logic.
Handles errors and updates the trade database object.
:return: True if the order succeeded, and False in case of problems.
"""
# Limit price threshold: As limit price should always be below price
LIMIT_PRICE_PCT = 0.99
try:
stoploss_order = self.exchange.stoploss_limit(pair=trade.pair, amount=trade.amount,
stop_price=stop_price,
rate=rate * LIMIT_PRICE_PCT)
trade.stoploss_order_id = str(stoploss_order['id'])
return True
except DependencyException:
trade.stoploss_order_id = None
logger.exception('Unable to place a stoploss order on exchange.')
return False
def handle_stoploss_on_exchange(self, trade: Trade) -> bool: def handle_stoploss_on_exchange(self, trade: Trade) -> bool:
""" """
Check if trade is fulfilled in which case the stoploss Check if trade is fulfilled in which case the stoploss
@ -638,9 +658,6 @@ class FreqtradeBot(object):
# If trade open order id does not exist: buy order is fulfilled # If trade open order id does not exist: buy order is fulfilled
buy_order_fulfilled = not trade.open_order_id buy_order_fulfilled = not trade.open_order_id
# Limit price threshold: As limit price should always be below price
limit_price_pct = 0.99
# If buy order is fulfilled but there is no stoploss, we add a stoploss on exchange # If buy order is fulfilled but there is no stoploss, we add a stoploss on exchange
if (buy_order_fulfilled and not stoploss_order): if (buy_order_fulfilled and not stoploss_order):
if self.edge: if self.edge:
@ -650,34 +667,18 @@ class FreqtradeBot(object):
stop_price = trade.open_rate * (1 + stoploss) stop_price = trade.open_rate * (1 + stoploss)
# limit price should be less than stop price. if self.create_stoploss_order(trade=trade, stop_price=stop_price, rate=stop_price):
limit_price = stop_price * limit_price_pct
try:
stoploss_order_id = self.exchange.stoploss_limit(
pair=trade.pair, amount=trade.amount, stop_price=stop_price, rate=limit_price
)['id']
trade.stoploss_order_id = str(stoploss_order_id)
trade.stoploss_last_update = datetime.now() trade.stoploss_last_update = datetime.now()
return False return False
except DependencyException as exception:
trade.stoploss_order_id = None
logger.warning('Unable to place a stoploss order on exchange: %s', exception)
# If stoploss order is canceled for some reason we add it # If stoploss order is canceled for some reason we add it
if stoploss_order and stoploss_order['status'] == 'canceled': if stoploss_order and stoploss_order['status'] == 'canceled':
try: if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss,
stoploss_order_id = self.exchange.stoploss_limit( rate=trade.stop_loss):
pair=trade.pair, amount=trade.amount,
stop_price=trade.stop_loss, rate=trade.stop_loss * limit_price_pct
)['id']
trade.stoploss_order_id = str(stoploss_order_id)
return False return False
except DependencyException as exception: else:
trade.stoploss_order_id = None trade.stoploss_order_id = None
logger.warning('Stoploss order was cancelled, ' logger.warning('Stoploss order was cancelled, but unable to recreate one.')
'but unable to recreate one: %s', exception)
# We check if stoploss order is fulfilled # We check if stoploss order is fulfilled
if stoploss_order and stoploss_order['status'] == 'closed': if stoploss_order and stoploss_order['status'] == 'closed':
@ -720,17 +721,13 @@ class FreqtradeBot(object):
logger.exception(f"Could not cancel stoploss order {order['id']} " logger.exception(f"Could not cancel stoploss order {order['id']} "
f"for pair {trade.pair}") f"for pair {trade.pair}")
try: # Create new stoploss order
# creating the new one if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss,
stoploss_order_id = self.exchange.stoploss_limit( rate=trade.stop_loss):
pair=trade.pair, amount=trade.amount, return False
stop_price=trade.stop_loss, rate=trade.stop_loss * 0.99 else:
)['id'] logger.warning(f"Could not create trailing stoploss order "
trade.stoploss_order_id = str(stoploss_order_id) f"for pair {trade.pair}.")
except DependencyException:
trade.stoploss_order_id = None
logger.exception(f"Could not create trailing stoploss order "
f"for pair {trade.pair}.")
def _check_and_execute_sell(self, trade: Trade, sell_rate: float, def _check_and_execute_sell(self, trade: Trade, sell_rate: float,
buy: bool, sell: bool) -> bool: buy: bool, sell: bool) -> bool:

View File

@ -1153,7 +1153,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
side_effect=DependencyException() side_effect=DependencyException()
) )
freqtrade.handle_stoploss_on_exchange(trade) freqtrade.handle_stoploss_on_exchange(trade)
assert log_has('Unable to place a stoploss order on exchange: ', caplog) assert log_has('Unable to place a stoploss order on exchange.', caplog)
assert trade.stoploss_order_id is None assert trade.stoploss_order_id is None
# Fifth case: get_order returns InvalidOrder # Fifth case: get_order returns InvalidOrder