merge upstream

This commit is contained in:
மனோஜ்குமார் பழனிச்சாமி
2022-05-08 13:14:07 +05:30
29 changed files with 772 additions and 129 deletions

View File

@@ -2364,7 +2364,7 @@ def test_bot_loop_start_called_once(mocker, default_conf_usdt, caplog):
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_entry_usercustom(
def test_manage_open_orders_entry_usercustom(
default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade,
limit_sell_order_old, fee, mocker, is_short
) -> None:
@@ -2396,12 +2396,12 @@ def test_check_handle_timedout_entry_usercustom(
Trade.query.session.add(open_trade)
# Ensure default is to return empty (so not mocked yet)
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
# Return false - trade remains open
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
nb_trades = len(trades)
@@ -2409,7 +2409,7 @@ def test_check_handle_timedout_entry_usercustom(
assert freqtrade.strategy.check_entry_timeout.call_count == 1
freqtrade.strategy.check_entry_timeout = MagicMock(side_effect=KeyError)
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
nb_trades = len(trades)
@@ -2418,7 +2418,7 @@ def test_check_handle_timedout_entry_usercustom(
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=True)
# Trade should be closed since the function returns true
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_wr_mock.call_count == 1
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
@@ -2428,7 +2428,7 @@ def test_check_handle_timedout_entry_usercustom(
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_entry(
def test_manage_open_orders_entry(
default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade,
limit_sell_order_old, fee, mocker, is_short
) -> None:
@@ -2454,8 +2454,9 @@ def test_check_handle_timedout_entry(
Trade.query.session.add(open_trade)
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234)
# check it does cancel buy orders over the time limit
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
@@ -2463,6 +2464,99 @@ def test_check_handle_timedout_entry(
assert nb_trades == 0
# Custom user buy-timeout is never called
assert freqtrade.strategy.check_entry_timeout.call_count == 0
# Entry adjustment is never called
assert freqtrade.strategy.adjust_entry_price.call_count == 0
@pytest.mark.parametrize("is_short", [False, True])
def test_adjust_entry_cancel(
default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade,
limit_sell_order_old, fee, mocker, caplog, is_short
) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
old_order = limit_sell_order_old if is_short else limit_buy_order_old
old_order['id'] = open_trade.open_order_id
limit_buy_cancel = deepcopy(old_order)
limit_buy_cancel['status'] = 'canceled'
cancel_order_mock = MagicMock(return_value=limit_buy_cancel)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker_usdt,
fetch_order=MagicMock(return_value=old_order),
cancel_order_with_result=cancel_order_mock,
get_fee=fee
)
open_trade.is_short = is_short
Trade.query.session.add(open_trade)
# Timeout to not interfere
freqtrade.strategy.ft_check_timed_out = MagicMock(return_value=False)
# check that order is cancelled
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=None)
freqtrade.manage_open_orders()
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 0
assert len(Order.query.all()) == 0
assert log_has_re(
f"{'Sell' if is_short else 'Buy'} order user requested order cancel*", caplog)
assert log_has_re(
f"{'Sell' if is_short else 'Buy'} order fully cancelled.*", caplog)
# Entry adjustment is called
assert freqtrade.strategy.adjust_entry_price.call_count == 1
@pytest.mark.parametrize("is_short", [False, True])
def test_adjust_entry_maintain_replace(
default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade,
limit_sell_order_old, fee, mocker, caplog, is_short
) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
old_order = limit_sell_order_old if is_short else limit_buy_order_old
old_order['id'] = open_trade.open_order_id
limit_buy_cancel = deepcopy(old_order)
limit_buy_cancel['status'] = 'canceled'
cancel_order_mock = MagicMock(return_value=limit_buy_cancel)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
fetch_ticker=ticker_usdt,
fetch_order=MagicMock(return_value=old_order),
cancel_order_with_result=cancel_order_mock,
get_fee=fee
)
open_trade.is_short = is_short
Trade.query.session.add(open_trade)
# Timeout to not interfere
freqtrade.strategy.ft_check_timed_out = MagicMock(return_value=False)
# Check that order is maintained
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=old_order['price'])
freqtrade.manage_open_orders()
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1
assert len(Order.get_open_orders()) == 1
# Entry adjustment is called
assert freqtrade.strategy.adjust_entry_price.call_count == 1
# Check that order is replaced
freqtrade.get_valid_enter_price_and_stake = MagicMock(return_value={100, 10, 1})
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234)
freqtrade.manage_open_orders()
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
assert len(trades) == 1
nb_all_orders = len(Order.query.all())
assert nb_all_orders == 2
# New order seems to be in closed status?
# nb_open_orders = len(Order.get_open_orders())
# assert nb_open_orders == 1
assert log_has_re(
f"{'Sell' if is_short else 'Buy'} order cancelled to be replaced*", caplog)
# Entry adjustment is called
assert freqtrade.strategy.adjust_entry_price.call_count == 1
@pytest.mark.parametrize("is_short", [False, True])
@@ -2488,18 +2582,17 @@ def test_check_handle_cancelled_buy(
Trade.query.session.add(open_trade)
# check it does cancel buy orders over the time limit
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
assert rpc_mock.call_count == 1
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
nb_trades = len(trades)
assert nb_trades == 0
assert len(trades) == 0
assert log_has_re(
f"{'Sell' if is_short else 'Buy'} order cancelled on exchange for Trade.*", caplog)
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_buy_exception(
def test_manage_open_orders_buy_exception(
default_conf_usdt, ticker_usdt, open_trade, is_short, fee, mocker
) -> None:
rpc_mock = patch_RPCManager(mocker)
@@ -2519,7 +2612,7 @@ def test_check_handle_timedout_buy_exception(
Trade.query.session.add(open_trade)
# check it does cancel buy orders over the time limit
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
assert rpc_mock.call_count == 0
trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all()
@@ -2528,7 +2621,7 @@ def test_check_handle_timedout_buy_exception(
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_exit_usercustom(
def test_manage_open_orders_exit_usercustom(
default_conf_usdt, ticker_usdt, limit_sell_order_old, mocker,
is_short, open_trade_usdt, caplog
) -> None:
@@ -2559,13 +2652,13 @@ def test_check_handle_timedout_exit_usercustom(
Trade.query.session.add(open_trade_usdt)
# Ensure default is false
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
freqtrade.strategy.check_exit_timeout = MagicMock(return_value=False)
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
# Return false - No impact
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
assert rpc_mock.call_count == 0
assert open_trade_usdt.is_open is False
@@ -2575,7 +2668,7 @@ def test_check_handle_timedout_exit_usercustom(
freqtrade.strategy.check_exit_timeout = MagicMock(side_effect=KeyError)
freqtrade.strategy.check_entry_timeout = MagicMock(side_effect=KeyError)
# Return Error - No impact
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
assert rpc_mock.call_count == 0
assert open_trade_usdt.is_open is False
@@ -2585,7 +2678,7 @@ def test_check_handle_timedout_exit_usercustom(
# Return True - sells!
freqtrade.strategy.check_exit_timeout = MagicMock(return_value=True)
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=True)
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1
assert open_trade_usdt.is_open is True
@@ -2598,7 +2691,7 @@ def test_check_handle_timedout_exit_usercustom(
mocker.patch('freqtrade.persistence.Trade.get_exit_order_count', return_value=1)
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.execute_trade_exit',
side_effect=DependencyException)
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert log_has_re('Unable to emergency sell .*', caplog)
et_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.execute_trade_exit')
@@ -2608,16 +2701,16 @@ def test_check_handle_timedout_exit_usercustom(
# If cancelling fails - no emergency sell!
with patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_exit', return_value=False):
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert et_mock.call_count == 0
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert log_has_re('Emergency exiting trade.*', caplog)
assert et_mock.call_count == 1
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_exit(
def test_manage_open_orders_exit(
default_conf_usdt, ticker_usdt, limit_sell_order_old, mocker, is_short, open_trade_usdt
) -> None:
rpc_mock = patch_RPCManager(mocker)
@@ -2644,7 +2737,7 @@ def test_check_handle_timedout_exit(
freqtrade.strategy.check_exit_timeout = MagicMock(return_value=False)
freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False)
# check it does cancel sell orders over the time limit
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 1
assert rpc_mock.call_count == 1
assert open_trade_usdt.is_open is True
@@ -2680,7 +2773,7 @@ def test_check_handle_cancelled_exit(
Trade.query.session.add(open_trade_usdt)
# check it does cancel sell orders over the time limit
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_mock.call_count == 0
assert rpc_mock.call_count == 1
assert open_trade_usdt.is_open is True
@@ -2690,7 +2783,7 @@ def test_check_handle_cancelled_exit(
@pytest.mark.parametrize("is_short", [False, True])
@pytest.mark.parametrize("leverage", [1, 3, 5, 10])
def test_check_handle_timedout_partial(
def test_manage_open_orders_partial(
default_conf_usdt, ticker_usdt, limit_buy_order_old_partial, is_short, leverage,
open_trade, mocker
) -> None:
@@ -2716,7 +2809,7 @@ def test_check_handle_timedout_partial(
# check it does cancel buy orders over the time limit
# note this is for a partially-complete buy order
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert cancel_order_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()
@@ -2727,7 +2820,7 @@ def test_check_handle_timedout_partial(
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_partial_fee(
def test_manage_open_orders_partial_fee(
default_conf_usdt, ticker_usdt, open_trade, caplog, fee, is_short,
limit_buy_order_old_partial, trades_for_order,
limit_buy_order_old_partial_canceled, mocker
@@ -2759,7 +2852,7 @@ def test_check_handle_timedout_partial_fee(
Trade.query.session.add(open_trade)
# cancelling a half-filled order should update the amount to the bought amount
# and apply fees if necessary.
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert log_has_re(r"Applying fee on amount for Trade.*", caplog)
@@ -2776,7 +2869,7 @@ def test_check_handle_timedout_partial_fee(
@pytest.mark.parametrize("is_short", [False, True])
def test_check_handle_timedout_partial_except(
def test_manage_open_orders_partial_except(
default_conf_usdt, ticker_usdt, open_trade, caplog, fee, is_short,
limit_buy_order_old_partial, trades_for_order,
limit_buy_order_old_partial_canceled, mocker
@@ -2807,7 +2900,7 @@ def test_check_handle_timedout_partial_except(
Trade.query.session.add(open_trade)
# cancelling a half-filled order should update the amount to the bought amount
# and apply fees if necessary.
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert log_has_re(r"Could not update trade amount: .*", caplog)
@@ -2823,8 +2916,8 @@ def test_check_handle_timedout_partial_except(
assert trades[0].fee_open == fee()
def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_trade_usdt, mocker,
caplog) -> None:
def test_manage_open_orders_exception(default_conf_usdt, ticker_usdt, open_trade_usdt, mocker,
caplog) -> None:
patch_RPCManager(mocker)
patch_exchange(mocker)
cancel_order_mock = MagicMock()
@@ -2845,7 +2938,7 @@ def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_tr
Trade.query.session.add(open_trade_usdt)
caplog.clear()
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
assert log_has_re(r"Cannot query order for Trade\(id=1, pair=ADA/USDT, amount=30.00000000, "
r"is_short=False, leverage=1.0, "
r"open_rate=2.00000000, open_since="
@@ -3411,7 +3504,7 @@ def test_execute_trade_exit_with_stoploss_on_exchange(
assert trade
trades = [trade]
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
freqtrade.exit_positions(trades)
# Increase the price and sell it
@@ -3463,7 +3556,7 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(
# Create some test data
freqtrade.enter_positions()
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
trade = Trade.query.first()
trades = [trade]
assert trade.stoploss_order_id is None
@@ -5233,7 +5326,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
assert trade.stake_amount == 110
assert not trade.fee_updated('buy')
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
trade = Trade.query.first()
assert trade
@@ -5339,7 +5432,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None:
MagicMock(return_value=closed_dca_order_1))
mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order',
MagicMock(return_value=closed_dca_order_1))
freqtrade.check_handle_timedout()
freqtrade.manage_open_orders()
# Assert trade is as expected (averaged dca)
trade = Trade.query.first()