fix more freqtradebot tests, update params of handle_cancel_enter, handle_cancel_exit
This commit is contained in:
@@ -1076,7 +1076,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
trades_closed = 0
|
trades_closed = 0
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
|
|
||||||
if trade.open_order_id is None and not self.wallets.check_exit_amount(trade):
|
if trade.open_orders_count == 0 and not self.wallets.check_exit_amount(trade):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f'Not enough {trade.safe_base_currency} in wallet to exit {trade}. '
|
f'Not enough {trade.safe_base_currency} in wallet to exit {trade}. '
|
||||||
'Trying to recover.')
|
'Trying to recover.')
|
||||||
@@ -1094,7 +1094,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
f'Unable to handle stoploss on exchange for {trade.pair}: {exception}')
|
f'Unable to handle stoploss on exchange for {trade.pair}: {exception}')
|
||||||
# Check if we can sell our current pair
|
# Check if we can sell our current pair
|
||||||
if trade.open_order_id is None and trade.is_open and self.handle_trade(trade):
|
if trade.open_orders_count == 0 and trade.is_open and self.handle_trade(trade):
|
||||||
trades_closed += 1
|
trades_closed += 1
|
||||||
|
|
||||||
except DependencyException as exception:
|
except DependencyException as exception:
|
||||||
@@ -1236,7 +1236,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
self.handle_protections(trade.pair, trade.trade_direction)
|
self.handle_protections(trade.pair, trade.trade_direction)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if trade.open_order_id or not trade.is_open:
|
if trade.open_orders_count != 0 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
|
||||||
# as the Amount on the exchange is tied up in another trade.
|
# as the Amount on the exchange is tied up in another trade.
|
||||||
# The trade can be closed already (sell-order fill confirmation came in this iteration)
|
# The trade can be closed already (sell-order fill confirmation came in this iteration)
|
||||||
|
|||||||
+1
-1
@@ -2629,7 +2629,7 @@ def open_trade_usdt():
|
|||||||
pair='ADA/USDT',
|
pair='ADA/USDT',
|
||||||
open_rate=2.0,
|
open_rate=2.0,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
open_order_id='123456789_exit',
|
# open_order_id='123456789_exit',
|
||||||
amount=30.0,
|
amount=30.0,
|
||||||
fee_open=0.0,
|
fee_open=0.0,
|
||||||
fee_close=0.0,
|
fee_close=0.0,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ def mock_trade_usdt_1(fee, is_short: bool):
|
|||||||
close_profit_abs=-4.09,
|
close_profit_abs=-4.09,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
strategy='SampleStrategy',
|
strategy='SampleStrategy',
|
||||||
open_order_id=f'prod_exit_1_{direc(is_short)}',
|
# open_order_id=f'prod_exit_1_{direc(is_short)}',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
is_short=is_short,
|
is_short=is_short,
|
||||||
)
|
)
|
||||||
@@ -123,7 +123,7 @@ def mock_trade_usdt_2(fee, is_short: bool):
|
|||||||
close_profit_abs=3.9875,
|
close_profit_abs=3.9875,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
is_open=False,
|
is_open=False,
|
||||||
open_order_id=f'12366_{direc(is_short)}',
|
# open_order_id=f'12366_{direc(is_short)}',
|
||||||
strategy='StrategyTestV2',
|
strategy='StrategyTestV2',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
enter_tag='TEST1',
|
enter_tag='TEST1',
|
||||||
@@ -231,7 +231,7 @@ def mock_trade_usdt_4(fee, is_short: bool):
|
|||||||
is_open=True,
|
is_open=True,
|
||||||
open_rate=2.0,
|
open_rate=2.0,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
open_order_id=f'prod_buy_12345_{direc(is_short)}',
|
# open_order_id=f'prod_buy_12345_{direc(is_short)}',
|
||||||
strategy='StrategyTestV2',
|
strategy='StrategyTestV2',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
is_short=is_short,
|
is_short=is_short,
|
||||||
@@ -340,7 +340,7 @@ def mock_trade_usdt_6(fee, is_short: bool):
|
|||||||
open_rate=10.0,
|
open_rate=10.0,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
strategy='SampleStrategy',
|
strategy='SampleStrategy',
|
||||||
open_order_id=f'prod_exit_6_{direc(is_short)}',
|
# open_order_id=f'prod_exit_6_{direc(is_short)}',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
is_short=is_short,
|
is_short=is_short,
|
||||||
)
|
)
|
||||||
@@ -378,7 +378,7 @@ def mock_trade_usdt_7(fee, is_short: bool):
|
|||||||
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=17),
|
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=17),
|
||||||
open_rate=2.0,
|
open_rate=2.0,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
open_order_id=f'1234_{direc(is_short)}',
|
# open_order_id=f'1234_{direc(is_short)}',
|
||||||
strategy='StrategyTestV2',
|
strategy='StrategyTestV2',
|
||||||
timeframe=5,
|
timeframe=5,
|
||||||
is_short=is_short,
|
is_short=is_short,
|
||||||
|
|||||||
+21
-17
@@ -1119,7 +1119,7 @@ def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_sho
|
|||||||
freqtrade.enter_positions()
|
freqtrade.enter_positions()
|
||||||
trade = Trade.session.scalars(select(Trade)).first()
|
trade = Trade.session.scalars(select(Trade)).first()
|
||||||
trade.is_short = is_short
|
trade.is_short = is_short
|
||||||
trade.open_order_id = None
|
# trade.open_order_id = None
|
||||||
trade.stoploss_order_id = None
|
trade.stoploss_order_id = None
|
||||||
trade.is_open = True
|
trade.is_open = True
|
||||||
trades = [trade]
|
trades = [trade]
|
||||||
@@ -1164,7 +1164,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
|||||||
trade = Trade.session.scalars(select(Trade)).first()
|
trade = Trade.session.scalars(select(Trade)).first()
|
||||||
trade.is_short = is_short
|
trade.is_short = is_short
|
||||||
trade.is_open = True
|
trade.is_open = True
|
||||||
trade.open_order_id = None
|
# trade.open_order_id = None
|
||||||
trade.stoploss_order_id = None
|
trade.stoploss_order_id = None
|
||||||
|
|
||||||
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
assert freqtrade.handle_stoploss_on_exchange(trade) is False
|
||||||
@@ -1175,7 +1175,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
|||||||
# should do nothing and return false
|
# should do nothing and return false
|
||||||
stop_order_dict.update({'id': "102"})
|
stop_order_dict.update({'id': "102"})
|
||||||
trade.is_open = True
|
trade.is_open = True
|
||||||
trade.open_order_id = None
|
# trade.open_order_id = None
|
||||||
trade.stoploss_order_id = "102"
|
trade.stoploss_order_id = "102"
|
||||||
trade.orders.append(
|
trade.orders.append(
|
||||||
Order(
|
Order(
|
||||||
@@ -1199,7 +1199,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
|||||||
# should set a stoploss immediately and return False
|
# should set a stoploss immediately and return False
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
trade.is_open = True
|
trade.is_open = True
|
||||||
trade.open_order_id = None
|
# trade.open_order_id = None
|
||||||
trade.stoploss_order_id = "102"
|
trade.stoploss_order_id = "102"
|
||||||
|
|
||||||
canceled_stoploss_order = MagicMock(return_value={'id': '103_1', 'status': 'canceled'})
|
canceled_stoploss_order = MagicMock(return_value={'id': '103_1', 'status': 'canceled'})
|
||||||
@@ -1224,7 +1224,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
|||||||
trade = Trade.session.scalars(select(Trade)).first()
|
trade = Trade.session.scalars(select(Trade)).first()
|
||||||
trade.is_short = is_short
|
trade.is_short = is_short
|
||||||
trade.is_open = True
|
trade.is_open = True
|
||||||
trade.open_order_id = None
|
# trade.open_order_id = None
|
||||||
trade.stoploss_order_id = "104"
|
trade.stoploss_order_id = "104"
|
||||||
trade.orders.append(Order(
|
trade.orders.append(Order(
|
||||||
ft_order_side='stoploss',
|
ft_order_side='stoploss',
|
||||||
@@ -3332,32 +3332,34 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
|||||||
l_order['filled'] = 0.0
|
l_order['filled'] = 0.0
|
||||||
l_order['status'] = 'open'
|
l_order['status'] = 'open'
|
||||||
reason = CANCEL_REASON['TIMEOUT']
|
reason = CANCEL_REASON['TIMEOUT']
|
||||||
assert freqtrade.handle_cancel_enter(trade, l_order, reason)
|
assert freqtrade.handle_cancel_enter(trade, l_order, trade.open_orders_ids[0], reason)
|
||||||
assert cancel_order_mock.call_count == 1
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
cancel_order_mock.reset_mock()
|
cancel_order_mock.reset_mock()
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
l_order['filled'] = 0.01
|
l_order['filled'] = 0.01
|
||||||
assert not freqtrade.handle_cancel_enter(trade, l_order, reason)
|
assert not freqtrade.handle_cancel_enter(trade, l_order, trade.open_orders_ids[0], reason)
|
||||||
assert cancel_order_mock.call_count == 0
|
assert cancel_order_mock.call_count == 0
|
||||||
assert log_has_re("Order .* for .* not cancelled, as the filled amount.* unexitable.*", caplog)
|
assert log_has_re("Order .* for .* not cancelled, as the filled amount.* unexitable.*", caplog)
|
||||||
|
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
cancel_order_mock.reset_mock()
|
cancel_order_mock.reset_mock()
|
||||||
l_order['filled'] = 2
|
l_order['filled'] = 2
|
||||||
assert not freqtrade.handle_cancel_enter(trade, l_order, reason)
|
assert not freqtrade.handle_cancel_enter(trade, l_order, trade.open_orders_ids[0], reason)
|
||||||
assert cancel_order_mock.call_count == 1
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
# Order remained open for some reason (cancel failed)
|
# Order remained open for some reason (cancel failed)
|
||||||
cancel_buy_order['status'] = 'open'
|
cancel_buy_order['status'] = 'open'
|
||||||
cancel_order_mock = MagicMock(return_value=cancel_buy_order)
|
cancel_order_mock = MagicMock(return_value=cancel_buy_order)
|
||||||
trade.open_order_id = 'some_open_order'
|
# trade.open_order_id = 'some_open_order'
|
||||||
mocker.patch(f'{EXMS}.cancel_order_with_result', cancel_order_mock)
|
mocker.patch(f'{EXMS}.cancel_order_with_result', cancel_order_mock)
|
||||||
assert not freqtrade.handle_cancel_enter(trade, l_order, reason)
|
assert not freqtrade.handle_cancel_enter(trade, l_order, trade.open_orders_ids[0], reason)
|
||||||
assert log_has_re(r"Order .* for .* not cancelled.", caplog)
|
assert log_has_re(r"Order .* for .* not cancelled.", caplog)
|
||||||
# min_pair_stake empty should not crash
|
# min_pair_stake empty should not crash
|
||||||
mocker.patch(f'{EXMS}.get_min_pair_stake_amount', return_value=None)
|
mocker.patch(f'{EXMS}.get_min_pair_stake_amount', return_value=None)
|
||||||
assert not freqtrade.handle_cancel_enter(trade, limit_order[entry_side(is_short)], reason)
|
assert not freqtrade.handle_cancel_enter(
|
||||||
|
trade, limit_order[entry_side(is_short)], trade.open_orders_ids[0], reason
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("is_short", [False, True])
|
@pytest.mark.parametrize("is_short", [False, True])
|
||||||
@@ -3378,7 +3380,9 @@ def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_sho
|
|||||||
trade = mock_trade_usdt_4(fee, is_short)
|
trade = mock_trade_usdt_4(fee, is_short)
|
||||||
Trade.session.add(trade)
|
Trade.session.add(trade)
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
assert freqtrade.handle_cancel_enter(trade, limit_buy_order_canceled_empty, reason)
|
assert freqtrade.handle_cancel_enter(
|
||||||
|
trade, limit_buy_order_canceled_empty, trade.open_orders_ids[0], reason
|
||||||
|
)
|
||||||
assert cancel_order_mock.call_count == 0
|
assert cancel_order_mock.call_count == 0
|
||||||
assert log_has_re(
|
assert log_has_re(
|
||||||
f'{trade.entry_side.capitalize()} order fully cancelled. '
|
f'{trade.entry_side.capitalize()} order fully cancelled. '
|
||||||
@@ -3415,7 +3419,7 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order
|
|||||||
l_order['filled'] = 0.0
|
l_order['filled'] = 0.0
|
||||||
l_order['status'] = 'open'
|
l_order['status'] = 'open'
|
||||||
reason = CANCEL_REASON['TIMEOUT']
|
reason = CANCEL_REASON['TIMEOUT']
|
||||||
assert freqtrade.handle_cancel_enter(trade, l_order, reason)
|
assert freqtrade.handle_cancel_enter(trade, l_order, trade.open_orders_ids[0], reason)
|
||||||
assert cancel_order_mock.call_count == 1
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
cancel_order_mock.reset_mock()
|
cancel_order_mock.reset_mock()
|
||||||
@@ -3423,7 +3427,7 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order
|
|||||||
order = deepcopy(l_order)
|
order = deepcopy(l_order)
|
||||||
order['status'] = 'canceled'
|
order['status'] = 'canceled'
|
||||||
mocker.patch(f'{EXMS}.fetch_order', return_value=order)
|
mocker.patch(f'{EXMS}.fetch_order', return_value=order)
|
||||||
assert not freqtrade.handle_cancel_enter(trade, l_order, reason)
|
assert not freqtrade.handle_cancel_enter(trade, l_order, trade.open_orders_ids[0], reason)
|
||||||
assert cancel_order_mock.call_count == 1
|
assert cancel_order_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@@ -4002,7 +4006,7 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(
|
|||||||
freqtrade.exit_positions(trades)
|
freqtrade.exit_positions(trades)
|
||||||
assert trade
|
assert trade
|
||||||
assert trade.stoploss_order_id == '123'
|
assert trade.stoploss_order_id == '123'
|
||||||
assert trade.open_order_id is None
|
# assert trade.open_order_id is None
|
||||||
|
|
||||||
# Assuming stoploss on exchange is hit
|
# Assuming stoploss on exchange is hit
|
||||||
# stoploss_order_id should become None
|
# stoploss_order_id should become None
|
||||||
@@ -4745,7 +4749,7 @@ def test_get_real_amount(
|
|||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
open_rate=0.245441,
|
open_rate=0.245441,
|
||||||
open_order_id="123456"
|
# open_order_id="123456"
|
||||||
)
|
)
|
||||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||||
|
|
||||||
@@ -5034,7 +5038,7 @@ def test_apply_fee_conditional(default_conf_usdt, fee, mocker,
|
|||||||
open_rate=0.245441,
|
open_rate=0.245441,
|
||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
open_order_id="123456"
|
# open_order_id="123456"
|
||||||
)
|
)
|
||||||
order = Order(
|
order = Order(
|
||||||
ft_order_side='buy',
|
ft_order_side='buy',
|
||||||
|
|||||||
Reference in New Issue
Block a user