Don't send double-notifications for stoploss fills

This commit is contained in:
Matthias 2021-04-19 21:32:04 +02:00
parent fecd5c582b
commit 8800a09770
3 changed files with 25 additions and 14 deletions

View File

@ -1361,7 +1361,8 @@ class FreqtradeBot(LoggingMixin):
# Updating wallets when order is closed # Updating wallets when order is closed
if not trade.is_open: if not trade.is_open:
self._notify_sell(trade, '', True) if not stoploss_order:
self._notify_sell(trade, '', True)
self.protections.stop_per_pair(trade.pair) self.protections.stop_per_pair(trade.pair)
self.protections.global_stop() self.protections.global_stop()
self.wallets.update() self.wallets.update()

View File

@ -683,7 +683,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
context.args = ["1"] context.args = ["1"]
telegram._forcesell(update=update, context=context) telegram._forcesell(update=update, context=context)
assert msg_mock.call_count == 3 assert msg_mock.call_count == 4
last_msg = msg_mock.call_args_list[-1][0][0] last_msg = msg_mock.call_args_list[-1][0][0]
assert { assert {
'type': RPCMessageType.SELL_NOTIFICATION, 'type': RPCMessageType.SELL_NOTIFICATION,
@ -703,6 +703,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
'sell_reason': SellType.FORCE_SELL.value, 'sell_reason': SellType.FORCE_SELL.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == last_msg } == last_msg
@ -743,7 +744,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
context.args = ["1"] context.args = ["1"]
telegram._forcesell(update=update, context=context) telegram._forcesell(update=update, context=context)
assert msg_mock.call_count == 3 assert msg_mock.call_count == 4
last_msg = msg_mock.call_args_list[-1][0][0] last_msg = msg_mock.call_args_list[-1][0][0]
assert { assert {
@ -764,6 +765,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
'sell_reason': SellType.FORCE_SELL.value, 'sell_reason': SellType.FORCE_SELL.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == last_msg } == last_msg
@ -794,9 +796,9 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
context.args = ["all"] context.args = ["all"]
telegram._forcesell(update=update, context=context) telegram._forcesell(update=update, context=context)
# Called for each trade 3 times # Called for each trade 4 times
assert msg_mock.call_count == 8 assert msg_mock.call_count == 12
msg = msg_mock.call_args_list[1][0][0] msg = msg_mock.call_args_list[2][0][0]
assert { assert {
'type': RPCMessageType.SELL_NOTIFICATION, 'type': RPCMessageType.SELL_NOTIFICATION,
'trade_id': 1, 'trade_id': 1,
@ -815,6 +817,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
'sell_reason': SellType.FORCE_SELL.value, 'sell_reason': SellType.FORCE_SELL.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == msg } == msg

View File

@ -1710,6 +1710,7 @@ def test_update_trade_state(mocker, default_conf, limit_buy_order, caplog) -> No
open_rate=0.01, open_rate=0.01,
open_date=arrow.utcnow().datetime, open_date=arrow.utcnow().datetime,
amount=11, amount=11,
exchange="binance",
) )
assert not freqtrade.update_trade_state(trade, None) assert not freqtrade.update_trade_state(trade, None)
assert log_has_re(r'Orderid for trade .* is empty.', caplog) assert log_has_re(r'Orderid for trade .* is empty.', caplog)
@ -2262,7 +2263,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old,
# check it does cancel sell orders over the time limit # check it does cancel sell orders over the time limit
freqtrade.check_handle_timedout() freqtrade.check_handle_timedout()
assert cancel_order_mock.call_count == 1 assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1 assert rpc_mock.call_count == 2
assert open_trade.is_open is True assert open_trade.is_open is True
# Custom user sell-timeout is never called # Custom user sell-timeout is never called
assert freqtrade.strategy.check_sell_timeout.call_count == 0 assert freqtrade.strategy.check_sell_timeout.call_count == 0
@ -2319,7 +2320,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
# note this is for a partially-complete buy order # note this is for a partially-complete buy order
freqtrade.check_handle_timedout() freqtrade.check_handle_timedout()
assert cancel_order_mock.call_count == 1 assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1 assert rpc_mock.call_count == 2
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1 assert len(trades) == 1
assert trades[0].amount == 23.0 assert trades[0].amount == 23.0
@ -2354,7 +2355,7 @@ def test_check_handle_timedout_partial_fee(default_conf, ticker, open_trade, cap
assert log_has_re(r"Applying fee on amount for Trade.*", caplog) assert log_has_re(r"Applying fee on amount for Trade.*", caplog)
assert cancel_order_mock.call_count == 1 assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1 assert rpc_mock.call_count == 2
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1 assert len(trades) == 1
# Verify that trade has been updated # Verify that trade has been updated
@ -2394,7 +2395,7 @@ def test_check_handle_timedout_partial_except(default_conf, ticker, open_trade,
assert log_has_re(r"Could not update trade amount: .*", caplog) assert log_has_re(r"Could not update trade amount: .*", caplog)
assert cancel_order_mock.call_count == 1 assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1 assert rpc_mock.call_count == 2
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1 assert len(trades) == 1
# Verify that trade has been updated # Verify that trade has been updated
@ -2639,6 +2640,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> N
'sell_reason': SellType.ROI.value, 'sell_reason': SellType.ROI.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == last_msg } == last_msg
@ -2689,6 +2691,7 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker)
'sell_reason': SellType.STOP_LOSS.value, 'sell_reason': SellType.STOP_LOSS.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == last_msg } == last_msg
@ -2746,7 +2749,7 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
'sell_reason': SellType.STOP_LOSS.value, 'sell_reason': SellType.STOP_LOSS.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == last_msg } == last_msg
@ -2830,7 +2833,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf, ticker, fee, ticke
trade = Trade.query.first() trade = Trade.query.first()
assert trade assert trade
assert cancel_order.call_count == 1 assert cancel_order.call_count == 1
assert rpc_mock.call_count == 2 assert rpc_mock.call_count == 3
def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, fee, def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, fee,
@ -2898,7 +2901,10 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf, ticker, f
assert trade.stoploss_order_id is None assert trade.stoploss_order_id is None
assert trade.is_open is False assert trade.is_open is False
assert trade.sell_reason == SellType.STOPLOSS_ON_EXCHANGE.value assert trade.sell_reason == SellType.STOPLOSS_ON_EXCHANGE.value
assert rpc_mock.call_count == 2 assert rpc_mock.call_count == 3
assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.BUY_NOTIFICATION
assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.BUY_FILL_NOTIFICATION
assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL_NOTIFICATION
def test_execute_sell_market_order(default_conf, ticker, fee, def test_execute_sell_market_order(default_conf, ticker, fee,
@ -2932,7 +2938,7 @@ def test_execute_sell_market_order(default_conf, ticker, fee,
assert not trade.is_open assert not trade.is_open
assert trade.close_profit == 0.0620716 assert trade.close_profit == 0.0620716
assert rpc_mock.call_count == 2 assert rpc_mock.call_count == 3
last_msg = rpc_mock.call_args_list[-1][0][0] last_msg = rpc_mock.call_args_list[-1][0][0]
assert { assert {
'type': RPCMessageType.SELL_NOTIFICATION, 'type': RPCMessageType.SELL_NOTIFICATION,
@ -2952,6 +2958,7 @@ def test_execute_sell_market_order(default_conf, ticker, fee,
'sell_reason': SellType.ROI.value, 'sell_reason': SellType.ROI.value,
'open_date': ANY, 'open_date': ANY,
'close_date': ANY, 'close_date': ANY,
'close_rate': ANY,
} == last_msg } == last_msg