diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index ed2ab0a61..54b89e451 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -689,7 +689,16 @@ class Exchange: # Order handling def create_order(self, pair: str, ordertype: str, side: str, amount: float, - rate: float, params: Dict = {}) -> Dict: + rate: float, time_in_force: str = 'gtc') -> Dict: + + if self._config['dry_run']: + dry_order = self.create_dry_run_order(pair, ordertype, side, amount, rate) + return dry_order + + params = self._params.copy() + if time_in_force != 'gtc' and ordertype != 'market': + params.update({'timeInForce': time_in_force}) + try: # Set the precision for amount and price(rate) as accepted by the exchange amount = self.amount_to_precision(pair, amount) @@ -720,32 +729,6 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e - def buy(self, pair: str, ordertype: str, amount: float, - rate: float, time_in_force: str) -> Dict: - - if self._config['dry_run']: - dry_order = self.create_dry_run_order(pair, ordertype, "buy", amount, rate) - return dry_order - - params = self._params.copy() - if time_in_force != 'gtc' and ordertype != 'market': - params.update({'timeInForce': time_in_force}) - - return self.create_order(pair, ordertype, 'buy', amount, rate, params) - - def sell(self, pair: str, ordertype: str, amount: float, - rate: float, time_in_force: str = 'gtc') -> Dict: - - if self._config['dry_run']: - dry_order = self.create_dry_run_order(pair, ordertype, "sell", amount, rate) - return dry_order - - params = self._params.copy() - if time_in_force != 'gtc' and ordertype != 'market': - params.update({'timeInForce': time_in_force}) - - return self.create_order(pair, ordertype, 'sell', amount, rate, params) - def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool: """ Verify stop_loss against stoploss-order value (limit or price) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index d430dbc48..25b8d154b 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -510,9 +510,9 @@ class FreqtradeBot(LoggingMixin): logger.info(f"User requested abortion of buying {pair}") return False amount = self.exchange.amount_to_precision(pair, amount) - order = self.exchange.buy(pair=pair, ordertype=order_type, - amount=amount, rate=buy_limit_requested, - time_in_force=time_in_force) + order = self.exchange.create_order(pair=pair, ordertype=order_type, side="buy", + amount=amount, rate=buy_limit_requested, + time_in_force=time_in_force) order_obj = Order.parse_from_ccxt_object(order, pair, 'buy') order_id = order['id'] order_status = order.get('status', None) @@ -1094,11 +1094,11 @@ class FreqtradeBot(LoggingMixin): try: # Execute sell and update trade record - order = self.exchange.sell(pair=trade.pair, - ordertype=order_type, - amount=amount, rate=limit, - time_in_force=time_in_force - ) + order = self.exchange.create_order(pair=trade.pair, + ordertype=order_type, side="sell", + amount=amount, rate=limit, + time_in_force=time_in_force + ) except InsufficientFundsError as e: logger.warning(f"Unable to place order {e}.") # Try to figure out what went wrong diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 02adf01c4..bacb7edbb 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1056,8 +1056,8 @@ def test_buy_dry_run(default_conf, mocker): default_conf['dry_run'] = True exchange = get_patched_exchange(mocker, default_conf) - order = exchange.buy(pair='ETH/BTC', ordertype='limit', - amount=1, rate=200, time_in_force='gtc') + order = exchange.create_order(pair='ETH/BTC', ordertype='limit', side="buy", + amount=1, rate=200, time_in_force='gtc') assert 'id' in order assert 'dry_run_buy_' in order['id'] @@ -1080,8 +1080,8 @@ def test_buy_prod(default_conf, mocker, exchange_name): mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - order = exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) assert 'id' in order assert 'info' in order @@ -1094,9 +1094,10 @@ def test_buy_prod(default_conf, mocker, exchange_name): api_mock.create_order.reset_mock() order_type = 'limit' - order = exchange.buy( + order = exchange.create_order( pair='ETH/BTC', ordertype=order_type, + side="buy", amount=1, rate=200, time_in_force=time_in_force) @@ -1110,32 +1111,32 @@ def test_buy_prod(default_conf, mocker, exchange_name): with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("Not enough funds")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.buy(pair='ETH/BTC', ordertype='limit', - amount=1, rate=200, time_in_force=time_in_force) + exchange.create_order(pair='ETH/BTC', ordertype='limit', side="buy", + amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.buy(pair='ETH/BTC', ordertype='market', - amount=1, rate=200, time_in_force=time_in_force) + exchange.create_order(pair='ETH/BTC', ordertype='market', side="buy", + amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(TemporaryError): api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("Network disconnect")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) with pytest.raises(OperationalException): api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("Unknown error")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) @pytest.mark.parametrize("exchange_name", EXCHANGES) @@ -1157,8 +1158,8 @@ def test_buy_considers_time_in_force(default_conf, mocker, exchange_name): order_type = 'limit' time_in_force = 'ioc' - order = exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) assert 'id' in order assert 'info' in order @@ -1174,8 +1175,8 @@ def test_buy_considers_time_in_force(default_conf, mocker, exchange_name): order_type = 'market' time_in_force = 'ioc' - order = exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) assert 'id' in order assert 'info' in order @@ -1193,7 +1194,8 @@ def test_sell_dry_run(default_conf, mocker): default_conf['dry_run'] = True exchange = get_patched_exchange(mocker, default_conf) - order = exchange.sell(pair='ETH/BTC', ordertype='limit', amount=1, rate=200) + order = exchange.create_order(pair='ETH/BTC', ordertype='limit', + side="sell", amount=1, rate=200) assert 'id' in order assert 'dry_run_sell_' in order['id'] @@ -1216,7 +1218,8 @@ def test_sell_prod(default_conf, mocker, exchange_name): mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - order = exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, + side="sell", amount=1, rate=200) assert 'id' in order assert 'info' in order @@ -1229,7 +1232,8 @@ def test_sell_prod(default_conf, mocker, exchange_name): api_mock.create_order.reset_mock() order_type = 'limit' - order = exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, + side="sell", amount=1, rate=200) assert api_mock.create_order.call_args[0][0] == 'ETH/BTC' assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'sell' @@ -1240,28 +1244,28 @@ def test_sell_prod(default_conf, mocker, exchange_name): with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) + exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200) with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.sell(pair='ETH/BTC', ordertype='limit', amount=1, rate=200) + exchange.create_order(pair='ETH/BTC', ordertype='limit', side="sell", amount=1, rate=200) # Market orders don't require price, so the behaviour is slightly different with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InvalidOrder("Order not found")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.sell(pair='ETH/BTC', ordertype='market', amount=1, rate=200) + exchange.create_order(pair='ETH/BTC', ordertype='market', side="sell", amount=1, rate=200) with pytest.raises(TemporaryError): api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No Connection")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) + exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200) with pytest.raises(OperationalException): api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) - exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) + exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", amount=1, rate=200) @pytest.mark.parametrize("exchange_name", EXCHANGES) @@ -1283,8 +1287,8 @@ def test_sell_considers_time_in_force(default_conf, mocker, exchange_name): order_type = 'limit' time_in_force = 'ioc' - order = exchange.sell(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", + amount=1, rate=200, time_in_force=time_in_force) assert 'id' in order assert 'info' in order @@ -1299,8 +1303,8 @@ def test_sell_considers_time_in_force(default_conf, mocker, exchange_name): order_type = 'market' time_in_force = 'ioc' - order = exchange.sell(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="sell", + amount=1, rate=200, time_in_force=time_in_force) assert 'id' in order assert 'info' in order @@ -2186,7 +2190,7 @@ def test_cancel_order_dry_run(default_conf, mocker, exchange_name): assert exchange.cancel_order(order_id='123', pair='TKN/BTC') == {} assert exchange.cancel_stoploss_order(order_id='123', pair='TKN/BTC') == {} - order = exchange.buy('ETH/BTC', 'limit', 5, 0.55, 'gtc') + order = exchange.create_order('ETH/BTC', 'limit', "sell", 5, 0.55, 'gtc') cancel_order = exchange.cancel_order(order_id=order['id'], pair='ETH/BTC') assert order['id'] == cancel_order['id'] diff --git a/tests/exchange/test_kraken.py b/tests/exchange/test_kraken.py index ed22cde92..eb79dfc10 100644 --- a/tests/exchange/test_kraken.py +++ b/tests/exchange/test_kraken.py @@ -31,8 +31,8 @@ def test_buy_kraken_trading_agreement(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken") - order = exchange.buy(pair='ETH/BTC', ordertype=order_type, - amount=1, rate=200, time_in_force=time_in_force) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, side="buy", + amount=1, rate=200, time_in_force=time_in_force) assert 'id' in order assert 'info' in order @@ -63,7 +63,8 @@ def test_sell_kraken_trading_agreement(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken") - order = exchange.sell(pair='ETH/BTC', ordertype=order_type, amount=1, rate=200) + order = exchange.create_order(pair='ETH/BTC', ordertype=order_type, + side="sell", amount=1, rate=200) assert 'id' in order assert 'info' in order diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index fad24f9e2..05a4316f8 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -857,7 +857,7 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order_open) -> get_balances=MagicMock(return_value=ticker), fetch_ticker=ticker, get_fee=fee, - buy=buy_mm + create_order=buy_mm ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 4912a2a4d..31e3a4ff7 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -169,7 +169,7 @@ def test_check_available_stake_amount(default_conf, ticker, mocker, fee, limit_b mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee ) default_conf['dry_run_wallet'] = wallet @@ -384,7 +384,7 @@ def test_create_trade_minimal_amount(default_conf, ticker, limit_buy_order_open, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=buy_mock, + create_order=buy_mock, get_fee=fee, ) default_conf['stake_amount'] = 0.0005 @@ -404,7 +404,7 @@ def test_create_trade_too_small_stake_amount(default_conf, ticker, limit_buy_ord mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=buy_mock, + create_order=buy_mock, get_fee=fee, ) @@ -425,7 +425,7 @@ def test_create_trade_zero_stake_amount(default_conf, ticker, limit_buy_order_op mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=buy_mock, + create_order=buy_mock, get_fee=fee, ) @@ -444,7 +444,7 @@ def test_create_trade_limit_reached(default_conf, ticker, limit_buy_order_open, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) default_conf['max_open_trades'] = 0 @@ -464,7 +464,7 @@ def test_enter_positions_no_pairs_left(default_conf, ticker, limit_buy_order_ope mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) @@ -487,7 +487,7 @@ def test_enter_positions_no_pairs_in_whitelist(default_conf, ticker, limit_buy_o mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value={'id': limit_buy_order['id']}), + create_order=MagicMock(return_value={'id': limit_buy_order['id']}), get_fee=fee, ) default_conf['exchange']['pair_whitelist'] = [] @@ -507,7 +507,7 @@ def test_enter_positions_global_pairlock(default_conf, ticker, limit_buy_order, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value={'id': limit_buy_order['id']}), + create_order=MagicMock(return_value={'id': limit_buy_order['id']}), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf) @@ -556,7 +556,7 @@ def test_create_trades_multiple_trades(default_conf, ticker, fee, mocker, limit_ mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf) @@ -577,7 +577,7 @@ def test_create_trades_preopen(default_conf, ticker, fee, mocker, limit_buy_orde mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf) @@ -606,7 +606,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, limit_buy mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), fetch_order=MagicMock(return_value=limit_buy_order), get_fee=fee, ) @@ -641,7 +641,7 @@ def test_process_exchange_failures(default_conf, ticker, mocker) -> None: mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(side_effect=TemporaryError) + create_order=MagicMock(side_effect=TemporaryError) ) sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None) @@ -658,7 +658,7 @@ def test_process_operational_exception(default_conf, ticker, mocker) -> None: mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(side_effect=OperationalException) + create_order=MagicMock(side_effect=OperationalException) ) worker = Worker(args=None, config=default_conf) patch_get_signal(worker.freqtrade) @@ -676,7 +676,7 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order_open, fee, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), fetch_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) @@ -703,7 +703,7 @@ def test_process_trade_no_whitelist_pair(default_conf, ticker, limit_buy_order, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value={'id': limit_buy_order['id']}), + create_order=MagicMock(return_value={'id': limit_buy_order['id']}), fetch_order=MagicMock(return_value=limit_buy_order), get_fee=fee, ) @@ -753,7 +753,7 @@ def test_process_informative_pairs_added(default_conf, ticker, mocker) -> None: mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(side_effect=TemporaryError), + create_order=MagicMock(side_effect=TemporaryError), refresh_latest_ohlcv=refresh_mock, ) inf_pairs = MagicMock(return_value=[("BTC/ETH", '1m'), ("ETH/USDT", "1h")]) @@ -790,7 +790,7 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order 'ask': 0.00001173, 'last': 0.00001172 }), - buy=buy_mm, + create_order=buy_mm, get_min_pair_stake_amount=MagicMock(return_value=1), get_fee=fee, ) @@ -839,7 +839,8 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order limit_buy_order['cost'] = 100 limit_buy_order['id'] = '444' - mocker.patch('freqtrade.exchange.Exchange.buy', MagicMock(return_value=limit_buy_order)) + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=limit_buy_order)) assert freqtrade.execute_buy(pair, stake_amount) trade = Trade.query.all()[2] assert trade @@ -855,7 +856,8 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order limit_buy_order['price'] = 0.5 limit_buy_order['cost'] = 40.495905365 limit_buy_order['id'] = '555' - mocker.patch('freqtrade.exchange.Exchange.buy', MagicMock(return_value=limit_buy_order)) + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=limit_buy_order)) assert freqtrade.execute_buy(pair, stake_amount) trade = Trade.query.all()[3] assert trade @@ -889,7 +891,8 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order limit_buy_order['price'] = 0.5 limit_buy_order['cost'] = 0.0 limit_buy_order['id'] = '66' - mocker.patch('freqtrade.exchange.Exchange.buy', MagicMock(return_value=limit_buy_order)) + mocker.patch('freqtrade.exchange.Exchange.create_order', + MagicMock(return_value=limit_buy_order)) assert not freqtrade.execute_buy(pair, stake_amount) # Fail to get price... @@ -908,7 +911,7 @@ def test_execute_buy_confirm_error(mocker, default_conf, fee, limit_buy_order) - 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value=limit_buy_order), + create_order=MagicMock(return_value=limit_buy_order), get_rate=MagicMock(return_value=0.11), get_min_pair_stake_amount=MagicMock(return_value=1), get_fee=fee, @@ -970,8 +973,10 @@ def test_handle_stoploss_on_exchange(mocker, default_conf, fee, caplog, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value={'id': limit_buy_order['id']}), - sell=MagicMock(return_value={'id': limit_sell_order['id']}), + create_order=MagicMock(side_effect=[ + {'id': limit_buy_order['id']}, + {'id': limit_sell_order['id']}, + ]), get_fee=fee, ) mocker.patch.multiple( @@ -1087,8 +1092,10 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf, fee, caplog, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value={'id': limit_buy_order['id']}), - sell=MagicMock(return_value={'id': limit_sell_order['id']}), + create_order=MagicMock(side_effect=[ + {'id': limit_buy_order['id']}, + {'id': limit_sell_order['id']}, + ]), get_fee=fee, ) mocker.patch.multiple( @@ -1116,7 +1123,10 @@ def test_create_stoploss_order_invalid_order(mocker, default_conf, caplog, fee, limit_buy_order_open, limit_sell_order): rpc_mock = patch_RPCManager(mocker) patch_exchange(mocker) - sell_mock = MagicMock(return_value={'id': limit_sell_order['id']}) + create_order_mock = MagicMock(side_effect=[ + limit_buy_order_open, + {'id': limit_sell_order['id']} + ]) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=MagicMock(return_value={ @@ -1124,8 +1134,7 @@ def test_create_stoploss_order_invalid_order(mocker, default_conf, caplog, fee, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value=limit_buy_order_open), - sell=sell_mock, + create_order=create_order_mock, get_fee=fee, ) mocker.patch.multiple( @@ -1147,10 +1156,10 @@ def test_create_stoploss_order_invalid_order(mocker, default_conf, caplog, fee, assert log_has("Selling the trade forcefully", caplog) # Should call a market sell - assert sell_mock.call_count == 1 - assert sell_mock.call_args[1]['ordertype'] == 'market' - assert sell_mock.call_args[1]['pair'] == trade.pair - assert sell_mock.call_args[1]['amount'] == trade.amount + assert create_order_mock.call_count == 2 + assert create_order_mock.call_args[1]['ordertype'] == 'market' + assert create_order_mock.call_args[1]['pair'] == trade.pair + assert create_order_mock.call_args[1]['amount'] == trade.amount # Rpc is sending first buy, then sell assert rpc_mock.call_count == 2 @@ -1171,8 +1180,10 @@ def test_create_stoploss_order_insufficient_funds(mocker, default_conf, caplog, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value=limit_buy_order_open), - sell=sell_mock, + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + sell_mock, + ]), get_fee=fee, fetch_order=MagicMock(return_value={'status': 'canceled'}), ) @@ -1212,8 +1223,10 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value={'id': limit_buy_order['id']}), - sell=MagicMock(return_value={'id': limit_sell_order['id']}), + create_order=MagicMock(side_effect=[ + {'id': limit_buy_order['id']}, + {'id': limit_sell_order['id']}, + ]), get_fee=fee, ) mocker.patch.multiple( @@ -1318,8 +1331,10 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value={'id': limit_buy_order['id']}), - sell=MagicMock(return_value={'id': limit_sell_order['id']}), + create_order=MagicMock(side_effect=[ + {'id': limit_buy_order['id']}, + {'id': limit_sell_order['id']}, + ]), get_fee=fee, ) mocker.patch.multiple( @@ -1391,8 +1406,10 @@ def test_handle_stoploss_on_exchange_custom_stop(mocker, default_conf, fee, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value={'id': limit_buy_order['id']}), - sell=MagicMock(return_value={'id': limit_sell_order['id']}), + create_order=MagicMock(side_effect=[ + {'id': limit_buy_order['id']}, + {'id': limit_sell_order['id']}, + ]), get_fee=fee, ) mocker.patch.multiple( @@ -1502,8 +1519,10 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog, 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value={'id': limit_buy_order['id']}), - sell=MagicMock(return_value={'id': limit_sell_order['id']}), + create_order=MagicMock(side_effect=[ + {'id': limit_buy_order['id']}, + {'id': limit_sell_order['id']}, + ]), get_fee=fee, stoploss=stoploss, ) @@ -1840,8 +1859,10 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order_open, limi 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value=limit_buy_order), - sell=MagicMock(return_value=limit_sell_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order, + limit_sell_order_open, + ]), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf) @@ -1877,7 +1898,10 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) @@ -1930,7 +1954,10 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) @@ -1954,15 +1981,18 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open, caplog) -def test_handle_trade_use_sell_signal( - default_conf, ticker, limit_buy_order_open, fee, mocker, caplog) -> None: +def test_handle_trade_use_sell_signal(default_conf, ticker, limit_buy_order_open, + limit_sell_order_open, fee, mocker, caplog) -> None: # use_sell_signal is True buy default caplog.set_level(logging.DEBUG) patch_RPCManager(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + limit_sell_order_open, + ]), get_fee=fee, ) @@ -1990,7 +2020,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_buy_order_open mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf) @@ -2746,13 +2776,16 @@ def test_execute_sell_sloe_cancel_exception(mocker, default_conf, ticker, fee, c mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order', side_effect=InvalidOrderException()) mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=300)) - sellmock = MagicMock(return_value={'id': '12345555'}) + create_order_mock = MagicMock(side_effect=[ + {'id': '12345554'}, + {'id': '12345555'}, + ]) patch_exchange(mocker) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, get_fee=fee, - sell=sellmock + create_order=create_order_mock, ) freqtrade.strategy.order_types['stoploss_on_exchange'] = True @@ -2767,7 +2800,7 @@ def test_execute_sell_sloe_cancel_exception(mocker, default_conf, ticker, fee, c freqtrade.execute_sell(trade=trade, limit=1234, sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS)) - assert sellmock.call_count == 1 + assert create_order_mock.call_count == 2 assert log_has('Could not cancel stoploss order abcd', caplog) @@ -2963,7 +2996,10 @@ def test_execute_sell_insufficient_funds_error(default_conf, ticker, fee, 'freqtrade.exchange.Exchange', fetch_ticker=ticker, get_fee=fee, - sell=MagicMock(side_effect=InsufficientFundsError()) + create_order=MagicMock(side_effect=[ + {'id': 1234553382}, + InsufficientFundsError(), + ]), ) patch_get_signal(freqtrade) @@ -2996,7 +3032,10 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, limit_buy 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf.update({ @@ -3033,7 +3072,10 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, limit_bu 'ask': 0.00002173, 'last': 0.00002172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf.update({ @@ -3064,7 +3106,10 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, limit_buy_o 'ask': 0.00000173, 'last': 0.00000172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf.update({ @@ -3094,7 +3139,10 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, limit_buy_ 'ask': 0.0000173, 'last': 0.0000172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf.update({ @@ -3127,7 +3175,10 @@ def test_sell_not_enough_balance(default_conf, limit_buy_order, limit_buy_order_ 'ask': 0.00002173, 'last': 0.00002172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) @@ -3245,7 +3296,10 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, limit_buy_order 'ask': 0.0000173, 'last': 0.0000172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf['ignore_roi_if_buy_signal'] = True @@ -3279,7 +3333,10 @@ def test_trailing_stop_loss(default_conf, limit_buy_order_open, limit_buy_order, 'ask': 0.00001099, 'last': 0.00001099 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf['trailing_stop'] = True @@ -3331,7 +3388,10 @@ def test_trailing_stop_loss_positive(default_conf, limit_buy_order, limit_buy_or 'ask': buy_price - 0.000001, 'last': buy_price - 0.000001 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) default_conf['trailing_stop'] = True @@ -3388,7 +3448,10 @@ def test_trailing_stop_loss_offset(default_conf, limit_buy_order, limit_buy_orde 'ask': buy_price - 0.000001, 'last': buy_price - 0.000001 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + ]), get_fee=fee, ) patch_whitelist(mocker, default_conf) @@ -3448,7 +3511,7 @@ def test_tsl_only_offset_reached(default_conf, limit_buy_order, limit_buy_order_ 'ask': buy_price, 'last': buy_price }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) patch_whitelist(mocker, default_conf) @@ -3508,7 +3571,11 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order, limit_b 'ask': 0.00000173, 'last': 0.00000172 }), - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + {'id': 1234553382}, + {'id': 1234553383} + ]), get_fee=fee, _is_dry_limit_order_filled=MagicMock(return_value=False), ) @@ -3905,7 +3972,7 @@ def test_order_book_depth_of_market(default_conf, ticker, limit_buy_order_open, mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) @@ -3942,7 +4009,7 @@ def test_order_book_depth_of_market_high_delta(default_conf, ticker, limit_buy_o mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value={'id': limit_buy_order['id']}), + create_order=MagicMock(return_value={'id': limit_buy_order['id']}), get_fee=fee, ) # Save state of current whitelist @@ -4039,8 +4106,10 @@ def test_order_book_ask_strategy(default_conf, limit_buy_order_open, limit_buy_o 'ask': 0.00001173, 'last': 0.00001172 }), - buy=MagicMock(return_value=limit_buy_order_open), - sell=MagicMock(return_value=limit_sell_order_open), + create_order=MagicMock(side_effect=[ + limit_buy_order_open, + limit_sell_order_open, + ]), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf) @@ -4105,7 +4174,7 @@ def test_sync_wallet_dry_run(mocker, default_conf, ticker, fee, limit_buy_order_ mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee, ) diff --git a/tests/test_wallets.py b/tests/test_wallets.py index 64db3b9cd..9f58cb71d 100644 --- a/tests/test_wallets.py +++ b/tests/test_wallets.py @@ -125,7 +125,7 @@ def test_get_trade_stake_amount_no_stake_amount(default_conf, mocker) -> None: (1, None, 50, 66.66666), (0.99, None, 49.5, 66.0), (0.50, None, 25, 33.3333), - # Tests with capital ignore balance_ratio + # Tests with capital ignore balance_ratio (1, 100, 50, 0.0), (0.99, 200, 50, 66.66666), (0.99, 150, 50, 50), @@ -138,7 +138,7 @@ def test_get_trade_stake_amount_unlimited_amount(default_conf, ticker, balance_r mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, - buy=MagicMock(return_value=limit_buy_order_open), + create_order=MagicMock(return_value=limit_buy_order_open), get_fee=fee )