Skip to content

Commit

Permalink
Abstract creating stoploss-orders from stoploss-logic
Browse files Browse the repository at this point in the history
  • Loading branch information
xmatthias committed Aug 31, 2019
1 parent a7e45c5 commit f0c0f56
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 36 deletions.
67 changes: 32 additions & 35 deletions freqtrade/freqtradebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,26 @@ def handle_trade(self, trade: Trade) -> bool:
logger.debug('Found no sell signal for %s.', trade)
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:
"""
Check if trade is fulfilled in which case the stoploss
Expand All @@ -638,9 +658,6 @@ def handle_stoploss_on_exchange(self, trade: Trade) -> bool:
# If trade open order id does not exist: buy order is fulfilled
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_fulfilled and not stoploss_order):
if self.edge:
Expand All @@ -650,34 +667,18 @@ def handle_stoploss_on_exchange(self, trade: Trade) -> bool:

stop_price = trade.open_rate * (1 + stoploss)

# limit price should be less than 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)
if self.create_stoploss_order(trade=trade, stop_price=stop_price, rate=stop_price):
trade.stoploss_last_update = datetime.now()
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 and stoploss_order['status'] == 'canceled':
try:
stoploss_order_id = self.exchange.stoploss_limit(
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)
if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss,
rate=trade.stop_loss):
return False
except DependencyException as exception:
else:
trade.stoploss_order_id = None
logger.warning('Stoploss order was cancelled, '
'but unable to recreate one: %s', exception)
logger.warning('Stoploss order was cancelled, but unable to recreate one.')

# We check if stoploss order is fulfilled
if stoploss_order and stoploss_order['status'] == 'closed':
Expand Down Expand Up @@ -720,17 +721,13 @@ def handle_trailing_stoploss_on_exchange(self, trade: Trade, order):
logger.exception(f"Could not cancel stoploss order {order['id']} "
f"for pair {trade.pair}")

try:
# creating the new one
stoploss_order_id = self.exchange.stoploss_limit(
pair=trade.pair, amount=trade.amount,
stop_price=trade.stop_loss, rate=trade.stop_loss * 0.99
)['id']
trade.stoploss_order_id = str(stoploss_order_id)
except DependencyException:
trade.stoploss_order_id = None
logger.exception(f"Could not create trailing stoploss order "
f"for pair {trade.pair}.")
# Create new stoploss order
if self.create_stoploss_order(trade=trade, stop_price=trade.stop_loss,
rate=trade.stop_loss):
return False
else:
logger.warning(f"Could not create trailing stoploss order "
f"for pair {trade.pair}.")

def _check_and_execute_sell(self, trade: Trade, sell_rate: float,
buy: bool, sell: bool) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion freqtrade/tests/test_freqtradebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
side_effect=DependencyException()
)
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

# Fifth case: get_order returns InvalidOrder
Expand Down

0 comments on commit f0c0f56

Please sign in to comment.