switching limit_buy_order_usdt and limit_sell_order_usdt to limit_order(enter_side[is_short]) and limit_order(exit_side[is_short])

This commit is contained in:
Sam Germain 2021-10-02 23:35:50 -06:00
parent 57d66cc0f7
commit 09ef0781a1
3 changed files with 172 additions and 195 deletions

View File

@ -16,8 +16,8 @@ from freqtrade.configuration import validate_config_consistency
from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.converter import order_book_to_dataframe
from freqtrade.data.dataprovider import DataProvider from freqtrade.data.dataprovider import DataProvider
from freqtrade.edge import Edge from freqtrade.edge import Edge
from freqtrade.enums import (Collateral, RPCMessageType, SellType, SignalDirection, SignalTagType, from freqtrade.enums import (Collateral, RPCMessageType, SellType, SignalDirection, State,
State, TradingMode) TradingMode)
from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError, from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError,
InvalidOrderException, PricingError) InvalidOrderException, PricingError)
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds

View File

@ -2349,27 +2349,24 @@ def market_sell_order_usdt():
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def open_order(limit_buy_order_open, limit_sell_order_open): def limit_order(limit_buy_order_usdt, limit_sell_order_usdt):
# limit_sell_order_open if is_short else limit_buy_order_open
return { return {
True: limit_sell_order_open, 'buy': limit_buy_order_usdt,
False: limit_buy_order_open 'sell': limit_sell_order_usdt
} }
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def limit_order(limit_sell_order, limit_buy_order): def market_order(market_buy_order_usdt, market_sell_order_usdt):
# limit_sell_order if is_short else limit_buy_order
return { return {
True: limit_sell_order, 'buy': market_buy_order_usdt,
False: limit_buy_order 'sell': market_sell_order_usdt
} }
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def old_order(limit_sell_order_old, limit_buy_order_old): def limit_order_open(limit_buy_order_usdt_open, limit_sell_order_usdt_open):
# limit_sell_order_old if is_short else limit_buy_order_old
return { return {
True: limit_sell_order_old, 'buy': limit_buy_order_usdt_open,
False: limit_buy_order_old 'sell': limit_sell_order_usdt_open
} }

View File

@ -47,17 +47,6 @@ def patch_RPCManager(mocker) -> MagicMock:
return rpc_mock return rpc_mock
def open_order(limit_buy_order_usdt_open, limit_sell_order_usdt_open, is_short):
return limit_sell_order_usdt_open if is_short else limit_buy_order_usdt_open
def limit_order(limit_sell_order_usdt, limit_buy_order_usdt, is_short):
return limit_sell_order_usdt if is_short else limit_buy_order_usdt
def old_order(limit_sell_order_old, limit_buy_order_old, is_short):
return limit_sell_order_old if is_short else limit_buy_order_old
# Unit tests # Unit tests
@ -214,13 +203,14 @@ def test_edge_overrides_stake_amount(mocker, edge_conf) -> None:
'LTC/BTC', freqtrade.edge) == (999.9 * 0.5 * 0.01) / 0.21 'LTC/BTC', freqtrade.edge) == (999.9 * 0.5 * 0.01) / 0.21
@pytest.mark.parametrize('is_short', [False, True])
@pytest.mark.parametrize('buy_price_mult,ignore_strat_sl', [ @pytest.mark.parametrize('buy_price_mult,ignore_strat_sl', [
# Override stoploss # Override stoploss
(0.79, False), (0.79, False),
# Override strategy stoploss # Override strategy stoploss
(0.85, True) (0.85, True)
]) ])
def test_edge_overrides_stoploss(limit_buy_order_usdt, fee, caplog, mocker, def test_edge_overrides_stoploss(limit_order, fee, caplog, mocker, is_short,
buy_price_mult, ignore_strat_sl, edge_conf) -> None: buy_price_mult, ignore_strat_sl, edge_conf) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
@ -231,13 +221,13 @@ def test_edge_overrides_stoploss(limit_buy_order_usdt, fee, caplog, mocker,
# Thus, if price falls 21%, stoploss should be triggered # Thus, if price falls 21%, stoploss should be triggered
# #
# mocking the ticker_usdt: price is falling ... # mocking the ticker_usdt: price is falling ...
buy_price = limit_buy_order_usdt['price'] enter_price = limit_order[enter_side(is_short)]['price']
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
fetch_ticker=MagicMock(return_value={ fetch_ticker=MagicMock(return_value={
'bid': buy_price * buy_price_mult, 'bid': enter_price * buy_price_mult,
'ask': buy_price * buy_price_mult, 'ask': enter_price * buy_price_mult,
'last': buy_price * buy_price_mult, 'last': enter_price * buy_price_mult,
}), }),
get_fee=fee, get_fee=fee,
) )
@ -250,7 +240,7 @@ def test_edge_overrides_stoploss(limit_buy_order_usdt, fee, caplog, mocker,
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False) freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order_usdt) trade.update(limit_order[enter_side(is_short)])
############################################# #############################################
# stoploss shoud be hit # stoploss shoud be hit
@ -296,7 +286,7 @@ def test_total_open_trades_stakes(mocker, default_conf_usdt, ticker_usdt, fee) -
(False, 2.0), (False, 2.0),
(True, 2.2) (True, 2.2)
]) ])
def test_create_trade(default_conf_usdt, ticker_usdt, limit_buy_order_usdt, limit_sell_order_usdt, def test_create_trade(default_conf_usdt, ticker_usdt, limit_order,
fee, mocker, is_short, open_rate) -> None: fee, mocker, is_short, open_rate) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
@ -322,10 +312,7 @@ def test_create_trade(default_conf_usdt, ticker_usdt, limit_buy_order_usdt, limi
assert trade.exchange == 'binance' assert trade.exchange == 'binance'
# Simulate fulfilled LIMIT_BUY order for trade # Simulate fulfilled LIMIT_BUY order for trade
if is_short: trade.update(limit_order[enter_side(is_short)])
trade.update(limit_sell_order_usdt)
else:
trade.update(limit_buy_order_usdt)
assert trade.open_rate == open_rate assert trade.open_rate == open_rate
assert trade.amount == 30.0 assert trade.amount == 30.0
@ -357,16 +344,16 @@ def test_create_trade_no_stake_amount(default_conf_usdt, ticker_usdt, fee, mocke
(UNLIMITED_STAKE_AMOUNT, False, True, 0), (UNLIMITED_STAKE_AMOUNT, False, True, 0),
]) ])
def test_create_trade_minimal_amount( def test_create_trade_minimal_amount(
default_conf_usdt, ticker_usdt, limit_buy_order_usdt_open, fee, mocker, default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker,
stake_amount, create, amount_enough, max_open_trades, caplog, is_short stake_amount, create, amount_enough, max_open_trades, caplog, is_short
) -> None: ) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
buy_mock = MagicMock(return_value=limit_buy_order_usdt_open) enter_mock = MagicMock(return_value=limit_order_open[enter_side(is_short)])
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
fetch_ticker=ticker_usdt, fetch_ticker=ticker_usdt,
create_order=buy_mock, create_order=enter_mock,
get_fee=fee, get_fee=fee,
) )
default_conf_usdt['max_open_trades'] = max_open_trades default_conf_usdt['max_open_trades'] = max_open_trades
@ -377,7 +364,7 @@ def test_create_trade_minimal_amount(
if create: if create:
assert freqtrade.create_trade('ETH/USDT') assert freqtrade.create_trade('ETH/USDT')
if amount_enough: if amount_enough:
rate, amount = buy_mock.call_args[1]['rate'], buy_mock.call_args[1]['amount'] rate, amount = enter_mock.call_args[1]['rate'], enter_mock.call_args[1]['amount']
assert rate * amount <= default_conf_usdt['stake_amount'] assert rate * amount <= default_conf_usdt['stake_amount']
else: else:
assert log_has_re( assert log_has_re(
@ -549,15 +536,17 @@ def test_create_trades_preopen(default_conf_usdt, ticker_usdt, fee, mocker,
assert len(trades) == 4 assert len(trades) == 4
def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_buy_order_usdt, @pytest.mark.parametrize('is_short', [False, True])
limit_buy_order_usdt_open, fee, mocker, caplog) -> None: def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_order, limit_order_open,
is_short, fee, mocker, caplog
) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
fetch_ticker=ticker_usdt, fetch_ticker=ticker_usdt,
create_order=MagicMock(return_value=limit_buy_order_usdt_open), create_order=MagicMock(return_value=limit_order_open[enter_side(is_short)]),
fetch_order=MagicMock(return_value=limit_buy_order_usdt), fetch_order=MagicMock(return_value=limit_order[enter_side(is_short)]),
get_fee=fee, get_fee=fee,
) )
freqtrade = FreqtradeBot(default_conf_usdt) freqtrade = FreqtradeBot(default_conf_usdt)
@ -729,11 +718,11 @@ def test_process_informative_pairs_added(default_conf_usdt, ticker_usdt, mocker)
@pytest.mark.parametrize("is_short", [True, False]) @pytest.mark.parametrize("is_short", [True, False])
def test_execute_entry(mocker, default_conf_usdt, fee, limit_buy_order_usdt, limit_sell_order_usdt, def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
limit_buy_order_usdt_open, limit_sell_order_usdt_open, is_short) -> None: limit_order_open, is_short) -> None:
open_order = limit_sell_order_usdt_open if is_short else limit_buy_order_usdt_open open_order = limit_order_open[enter_side(is_short)]
order = limit_sell_order_usdt if is_short else limit_buy_order_usdt order = limit_order[enter_side(is_short)]
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
@ -906,8 +895,8 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_buy_order_usdt, lim
assert trade.open_rate_requested == 10 assert trade.open_rate_requested == 10
# TODO-lev: @pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_buy_order_usdt) -> None: def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_order, is_short) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
@ -916,7 +905,7 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_buy_o
'ask': 2.2, 'ask': 2.2,
'last': 1.9 'last': 1.9
}), }),
create_order=MagicMock(return_value=limit_buy_order_usdt), create_order=MagicMock(return_value=limit_order[enter_side(is_short)]),
get_rate=MagicMock(return_value=0.11), get_rate=MagicMock(return_value=0.11),
get_min_pair_stake_amount=MagicMock(return_value=1), get_min_pair_stake_amount=MagicMock(return_value=1),
get_fee=fee, get_fee=fee,
@ -928,11 +917,11 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_buy_o
# TODO-lev: KeyError happens on short, why? # TODO-lev: KeyError happens on short, why?
assert freqtrade.execute_entry(pair, stake_amount) assert freqtrade.execute_entry(pair, stake_amount)
limit_buy_order_usdt['id'] = '222' limit_order[enter_side(is_short)]['id'] = '222'
freqtrade.strategy.confirm_trade_entry = MagicMock(side_effect=Exception) freqtrade.strategy.confirm_trade_entry = MagicMock(side_effect=Exception)
assert freqtrade.execute_entry(pair, stake_amount) assert freqtrade.execute_entry(pair, stake_amount)
limit_buy_order_usdt['id'] = '2223' limit_order[enter_side(is_short)]['id'] = '2223'
freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True)
assert freqtrade.execute_entry(pair, stake_amount) assert freqtrade.execute_entry(pair, stake_amount)
@ -941,16 +930,15 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_buy_o
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_buy_order_usdt, def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_short) -> None:
limit_sell_order_usdt, is_short) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
order = limit_sell_order_usdt if is_short else limit_buy_order_usdt order = limit_order[enter_side(is_short)]
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[]) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
return_value=limit_buy_order_usdt['amount']) return_value=order['amount'])
stoploss = MagicMock(return_value={'id': 13434334}) stoploss = MagicMock(return_value={'id': 13434334})
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss) mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
@ -973,10 +961,10 @@ def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_buy_order_usd
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_short, def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_short,
limit_buy_order_usdt, limit_sell_order_usdt) -> None: limit_order) -> None:
stoploss = MagicMock(return_value={'id': 13434334}) stoploss = MagicMock(return_value={'id': 13434334})
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt enter_order = limit_order[enter_side(is_short)]
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt exit_order = limit_order[exit_side(is_short)]
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -1098,10 +1086,10 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog, is_short, def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog, is_short,
limit_buy_order_usdt, limit_sell_order_usdt) -> None: limit_order) -> None:
# Sixth case: stoploss order was cancelled but couldn't create new one # Sixth case: stoploss order was cancelled but couldn't create new one
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt enter_order = limit_order[enter_side(is_short)]
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt exit_order = limit_order[exit_side(is_short)]
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -1141,10 +1129,10 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog,
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_create_stoploss_order_invalid_order( def test_create_stoploss_order_invalid_order(
mocker, default_conf_usdt, caplog, fee, is_short, limit_buy_order_usdt, limit_sell_order_usdt, mocker, default_conf_usdt, caplog, fee, is_short, limit_order, limit_order_open
limit_buy_order_usdt_open, limit_sell_order_usdt_open): ):
open_order = limit_sell_order_usdt_open if is_short else limit_buy_order_usdt_open open_order = limit_order_open[enter_side(is_short)]
order = limit_buy_order_usdt if is_short else limit_sell_order_usdt order = limit_order[exit_side(is_short)]
rpc_mock = patch_RPCManager(mocker) rpc_mock = patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
create_order_mock = MagicMock(side_effect=[ create_order_mock = MagicMock(side_effect=[
@ -1194,14 +1182,10 @@ def test_create_stoploss_order_invalid_order(
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_create_stoploss_order_insufficient_funds( def test_create_stoploss_order_insufficient_funds(
mocker, default_conf_usdt, caplog, fee, limit_buy_order_usdt_open, limit_sell_order_usdt_open, mocker, default_conf_usdt, caplog, fee, limit_order_open,
limit_buy_order_usdt, limit_sell_order_usdt, is_short limit_order, is_short
): ):
exit_order = ( exit_order = limit_order[exit_side(is_short)]['id']
MagicMock(return_value={'id': limit_buy_order_usdt['id']})
if is_short else
MagicMock(return_value={'id': limit_sell_order_usdt['id']})
)
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mock_insuf = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_insufficient_funds') mock_insuf = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_insufficient_funds')
@ -1213,7 +1197,7 @@ def test_create_stoploss_order_insufficient_funds(
'last': 1.9 'last': 1.9
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_sell_order_usdt_open if is_short else limit_buy_order_usdt_open, limit_order[enter_side(is_short)],
exit_order, exit_order,
]), ]),
get_fee=fee, get_fee=fee,
@ -1246,11 +1230,11 @@ def test_create_stoploss_order_insufficient_funds(
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_handle_stoploss_on_exchange_trailing(mocker, default_conf_usdt, fee, is_short, def test_handle_stoploss_on_exchange_trailing(mocker, default_conf_usdt, fee, is_short,
limit_buy_order_usdt, limit_sell_order_usdt) -> None: limit_order) -> None:
# TODO-lev: test for short # TODO-lev: test for short
# When trailing stoploss is set # When trailing stoploss is set
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt enter_order = limit_order[enter_side(is_short)]
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt exit_order = limit_order[exit_side(is_short)]
stoploss = MagicMock(return_value={'id': 13434334}) stoploss = MagicMock(return_value={'id': 13434334})
patch_RPCManager(mocker) patch_RPCManager(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -1368,11 +1352,10 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf_usdt, fee, is
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_handle_stoploss_on_exchange_trailing_error( def test_handle_stoploss_on_exchange_trailing_error(
mocker, default_conf_usdt, fee, caplog, limit_buy_order_usdt, mocker, default_conf_usdt, fee, caplog, limit_order, is_short
limit_sell_order_usdt, is_short
) -> None: ) -> None:
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt enter_order = limit_order[enter_side(is_short)]
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt exit_order = limit_order[exit_side(is_short)]
# When trailing stoploss is set # When trailing stoploss is set
stoploss = MagicMock(return_value={'id': 13434334}) stoploss = MagicMock(return_value={'id': 13434334})
patch_exchange(mocker) patch_exchange(mocker)
@ -1450,11 +1433,10 @@ def test_handle_stoploss_on_exchange_trailing_error(
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_handle_stoploss_on_exchange_custom_stop( def test_handle_stoploss_on_exchange_custom_stop(
mocker, default_conf_usdt, fee, is_short, limit_buy_order_usdt, mocker, default_conf_usdt, fee, is_short, limit_order
limit_sell_order_usdt
) -> None: ) -> None:
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt enter_order = limit_order[enter_side(is_short)]
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt exit_order = limit_order[exit_side(is_short)]
# When trailing stoploss is set # When trailing stoploss is set
# TODO-lev: test for short # TODO-lev: test for short
stoploss = MagicMock(return_value={'id': 13434334}) stoploss = MagicMock(return_value={'id': 13434334})
@ -1573,10 +1555,10 @@ def test_handle_stoploss_on_exchange_custom_stop(
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog, is_short, def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog, is_short,
limit_buy_order_usdt, limit_sell_order_usdt) -> None: limit_order) -> None:
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt enter_order = limit_order[enter_side(is_short)]
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt exit_order = limit_order[exit_side(is_short)]
# When trailing stoploss is set # When trailing stoploss is set
stoploss = MagicMock(return_value={'id': 13434334}) stoploss = MagicMock(return_value={'id': 13434334})
@ -1717,15 +1699,16 @@ def test_enter_positions(mocker, default_conf_usdt, return_value, side_effect,
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_exit_positions( def test_exit_positions(
mocker, default_conf_usdt, limit_buy_order_usdt, is_short, caplog mocker, default_conf_usdt, limit_order, is_short, caplog
) -> None: ) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=limit_buy_order_usdt) mocker.patch('freqtrade.exchange.Exchange.fetch_order',
return_value=limit_order[enter_side(is_short)])
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[]) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
return_value=limit_buy_order_usdt['amount']) return_value=limit_order[enter_side(is_short)]['amount'])
trade = MagicMock() trade = MagicMock()
trade.is_short = is_short trade.is_short = is_short
@ -1747,12 +1730,11 @@ def test_exit_positions(
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_exit_positions_exception( def test_exit_positions_exception(
mocker, default_conf_usdt, limit_buy_order_usdt, mocker, default_conf_usdt, limit_order, caplog, is_short
limit_sell_order_usdt, caplog, is_short
) -> None: ) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
order = limit_sell_order_usdt if is_short else limit_buy_order_usdt order = limit_order[enter_side(is_short)]
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=limit_buy_order_usdt) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
trade = MagicMock() trade = MagicMock()
trade.is_short = is_short trade.is_short = is_short
@ -1774,11 +1756,10 @@ def test_exit_positions_exception(
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_update_trade_state( def test_update_trade_state(
mocker, default_conf_usdt, limit_buy_order_usdt, mocker, default_conf_usdt, limit_order, is_short, caplog
limit_sell_order_usdt, is_short, caplog
) -> None: ) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
order = limit_sell_order_usdt if is_short else limit_buy_order_usdt order = limit_order[enter_side(is_short)]
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
@ -1829,10 +1810,10 @@ def test_update_trade_state(
(8.0, False) (8.0, False)
]) ])
def test_update_trade_state_withorderdict( def test_update_trade_state_withorderdict(
default_conf_usdt, trades_for_order, limit_buy_order_usdt, fee, mocker, initial_amount, default_conf_usdt, trades_for_order, limit_order, fee, mocker, initial_amount,
has_rounding_fee, limit_sell_order_usdt, is_short, caplog has_rounding_fee, is_short, caplog
): ):
order = limit_sell_order_usdt if is_short else limit_buy_order_usdt order = limit_order[enter_side(is_short)]
trades_for_order[0]['amount'] = initial_amount trades_for_order[0]['amount'] = initial_amount
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order)
# fetch_order should not be called!! # fetch_order should not be called!!
@ -1855,15 +1836,15 @@ def test_update_trade_state_withorderdict(
) )
freqtrade.update_trade_state(trade, '123456', order) freqtrade.update_trade_state(trade, '123456', order)
assert trade.amount != amount assert trade.amount != amount
assert trade.amount == limit_buy_order_usdt['amount'] assert trade.amount == order['amount']
if has_rounding_fee: if has_rounding_fee:
assert log_has_re(r'Applying fee on amount for .*', caplog) assert log_has_re(r'Applying fee on amount for .*', caplog)
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_update_trade_state_exception(mocker, default_conf_usdt, is_short, limit_sell_order_usdt, def test_update_trade_state_exception(mocker, default_conf_usdt, is_short, limit_order,
limit_buy_order_usdt, caplog) -> None: caplog) -> None:
order = limit_sell_order_usdt if is_short else limit_buy_order_usdt order = limit_order[enter_side(is_short)]
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
@ -1899,11 +1880,10 @@ def test_update_trade_state_orderexception(mocker, default_conf_usdt, caplog) ->
@pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_update_trade_state_sell( def test_update_trade_state_sell(
default_conf_usdt, trades_for_order, limit_sell_order_usdt_open, limit_buy_order_usdt_open, default_conf_usdt, trades_for_order, limit_order_open, limit_order, is_short, mocker,
limit_sell_order_usdt, is_short, mocker, limit_buy_order_usdt,
): ):
open_order = limit_buy_order_usdt_open if is_short else limit_sell_order_usdt_open open_order = limit_order_open[exit_side(is_short)]
order = limit_buy_order_usdt if is_short else limit_sell_order_usdt l_order = limit_order[exit_side(is_short)]
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order)
# fetch_order should not be called!! # fetch_order should not be called!!
mocker.patch('freqtrade.exchange.Exchange.fetch_order', MagicMock(side_effect=ValueError)) mocker.patch('freqtrade.exchange.Exchange.fetch_order', MagicMock(side_effect=ValueError))
@ -1912,7 +1892,7 @@ def test_update_trade_state_sell(
patch_exchange(mocker) patch_exchange(mocker)
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
amount = order["amount"] amount = l_order["amount"]
wallet_mock.reset_mock() wallet_mock.reset_mock()
trade = Trade( trade = Trade(
pair='LTC/ETH', pair='LTC/ETH',
@ -1929,9 +1909,8 @@ def test_update_trade_state_sell(
order = Order.parse_from_ccxt_object(open_order, 'LTC/ETH', (enter_side(is_short))) order = Order.parse_from_ccxt_object(open_order, 'LTC/ETH', (enter_side(is_short)))
trade.orders.append(order) trade.orders.append(order)
assert order.status == 'open' assert order.status == 'open'
freqtrade.update_trade_state(trade, trade.open_order_id, freqtrade.update_trade_state(trade, trade.open_order_id, l_order)
limit_buy_order_usdt if is_short else limit_sell_order_usdt) assert trade.amount == l_order['amount']
assert trade.amount == limit_buy_order_usdt['amount'] if is_short else limit_sell_order_usdt['amount']
# Wallet needs to be updated after closing a limit-sell order to reenable buying # Wallet needs to be updated after closing a limit-sell order to reenable buying
assert wallet_mock.call_count == 1 assert wallet_mock.call_count == 1
assert not trade.is_open assert not trade.is_open
@ -1941,12 +1920,11 @@ def test_update_trade_state_sell(
@pytest.mark.parametrize('is_short', [False, True]) @pytest.mark.parametrize('is_short', [False, True])
def test_handle_trade( def test_handle_trade(
default_conf_usdt, limit_buy_order_usdt_open, limit_buy_order_usdt, default_conf_usdt, limit_order_open, limit_order, fee, mocker, is_short
limit_sell_order_usdt_open, limit_sell_order_usdt, fee, mocker, is_short
) -> None: ) -> None:
open_order = limit_buy_order_usdt_open if is_short else limit_sell_order_usdt_open open_order = limit_order_open[exit_side(is_short)]
enter_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt enter_order = limit_order[exit_side(is_short)]
exit_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt exit_order = limit_order[enter_side(is_short)]
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -1990,10 +1968,9 @@ def test_handle_trade(
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_handle_overlapping_signals( def test_handle_overlapping_signals(
default_conf_usdt, ticker_usdt, limit_buy_order_usdt_open, default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, is_short
limit_sell_order_usdt_open, fee, mocker, is_short
) -> None: ) -> None:
open_order = limit_buy_order_usdt_open if is_short else limit_sell_order_usdt_open open_order = limit_order_open[exit_side(is_short)]
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -2057,10 +2034,10 @@ def test_handle_overlapping_signals(
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_buy_order_usdt_open, def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, caplog,
limit_sell_order_usdt_open, fee, mocker, caplog, is_short) -> None: is_short) -> None:
open_order = limit_sell_order_usdt_open if is_short else limit_buy_order_usdt_open open_order = limit_order_open[enter_side(is_short)]
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
@ -2100,12 +2077,11 @@ def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_buy_order_usdt_o
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_handle_trade_use_sell_signal( def test_handle_trade_use_sell_signal(
default_conf_usdt, ticker_usdt, limit_buy_order_usdt_open, default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, caplog, is_short
limit_sell_order_usdt_open, fee, mocker, caplog, is_short
) -> None: ) -> None:
enter_open_order = limit_buy_order_usdt_open if is_short else limit_sell_order_usdt_open enter_open_order = limit_order_open[exit_side(is_short)]
exit_open_order = limit_sell_order_usdt_open if is_short else limit_buy_order_usdt_open exit_open_order = limit_order_open[enter_side(is_short)]
# use_sell_signal is True buy default # use_sell_signal is True buy default
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
@ -2141,12 +2117,12 @@ def test_handle_trade_use_sell_signal(
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_close_trade( def test_close_trade(
default_conf_usdt, ticker_usdt, limit_buy_order_usdt, limit_sell_order_usdt_open, default_conf_usdt, ticker_usdt, limit_order_open,
limit_buy_order_usdt_open, limit_sell_order_usdt, fee, mocker, is_short limit_order, fee, mocker, is_short
) -> None: ) -> None:
open_order = limit_buy_order_usdt_open if is_short else limit_sell_order_usdt_open open_order = limit_order_open[exit_side(is_short)]
enter_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt enter_order = limit_order[exit_side(is_short)]
exit_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt exit_order = limit_order[enter_side(is_short)]
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -2608,11 +2584,12 @@ def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_tr
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_buy_order_usdt, def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order,
is_short) -> None: is_short) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
cancel_buy_order = deepcopy(limit_buy_order_usdt) l_order = limit_order[enter_side('is_short')]
cancel_buy_order = deepcopy(limit_order[enter_side('is_short')])
cancel_buy_order['status'] = 'canceled' cancel_buy_order['status'] = 'canceled'
del cancel_buy_order['filled'] del cancel_buy_order['filled']
@ -2627,30 +2604,30 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_buy_order_
trade.open_rate = 200 trade.open_rate = 200
trade.is_short = False trade.is_short = False
trade.enter_side = "buy" trade.enter_side = "buy"
limit_buy_order_usdt['filled'] = 0.0 l_order['filled'] = 0.0
limit_buy_order_usdt['status'] = 'open' l_order['status'] = 'open'
reason = CANCEL_REASON['TIMEOUT'] reason = CANCEL_REASON['TIMEOUT']
assert freqtrade.handle_cancel_enter(trade, limit_buy_order_usdt, reason) assert freqtrade.handle_cancel_enter(trade, l_order, 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()
limit_buy_order_usdt['filled'] = 0.01 l_order['filled'] = 0.01
assert not freqtrade.handle_cancel_enter(trade, limit_buy_order_usdt, reason) assert not freqtrade.handle_cancel_enter(trade, l_order, 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()
limit_buy_order_usdt['filled'] = 2 l_order['filled'] = 2
assert not freqtrade.handle_cancel_enter(trade, limit_buy_order_usdt, reason) assert not freqtrade.handle_cancel_enter(trade, l_order, 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)
mocker.patch('freqtrade.exchange.Exchange.cancel_order_with_result', cancel_order_mock) mocker.patch('freqtrade.exchange.Exchange.cancel_order_with_result', cancel_order_mock)
assert not freqtrade.handle_cancel_enter(trade, limit_buy_order_usdt, reason) assert not freqtrade.handle_cancel_enter(trade, l_order, reason)
assert log_has_re(r"Order .* for .* not cancelled.", caplog) assert log_has_re(r"Order .* for .* not cancelled.", caplog)
@ -2684,10 +2661,11 @@ def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_sho
'String Return value', 'String Return value',
123 123
]) ])
def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_buy_order_usdt, is_short, def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order, is_short,
cancelorder) -> None: cancelorder) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
l_order = limit_order[enter_side('is_short')]
cancel_order_mock = MagicMock(return_value=cancelorder) cancel_order_mock = MagicMock(return_value=cancelorder)
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
@ -2702,15 +2680,15 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_buy_o
trade.enter_side = "buy" trade.enter_side = "buy"
trade.open_rate = 200 trade.open_rate = 200
trade.enter_side = "buy" trade.enter_side = "buy"
limit_buy_order_usdt['filled'] = 0.0 l_order['filled'] = 0.0
limit_buy_order_usdt['status'] = 'open' l_order['status'] = 'open'
reason = CANCEL_REASON['TIMEOUT'] reason = CANCEL_REASON['TIMEOUT']
assert freqtrade.handle_cancel_enter(trade, limit_buy_order_usdt, reason) assert freqtrade.handle_cancel_enter(trade, l_order, 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()
limit_buy_order_usdt['filled'] = 1.0 l_order['filled'] = 1.0
assert not freqtrade.handle_cancel_enter(trade, limit_buy_order_usdt, reason) assert not freqtrade.handle_cancel_enter(trade, l_order, reason)
assert cancel_order_mock.call_count == 1 assert cancel_order_mock.call_count == 1
@ -3061,8 +3039,8 @@ def test_execute_trade_exit_sloe_cancel_exception(
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_execute_trade_exit_with_stoploss_on_exchange(default_conf_usdt, ticker_usdt, fee, def test_execute_trade_exit_with_stoploss_on_exchange(
ticker_usdt_sell_up, is_short, mocker) -> None: default_conf_usdt, ticker_usdt, fee, ticker_usdt_sell_up, is_short, mocker) -> None:
default_conf_usdt['exchange']['name'] = 'binance' default_conf_usdt['exchange']['name'] = 'binance'
rpc_mock = patch_RPCManager(mocker) rpc_mock = patch_RPCManager(mocker)
@ -3296,7 +3274,7 @@ def test_execute_trade_exit_insufficient_funds_error(default_conf_usdt, ticker_u
(False, 0.10, 0.22, True, False, SellType.SELL_SIGNAL.value), (False, 0.10, 0.22, True, False, SellType.SELL_SIGNAL.value),
]) ])
def test_sell_profit_only( def test_sell_profit_only(
default_conf_usdt, limit_buy_order_usdt, limit_buy_order_usdt_open, is_short, default_conf_usdt, limit_order, limit_order_open, is_short,
fee, mocker, profit_only, bid, ask, handle_first, handle_second, sell_type) -> None: fee, mocker, profit_only, bid, ask, handle_first, handle_second, sell_type) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
@ -3308,7 +3286,7 @@ def test_sell_profit_only(
'last': bid 'last': bid
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_buy_order_usdt_open, limit_order_open[enter_side['is_short']],
{'id': 1234553382}, {'id': 1234553382},
]), ]),
get_fee=fee, get_fee=fee,
@ -3328,7 +3306,7 @@ def test_sell_profit_only(
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order_usdt) trade.update(limit_order[enter_side('is_short')])
freqtrade.wallets.update() freqtrade.wallets.update()
patch_get_signal(freqtrade, enter_long=False, exit_long=True) patch_get_signal(freqtrade, enter_long=False, exit_long=True)
assert freqtrade.handle_trade(trade) is handle_first assert freqtrade.handle_trade(trade) is handle_first
@ -3339,7 +3317,7 @@ def test_sell_profit_only(
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_sell_not_enough_balance(default_conf_usdt, limit_buy_order_usdt, limit_buy_order_usdt_open, def test_sell_not_enough_balance(default_conf_usdt, limit_order, limit_order_open,
is_short, fee, mocker, caplog) -> None: is_short, fee, mocker, caplog) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
@ -3351,7 +3329,7 @@ def test_sell_not_enough_balance(default_conf_usdt, limit_buy_order_usdt, limit_
'last': 0.00002172 'last': 0.00002172
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_buy_order_usdt_open, limit_order_open[enter_side(is_short)],
{'id': 1234553382}, {'id': 1234553382},
]), ]),
get_fee=fee, get_fee=fee,
@ -3365,7 +3343,7 @@ def test_sell_not_enough_balance(default_conf_usdt, limit_buy_order_usdt, limit_
trade = Trade.query.first() trade = Trade.query.first()
amnt = trade.amount amnt = trade.amount
trade.update(limit_buy_order_usdt) trade.update(limit_order[enter_side(is_short)])
patch_get_signal(freqtrade, enter_long=False, exit_long=True) patch_get_signal(freqtrade, enter_long=False, exit_long=True)
mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=trade.amount * 0.985)) mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=trade.amount * 0.985))
@ -3450,8 +3428,8 @@ def test_locked_pairs(default_conf_usdt, ticker_usdt, fee,
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usdt, def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_open, is_short,
limit_buy_order_usdt_open, is_short, fee, mocker) -> None: fee, mocker) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -3462,7 +3440,7 @@ def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usdt,
'last': 2.19 'last': 2.19
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_buy_order_usdt_open, limit_order_open[enter_side(is_short)],
{'id': 1234553382}, {'id': 1234553382},
]), ]),
get_fee=fee, get_fee=fee,
@ -3476,7 +3454,7 @@ def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usdt,
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order_usdt) trade.update(limit_order[enter_side(is_short)])
freqtrade.wallets.update() freqtrade.wallets.update()
patch_get_signal(freqtrade, enter_long=True, exit_long=True) patch_get_signal(freqtrade, enter_long=True, exit_long=True)
assert freqtrade.handle_trade(trade) is False assert freqtrade.handle_trade(trade) is False
@ -3488,7 +3466,7 @@ def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usdt,
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_trailing_stop_loss(default_conf_usdt, limit_buy_order_usdt_open, def test_trailing_stop_loss(default_conf_usdt, limit_order_open,
is_short, fee, caplog, mocker) -> None: is_short, fee, caplog, mocker) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
@ -3500,7 +3478,7 @@ def test_trailing_stop_loss(default_conf_usdt, limit_buy_order_usdt_open,
'last': 2.0 'last': 2.0
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_buy_order_usdt_open, limit_order_open[enter_side(is_short)],
{'id': 1234553382}, {'id': 1234553382},
]), ]),
get_fee=fee, get_fee=fee,
@ -3549,21 +3527,21 @@ def test_trailing_stop_loss(default_conf_usdt, limit_buy_order_usdt_open,
(0.055, True, 1.8), (0.055, True, 1.8),
]) ])
def test_trailing_stop_loss_positive( def test_trailing_stop_loss_positive(
default_conf_usdt, limit_buy_order_usdt, limit_buy_order_usdt_open, default_conf_usdt, limit_order, limit_order_open,
offset, fee, caplog, mocker, trail_if_reached, second_sl, is_short offset, fee, caplog, mocker, trail_if_reached, second_sl, is_short
) -> None: ) -> None:
buy_price = limit_buy_order_usdt['price'] enter_price = limit_order[enter_side(is_short)]['price']
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
fetch_ticker=MagicMock(return_value={ fetch_ticker=MagicMock(return_value={
'bid': buy_price - 0.01, 'bid': enter_price - 0.01,
'ask': buy_price - 0.01, 'ask': enter_price - 0.01,
'last': buy_price - 0.01 'last': enter_price - 0.01
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_buy_order_usdt_open, limit_order_open[enter_side(is_short)],
{'id': 1234553382}, {'id': 1234553382},
]), ]),
get_fee=fee, get_fee=fee,
@ -3581,7 +3559,7 @@ def test_trailing_stop_loss_positive(
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order_usdt) trade.update(limit_order[enter_side(is_short)])
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
# stop-loss not reached # stop-loss not reached
assert freqtrade.handle_trade(trade) is False assert freqtrade.handle_trade(trade) is False
@ -3590,9 +3568,9 @@ def test_trailing_stop_loss_positive(
mocker.patch( mocker.patch(
'freqtrade.exchange.Exchange.fetch_ticker', 'freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={ MagicMock(return_value={
'bid': buy_price + 0.06, 'bid': enter_price + 0.06,
'ask': buy_price + 0.06, 'ask': enter_price + 0.06,
'last': buy_price + 0.06 'last': enter_price + 0.06
}) })
) )
# stop-loss not reached, adjusted stoploss # stop-loss not reached, adjusted stoploss
@ -3610,9 +3588,9 @@ def test_trailing_stop_loss_positive(
mocker.patch( mocker.patch(
'freqtrade.exchange.Exchange.fetch_ticker', 'freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={ MagicMock(return_value={
'bid': buy_price + 0.125, 'bid': enter_price + 0.125,
'ask': buy_price + 0.125, 'ask': enter_price + 0.125,
'last': buy_price + 0.125, 'last': enter_price + 0.125,
}) })
) )
assert freqtrade.handle_trade(trade) is False assert freqtrade.handle_trade(trade) is False
@ -3625,23 +3603,23 @@ def test_trailing_stop_loss_positive(
mocker.patch( mocker.patch(
'freqtrade.exchange.Exchange.fetch_ticker', 'freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={ MagicMock(return_value={
'bid': buy_price + 0.02, 'bid': enter_price + 0.02,
'ask': buy_price + 0.02, 'ask': enter_price + 0.02,
'last': buy_price + 0.02 'last': enter_price + 0.02
}) })
) )
# Lower price again (but still positive) # Lower price again (but still positive)
assert freqtrade.handle_trade(trade) is True assert freqtrade.handle_trade(trade) is True
assert log_has( assert log_has(
f"ETH/USDT - HIT STOP: current price at {buy_price + 0.02:.6f}, " f"ETH/USDT - HIT STOP: current price at {enter_price + 0.02:.6f}, "
f"stoploss is {trade.stop_loss:.6f}, " f"stoploss is {trade.stop_loss:.6f}, "
f"initial stoploss was at 1.800000, trade opened at 2.000000", caplog) f"initial stoploss was at 1.800000, trade opened at 2.000000", caplog)
assert trade.sell_reason == SellType.TRAILING_STOP_LOSS.value assert trade.sell_reason == SellType.TRAILING_STOP_LOSS.value
# TODO-lev: @pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("is_short", [False, True])
def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usdt, def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_open,
limit_buy_order_usdt_open, fee, mocker) -> None: is_short, fee, mocker) -> None:
patch_RPCManager(mocker) patch_RPCManager(mocker)
patch_exchange(mocker) patch_exchange(mocker)
mocker.patch.multiple( mocker.patch.multiple(
@ -3652,7 +3630,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usd
'last': 0.00000172 'last': 0.00000172
}), }),
create_order=MagicMock(side_effect=[ create_order=MagicMock(side_effect=[
limit_buy_order_usdt_open, limit_order_open[enter_side(is_short)],
{'id': 1234553382}, {'id': 1234553382},
{'id': 1234553383} {'id': 1234553383}
]), ]),
@ -3669,7 +3647,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_buy_order_usd
freqtrade.enter_positions() freqtrade.enter_positions()
trade = Trade.query.first() trade = Trade.query.first()
trade.update(limit_buy_order_usdt) trade.update(limit_order[enter_side(is_short)])
# Sell due to min_roi_reached # Sell due to min_roi_reached
patch_get_signal(freqtrade, enter_long=True, exit_long=True) patch_get_signal(freqtrade, enter_long=True, exit_long=True)
assert freqtrade.handle_trade(trade) is True assert freqtrade.handle_trade(trade) is True
@ -3995,7 +3973,7 @@ def test_apply_fee_conditional(default_conf_usdt, fee, mocker,
]) ])
@ pytest.mark.parametrize('is_short', [False, True]) @ pytest.mark.parametrize('is_short', [False, True])
def test_order_book_depth_of_market( def test_order_book_depth_of_market(
default_conf_usdt, ticker_usdt, limit_buy_order_usdt_open, limit_buy_order_usdt, default_conf_usdt, ticker_usdt, limit_order, limit_order_open,
fee, mocker, order_book_l2, delta, is_high_delta, is_short fee, mocker, order_book_l2, delta, is_high_delta, is_short
): ):
default_conf_usdt['bid_strategy']['check_depth_of_market']['enabled'] = True default_conf_usdt['bid_strategy']['check_depth_of_market']['enabled'] = True
@ -4006,7 +3984,7 @@ def test_order_book_depth_of_market(
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
fetch_ticker=ticker_usdt, fetch_ticker=ticker_usdt,
create_order=MagicMock(return_value=limit_buy_order_usdt_open), create_order=MagicMock(return_value=limit_order_open[enter_side(is_short)]),
get_fee=fee, get_fee=fee,
) )
@ -4029,7 +4007,7 @@ def test_order_book_depth_of_market(
assert len(Trade.query.all()) == 1 assert len(Trade.query.all()) == 1
# Simulate fulfilled LIMIT_BUY order for trade # Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order_usdt) trade.update(limit_order_open[enter_side(is_short)])
assert trade.open_rate == 2.0 assert trade.open_rate == 2.0
assert whitelist == default_conf_usdt['exchange']['pair_whitelist'] assert whitelist == default_conf_usdt['exchange']['pair_whitelist']
@ -4200,15 +4178,15 @@ def test_sync_wallet_dry_run(mocker, default_conf_usdt, ticker_usdt, fee, limit_
@ pytest.mark.usefixtures("init_persistence") @ pytest.mark.usefixtures("init_persistence")
@ pytest.mark.parametrize("is_short", [False, True]) @ pytest.mark.parametrize("is_short", [False, True])
def test_cancel_all_open_orders(mocker, default_conf_usdt, fee, limit_buy_order_usdt, def test_cancel_all_open_orders(mocker, default_conf_usdt, fee, limit_order, limit_order_open,
limit_sell_order_usdt, is_short): is_short):
default_conf_usdt['cancel_open_orders_on_exit'] = True default_conf_usdt['cancel_open_orders_on_exit'] = True
mocker.patch('freqtrade.exchange.Exchange.fetch_order', mocker.patch('freqtrade.exchange.Exchange.fetch_order',
side_effect=[ side_effect=[
ExchangeError(), ExchangeError(),
limit_sell_order_usdt, limit_order[exit_side(is_short)],
limit_buy_order_usdt, limit_order_open[enter_side(is_short)],
limit_sell_order_usdt limit_order_open[exit_side(is_short)],
]) ])
buy_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_enter') buy_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_enter')
sell_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_exit') sell_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_exit')
@ -4558,4 +4536,6 @@ def test_get_valid_price(mocker, default_conf_usdt) -> None:
assert valid_price_at_min_alwd < proposed_price assert valid_price_at_min_alwd < proposed_price
# TODO-lev def test_leverage_prep() def test_leverage_prep():
# TODO-lev
return