use update_trade_state also for closed stoploss orders
This commit is contained in:
parent
0c3bdd66ac
commit
60f26ba501
@ -752,7 +752,7 @@ class FreqtradeBot:
|
|||||||
# 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':
|
||||||
trade.sell_reason = SellType.STOPLOSS_ON_EXCHANGE.value
|
trade.sell_reason = SellType.STOPLOSS_ON_EXCHANGE.value
|
||||||
trade.update(stoploss_order)
|
self.update_trade_state(trade, stoploss_order, sl_order=True)
|
||||||
# Lock pair for one candle to prevent immediate rebuys
|
# Lock pair for one candle to prevent immediate rebuys
|
||||||
self.strategy.lock_pair(trade.pair,
|
self.strategy.lock_pair(trade.pair,
|
||||||
timeframe_to_next_date(self.config['ticker_interval']))
|
timeframe_to_next_date(self.config['ticker_interval']))
|
||||||
@ -1123,7 +1123,7 @@ class FreqtradeBot:
|
|||||||
#
|
#
|
||||||
|
|
||||||
def update_trade_state(self, trade: Trade, action_order: dict = None,
|
def update_trade_state(self, trade: Trade, action_order: dict = None,
|
||||||
order_amount: float = None) -> bool:
|
order_amount: float = None, sl_order: bool = False) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks trades with open orders and updates the amount if necessary
|
Checks trades with open orders and updates the amount if necessary
|
||||||
Handles closing both buy and sell orders.
|
Handles closing both buy and sell orders.
|
||||||
@ -1131,34 +1131,37 @@ class FreqtradeBot:
|
|||||||
"""
|
"""
|
||||||
# Get order details for actual price per unit
|
# Get order details for actual price per unit
|
||||||
if trade.open_order_id:
|
if trade.open_order_id:
|
||||||
# Update trade with order values
|
order_id = trade.open_order_id
|
||||||
logger.info('Found open order for %s', trade)
|
elif trade.stoploss_order_id and sl_order:
|
||||||
try:
|
order_id = trade.stoploss_order_id
|
||||||
order = action_order or self.exchange.get_order(trade.open_order_id, trade.pair)
|
else:
|
||||||
except InvalidOrderException as exception:
|
return False
|
||||||
logger.warning('Unable to fetch order %s: %s', trade.open_order_id, exception)
|
# Update trade with order values
|
||||||
return False
|
logger.info('Found open order for %s', trade)
|
||||||
# Try update amount (binance-fix)
|
try:
|
||||||
try:
|
order = action_order or self.exchange.get_order(order_id, trade.pair)
|
||||||
new_amount = self.get_real_amount(trade, order, order_amount)
|
except InvalidOrderException as exception:
|
||||||
if not isclose(order['amount'], new_amount, abs_tol=constants.MATH_CLOSE_PREC):
|
logger.warning('Unable to fetch order %s: %s', order_id, exception)
|
||||||
order['amount'] = new_amount
|
return False
|
||||||
order.pop('filled', None)
|
# Try update amount (binance-fix)
|
||||||
trade.recalc_open_trade_price()
|
try:
|
||||||
except DependencyException as exception:
|
new_amount = self.get_real_amount(trade, order, order_amount)
|
||||||
logger.warning("Could not update trade amount: %s", exception)
|
if not isclose(order['amount'], new_amount, abs_tol=constants.MATH_CLOSE_PREC):
|
||||||
|
order['amount'] = new_amount
|
||||||
|
order.pop('filled', None)
|
||||||
|
trade.recalc_open_trade_price()
|
||||||
|
except DependencyException as exception:
|
||||||
|
logger.warning("Could not update trade amount: %s", exception)
|
||||||
|
|
||||||
if self.exchange.check_order_canceled_empty(order):
|
if self.exchange.check_order_canceled_empty(order):
|
||||||
# Trade has been cancelled on exchange
|
# Trade has been cancelled on exchange
|
||||||
# Handling of this will happen in check_handle_timeout.
|
# Handling of this will happen in check_handle_timeout.
|
||||||
return True
|
return True
|
||||||
trade.update(order)
|
trade.update(order)
|
||||||
|
|
||||||
# Updating wallets when order is closed
|
# Updating wallets when order is closed
|
||||||
if not trade.is_open:
|
if not trade.is_open:
|
||||||
self.wallets.update()
|
self.wallets.update()
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def apply_fee_conditional(self, trade: Trade, trade_base_currency: str,
|
def apply_fee_conditional(self, trade: Trade, trade_base_currency: str,
|
||||||
amount: float, fee_abs: float) -> float:
|
amount: float, fee_abs: float) -> float:
|
||||||
|
@ -1140,7 +1140,8 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog,
|
|||||||
'status': 'closed',
|
'status': 'closed',
|
||||||
'type': 'stop_loss_limit',
|
'type': 'stop_loss_limit',
|
||||||
'price': 3,
|
'price': 3,
|
||||||
'average': 2
|
'average': 2,
|
||||||
|
'amount': limit_buy_order['amount'],
|
||||||
})
|
})
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_order_hit)
|
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_order_hit)
|
||||||
assert freqtrade.handle_stoploss_on_exchange(trade) is True
|
assert freqtrade.handle_stoploss_on_exchange(trade) is True
|
||||||
|
@ -44,6 +44,8 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
|
|||||||
}
|
}
|
||||||
stoploss_order_closed = stoploss_order_open.copy()
|
stoploss_order_closed = stoploss_order_open.copy()
|
||||||
stoploss_order_closed['status'] = 'closed'
|
stoploss_order_closed['status'] = 'closed'
|
||||||
|
stoploss_order_closed['filled'] = stoploss_order_closed['amount']
|
||||||
|
|
||||||
# Sell first trade based on stoploss, keep 2nd and 3rd trade open
|
# Sell first trade based on stoploss, keep 2nd and 3rd trade open
|
||||||
stoploss_order_mock = MagicMock(
|
stoploss_order_mock = MagicMock(
|
||||||
side_effect=[stoploss_order_closed, stoploss_order_open, stoploss_order_open])
|
side_effect=[stoploss_order_closed, stoploss_order_open, stoploss_order_open])
|
||||||
@ -98,7 +100,7 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
|
|||||||
assert cancel_order_mock.call_count == 1
|
assert cancel_order_mock.call_count == 1
|
||||||
# Wallets must be updated between stoploss cancellation and selling, and will be updated again
|
# Wallets must be updated between stoploss cancellation and selling, and will be updated again
|
||||||
# during update_trade_state
|
# during update_trade_state
|
||||||
assert wallets_mock.call_count == 3
|
assert wallets_mock.call_count == 4
|
||||||
|
|
||||||
trade = trades[0]
|
trade = trades[0]
|
||||||
assert trade.sell_reason == SellType.STOPLOSS_ON_EXCHANGE.value
|
assert trade.sell_reason == SellType.STOPLOSS_ON_EXCHANGE.value
|
||||||
|
Loading…
Reference in New Issue
Block a user