From bd00f6de174f3d9f96e7980c71917d4901123073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=AE=AE=E0=AE=A9=E0=AF=8B=E0=AE=9C=E0=AF=8D=E0=AE=95?= =?UTF-8?q?=E0=AF=81=E0=AE=AE=E0=AE=BE=E0=AE=B0=E0=AF=8D=20=E0=AE=AA?= =?UTF-8?q?=E0=AE=B4=E0=AE=A9=E0=AE=BF=E0=AE=9A=E0=AF=8D=E0=AE=9A=E0=AE=BE?= =?UTF-8?q?=E0=AE=AE=E0=AE=BF?= Date: Mon, 28 Mar 2022 20:36:58 +0530 Subject: [PATCH] updated requested changes in PR #6545 --- freqtrade/exchange/exchange.py | 3 +- freqtrade/freqtradebot.py | 22 +++---- freqtrade/optimize/backtesting.py | 39 ++++++----- freqtrade/strategy/interface.py | 4 +- freqtrade/wallets.py | 2 +- tests/exchange/test_exchange.py | 104 +++++++++++++++--------------- tests/rpc/test_rpc_telegram.py | 15 ++--- tests/test_freqtradebot.py | 66 +++++++------------ tests/test_persistence.py | 4 +- 9 files changed, 118 insertions(+), 141 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index ebafbce4b..403369a9a 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1181,7 +1181,8 @@ class Exchange: buy_rate = None sell_rate = None if not refresh: - buy_rate, sell_rate = self._buy_rate_cache.get(pair), self._sell_rate_cache.get(pair) + buy_rate = self._buy_rate_cache.get(pair) + sell_rate = self._sell_rate_cache.get(pair) if buy_rate: logger.debug(f"Using cached buy rate for {pair}.") if sell_rate: diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index d0fa5e101..bae6c94ab 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -485,7 +485,7 @@ class FreqtradeBot(LoggingMixin): return else: logger.debug("Max adjustment entries is set to unlimited.") - self.execute_entry(trade.pair, stake_amount, trade=trade) + self.execute_entry(trade.pair, stake_amount, current_entry_rate, trade=trade) if stake_amount is not None and stake_amount < 0.0: # We should decrease our position @@ -631,10 +631,6 @@ class FreqtradeBot(LoggingMixin): trade.open_order_id = order_id trade.orders.append(order_obj) - if pos_adjust: - trade.recalc_trade_from_orders() - else: - trade.recalc_open_trade_value() Trade.query.session.add(trade) Trade.commit() @@ -1142,16 +1138,18 @@ class FreqtradeBot(LoggingMixin): trade.open_order_id = None trade.sell_reason = None cancelled = True + self.wallets.update() else: # TODO: figure out how to handle partially complete sell orders reason = constants.CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN'] cancelled = False - self.wallets.update() + order_obj = Order.parse_from_ccxt_object(order, trade.pair, 'sell') + sub_trade = order_obj.amount != trade.amount self._notify_exit_cancel( trade, order_type=self.strategy.order_types['sell'], - reason=reason + reason=reason, sub_trade=sub_trade, order=order_obj ) return cancelled @@ -1189,7 +1187,7 @@ class FreqtradeBot(LoggingMixin): exit_tag: Optional[str] = None, ordertype: Optional[str] = None, sub_trade_amt: float = None, - ) -> bool: + ) -> bool: """ Executes a trade exit for the given trade and limit :param trade: Trade instance @@ -1279,7 +1277,7 @@ class FreqtradeBot(LoggingMixin): current_rate = self.exchange.get_rate( trade.pair, refresh=False, side="sell") if not fill else None - # second condtion is for mypy only; order will always be passed during sub trade + # second condition is for mypy only; order will always be passed during sub trade if sub_trade and order is not None: amount = order.safe_filled profit_rate = order.safe_price @@ -1327,7 +1325,7 @@ class FreqtradeBot(LoggingMixin): self.rpc.send_msg(msg) def _notify_exit_cancel(self, trade: Trade, order_type: str, reason: str, - sub_trade: bool = False) -> None: + sub_trade: bool = False, order: Order=None) -> None: """ Sends rpc notification when a sell cancel occurred. """ @@ -1350,7 +1348,7 @@ class FreqtradeBot(LoggingMixin): 'gain': gain, 'limit': profit_rate or 0, 'order_type': order_type, - 'amount': trade.amount, + 'amount': order.safe_amount_after_fee, 'open_rate': trade.open_rate, 'current_rate': current_rate, 'profit_amount': profit_trade, @@ -1419,7 +1417,7 @@ class FreqtradeBot(LoggingMixin): trade.update_trade(order_obj) Trade.commit() - if order['status'] in constants.NON_OPEN_EXCHANGE_STATES: + if order.get('status') in constants.NON_OPEN_EXCHANGE_STATES: # If a buy order was closed, force update on stoploss on exchange if order.get('side', None) == 'buy': trade = self.cancel_stoploss_on_exchange(trade) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 5faf1a25b..add1609f7 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -383,8 +383,7 @@ class Backtesting: def _get_adjust_trade_entry_for_candle(self, trade: LocalTrade, row: Tuple ) -> LocalTrade: - current_entry_rate = current_exit_rate = row[OPEN_IDX] - current_rate = current_entry_rate + current_rate = row[OPEN_IDX] current_profit = trade.calc_profit_ratio(current_rate) min_stake = self.exchange.get_min_pair_stake_amount(trade.pair, current_rate, -0.1) @@ -393,7 +392,7 @@ class Backtesting: default_retval=None)( trade=trade, current_time=row[DATE_IDX].to_pydatetime(), current_rate=current_rate, current_profit=current_profit, min_stake=min_stake, max_stake=max_stake, - current_entry_rate=current_entry_rate, current_exit_rate=current_exit_rate) + current_entry_rate=current_rate, current_exit_rate=current_rate) # Check if we should increase our position if stake_amount is not None and stake_amount > 0.0: @@ -403,9 +402,8 @@ class Backtesting: return pos_trade if stake_amount is not None and stake_amount < 0.0: - amount = -stake_amount / current_rate + amount = abs(stake_amount) / current_rate if amount > trade.amount: - logger.info(f"Amount is higher than available. {amount} > {trade.amount}") return trade pos_trade = self._exit_trade(trade, row, current_rate, amount) if pos_trade is not None: @@ -441,29 +439,29 @@ class Backtesting: trade_dur = int((trade.close_date_utc - trade.open_date_utc).total_seconds() // 60) try: - closerate = self._get_close_rate(sell_row, trade, sell, trade_dur) + close_rate = self._get_close_rate(sell_row, trade, sell, trade_dur) except ValueError: return None - # call the custom exit price,with default value as previous closerate - current_profit = trade.calc_profit_ratio(closerate) + # call the custom exit price,with default value as previous close_rate + current_profit = trade.calc_profit_ratio(close_rate) order_type = self.strategy.order_types['sell'] if sell.sell_type in (SellType.SELL_SIGNAL, SellType.CUSTOM_SELL): # Custom exit pricing only for sell-signals if order_type == 'limit': - closerate = strategy_safe_wrapper(self.strategy.custom_exit_price, - default_retval=closerate)( + close_rate = strategy_safe_wrapper(self.strategy.custom_exit_price, + default_retval=close_rate)( pair=trade.pair, trade=trade, current_time=sell_candle_time, - proposed_rate=closerate, current_profit=current_profit) + proposed_rate=close_rate, current_profit=current_profit) # We can't place orders lower than current low. # freqtrade does not support this in live, and the order would fill immediately - closerate = max(closerate, sell_row[LOW_IDX]) + close_rate = max(close_rate, sell_row[LOW_IDX]) # Confirm trade exit: time_in_force = self.strategy.order_time_in_force['sell'] if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, order_type='limit', amount=trade.amount, - rate=closerate, + rate=close_rate, time_in_force=time_in_force, sell_reason=sell.sell_reason, current_time=sell_candle_time): @@ -480,15 +478,16 @@ class Backtesting: ): trade.sell_reason = sell_row[EXIT_TAG_IDX] - return self._exit_trade(trade, sell_row, closerate) + return self._exit_trade(trade, sell_row, close_rate) return None def _exit_trade(self, trade: LocalTrade, sell_row: Tuple, - closerate: float, amount: float = None) -> Optional[LocalTrade]: + close_rate: float, amount: float = None) -> Optional[LocalTrade]: self.order_id_counter += 1 sell_candle_time = sell_row[DATE_IDX].to_pydatetime() order_type = self.strategy.order_types['sell'] + amount = amount or trade.amount order = Order( id=self.order_id_counter, ft_trade_id=trade.id, @@ -502,12 +501,12 @@ class Backtesting: side="sell", order_type=order_type, status="open", - price=closerate, - average=closerate, - amount=amount or trade.amount, + price=close_rate, + average=close_rate, + amount=amount, filled=0, - remaining=trade.amount, - cost=trade.amount * closerate, + remaining=amount, + cost=amount * close_rate, ) trade.orders.append(order) return trade diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 1eea84676..1e5d9f747 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -882,8 +882,8 @@ class IStrategy(ABC, HyperStrategyMixin): return strategy_safe_wrapper(time_method, default_retval=False)( - pair=trade.pair, trade=trade, order=order, - current_time=current_time) + pair=trade.pair, trade=trade, order=order, + current_time=current_time) def advise_all_indicators(self, data: Dict[str, DataFrame]) -> Dict[str, DataFrame]: """ diff --git a/freqtrade/wallets.py b/freqtrade/wallets.py index 93f3d3800..b9d661e6d 100644 --- a/freqtrade/wallets.py +++ b/freqtrade/wallets.py @@ -249,7 +249,7 @@ class Wallets: if min_stake_amount is not None and min_stake_amount > max_stake_amount: if self._log: - logger.warning("Minimum stake amount > available balance.") + logger.warning(f"Minimum stake amount > available balance.{min_stake_amount} > {max_stake_amount}") return 0 if min_stake_amount is not None and stake_amount < min_stake_amount: if self._log: diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index de8caede9..f3cb04d41 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -26,6 +26,54 @@ from tests.conftest import get_mock_coro, get_patched_exchange, log_has, log_has # Make sure to always keep one exchange here which is NOT subclassed!! EXCHANGES = ['bittrex', 'binance', 'kraken', 'ftx'] +get_buy_rate_data = [ + ('ask', 20, 19, 10, 0.0, 20), # Full ask side + ('ask', 20, 19, 10, 1.0, 10), # Full last side + ('ask', 20, 19, 10, 0.5, 15), # Between ask and last + ('ask', 20, 19, 10, 0.7, 13), # Between ask and last + ('ask', 20, 19, 10, 0.3, 17), # Between ask and last + ('ask', 5, 6, 10, 1.0, 5), # last bigger than ask + ('ask', 5, 6, 10, 0.5, 5), # last bigger than ask + ('ask', 20, 19, 10, None, 20), # ask_last_balance missing + ('ask', 10, 20, None, 0.5, 10), # last not available - uses ask + ('ask', 4, 5, None, 0.5, 4), # last not available - uses ask + ('ask', 4, 5, None, 1, 4), # last not available - uses ask + ('ask', 4, 5, None, 0, 4), # last not available - uses ask + ('bid', 21, 20, 10, 0.0, 20), # Full bid side + ('bid', 21, 20, 10, 1.0, 10), # Full last side + ('bid', 21, 20, 10, 0.5, 15), # Between bid and last + ('bid', 21, 20, 10, 0.7, 13), # Between bid and last + ('bid', 21, 20, 10, 0.3, 17), # Between bid and last + ('bid', 6, 5, 10, 1.0, 5), # last bigger than bid + ('bid', 21, 20, 10, None, 20), # ask_last_balance missing + ('bid', 6, 5, 10, 0.5, 5), # last bigger than bid + ('bid', 21, 20, None, 0.5, 20), # last not available - uses bid + ('bid', 6, 5, None, 0.5, 5), # last not available - uses bid + ('bid', 6, 5, None, 1, 5), # last not available - uses bid + ('bid', 6, 5, None, 0, 5), # last not available - uses bid +] + +get_sell_rate_data = [ + ('bid', 12.0, 11.0, 11.5, 0.0, 11.0), # full bid side + ('bid', 12.0, 11.0, 11.5, 1.0, 11.5), # full last side + ('bid', 12.0, 11.0, 11.5, 0.5, 11.25), # between bid and lat + ('bid', 12.0, 11.2, 10.5, 0.0, 11.2), # Last smaller than bid + ('bid', 12.0, 11.2, 10.5, 1.0, 11.2), # Last smaller than bid - uses bid + ('bid', 12.0, 11.2, 10.5, 0.5, 11.2), # Last smaller than bid - uses bid + ('bid', 0.003, 0.002, 0.005, 0.0, 0.002), + ('bid', 0.003, 0.002, 0.005, None, 0.002), + ('ask', 12.0, 11.0, 12.5, 0.0, 12.0), # full ask side + ('ask', 12.0, 11.0, 12.5, 1.0, 12.5), # full last side + ('ask', 12.0, 11.0, 12.5, 0.5, 12.25), # between bid and lat + ('ask', 12.2, 11.2, 10.5, 0.0, 12.2), # Last smaller than ask + ('ask', 12.0, 11.0, 10.5, 1.0, 12.0), # Last smaller than ask - uses ask + ('ask', 12.0, 11.2, 10.5, 0.5, 12.0), # Last smaller than ask - uses ask + ('ask', 10.0, 11.0, 11.0, 0.0, 10.0), + ('ask', 10.11, 11.2, 11.0, 0.0, 10.11), + ('ask', 0.001, 0.002, 11.0, 0.0, 0.001), + ('ask', 0.006, 1.0, 11.0, 0.0, 0.006), + ('ask', 0.006, 1.0, 11.0, None, 0.006), +] def ccxt_exceptionhandlers(mocker, default_conf, api_mock, exchange_name, fun, mock_ccxt_fun, retries=API_RETRY_COUNT + 1, **kwargs): @@ -1903,33 +1951,6 @@ def test_fetch_l2_order_book_exception(default_conf, mocker, exchange_name): exchange.fetch_l2_order_book(pair='ETH/BTC', limit=50) -get_buy_rate_data = [ - ('ask', 20, 19, 10, 0.0, 20), # Full ask side - ('ask', 20, 19, 10, 1.0, 10), # Full last side - ('ask', 20, 19, 10, 0.5, 15), # Between ask and last - ('ask', 20, 19, 10, 0.7, 13), # Between ask and last - ('ask', 20, 19, 10, 0.3, 17), # Between ask and last - ('ask', 5, 6, 10, 1.0, 5), # last bigger than ask - ('ask', 5, 6, 10, 0.5, 5), # last bigger than ask - ('ask', 20, 19, 10, None, 20), # ask_last_balance missing - ('ask', 10, 20, None, 0.5, 10), # last not available - uses ask - ('ask', 4, 5, None, 0.5, 4), # last not available - uses ask - ('ask', 4, 5, None, 1, 4), # last not available - uses ask - ('ask', 4, 5, None, 0, 4), # last not available - uses ask - ('bid', 21, 20, 10, 0.0, 20), # Full bid side - ('bid', 21, 20, 10, 1.0, 10), # Full last side - ('bid', 21, 20, 10, 0.5, 15), # Between bid and last - ('bid', 21, 20, 10, 0.7, 13), # Between bid and last - ('bid', 21, 20, 10, 0.3, 17), # Between bid and last - ('bid', 6, 5, 10, 1.0, 5), # last bigger than bid - ('bid', 21, 20, 10, None, 20), # ask_last_balance missing - ('bid', 6, 5, 10, 0.5, 5), # last bigger than bid - ('bid', 21, 20, None, 0.5, 20), # last not available - uses bid - ('bid', 6, 5, None, 0.5, 5), # last not available - uses bid - ('bid', 6, 5, None, 1, 5), # last not available - uses bid - ('bid', 6, 5, None, 0, 5), # last not available - uses bid -] - @pytest.mark.parametrize("side,ask,bid,last,last_ab,expected", get_buy_rate_data) def test_get_buy_rate(mocker, default_conf, caplog, side, ask, bid, @@ -1955,29 +1976,6 @@ def test_get_buy_rate(mocker, default_conf, caplog, side, ask, bid, assert not log_has("Using cached buy rate for ETH/BTC.", caplog) -get_sell_rate_data = [ - ('bid', 12.0, 11.0, 11.5, 0.0, 11.0), # full bid side - ('bid', 12.0, 11.0, 11.5, 1.0, 11.5), # full last side - ('bid', 12.0, 11.0, 11.5, 0.5, 11.25), # between bid and lat - ('bid', 12.0, 11.2, 10.5, 0.0, 11.2), # Last smaller than bid - ('bid', 12.0, 11.2, 10.5, 1.0, 11.2), # Last smaller than bid - uses bid - ('bid', 12.0, 11.2, 10.5, 0.5, 11.2), # Last smaller than bid - uses bid - ('bid', 0.003, 0.002, 0.005, 0.0, 0.002), - ('bid', 0.003, 0.002, 0.005, None, 0.002), - ('ask', 12.0, 11.0, 12.5, 0.0, 12.0), # full ask side - ('ask', 12.0, 11.0, 12.5, 1.0, 12.5), # full last side - ('ask', 12.0, 11.0, 12.5, 0.5, 12.25), # between bid and lat - ('ask', 12.2, 11.2, 10.5, 0.0, 12.2), # Last smaller than ask - ('ask', 12.0, 11.0, 10.5, 1.0, 12.0), # Last smaller than ask - uses ask - ('ask', 12.0, 11.2, 10.5, 0.5, 12.0), # Last smaller than ask - uses ask - ('ask', 10.0, 11.0, 11.0, 0.0, 10.0), - ('ask', 10.11, 11.2, 11.0, 0.0, 10.11), - ('ask', 0.001, 0.002, 11.0, 0.0, 0.001), - ('ask', 0.006, 1.0, 11.0, 0.0, 0.006), - ('ask', 0.006, 1.0, 11.0, None, 0.006), -] - - @pytest.mark.parametrize('side,ask,bid,last,last_ab,expected', get_sell_rate_data) def test_get_sell_rate(default_conf, mocker, caplog, side, bid, ask, last, last_ab, expected) -> None: @@ -2108,7 +2106,7 @@ def test_get_rates_testing_buy(mocker, default_conf, caplog, side, ask, bid, api_mock = MagicMock() api_mock.fetch_l2_order_book = order_book_l2 api_mock.fetch_ticker = MagicMock( - return_value={'ask': ask, 'last': last, 'bid': bid}) + return_value={'ask': ask, 'last': last, 'bid': bid}) exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.get_rates('ETH/BTC', refresh=True)[0] == expected @@ -2148,12 +2146,12 @@ def test_get_rates_testing_sell(default_conf, mocker, caplog, side, bid, ask, pair = "ETH/BTC" # Test regular mode - rate = exchange.get_rate(pair, refresh=True, side="sell") + rate = exchange.get_rates(pair, refresh=True)[1] assert not log_has("Using cached sell rate for ETH/BTC.", caplog) assert isinstance(rate, float) assert rate == expected # Use caching - rate = exchange.get_rate(pair, refresh=False, side="sell") + rate = exchange.get_rates(pair, refresh=False)[1] assert rate == expected assert log_has("Using cached sell rate for ETH/BTC.", caplog) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 8466c17a1..196100d68 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -467,9 +467,8 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee, trades = Trade.query.all() for trade in trades: - trade.open_rate = oobj.safe_price - trade.amount = oobj.safe_amount_after_fee - trade.recalc_open_trade_value() + trade.orders[0] = oobj + trade.update_trade(oobj) trade.update_trade(oobjs) trade.close_date = datetime.utcnow() trade.is_open = False @@ -586,9 +585,8 @@ def test_weekly_handle(default_conf, update, ticker, limit_buy_order, fee, trades = Trade.query.all() for trade in trades: - trade.open_rate = oobj.safe_price - trade.amount = oobj.safe_amount_after_fee - trade.recalc_open_trade_value() + trade.orders[0] = oobj + trade.update_trade(oobj) trade.update_trade(oobjs) trade.close_date = datetime.utcnow() trade.is_open = False @@ -708,9 +706,8 @@ def test_monthly_handle(default_conf, update, ticker, limit_buy_order, fee, trades = Trade.query.all() for trade in trades: - trade.open_rate = oobj.safe_price - trade.amount = oobj.safe_amount_after_fee - trade.recalc_open_trade_value() + trade.orders[0] = oobj + trade.update_trade(oobj) trade.update_trade(oobjs) trade.close_date = datetime.utcnow() trade.is_open = False diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 352fc67b5..4ef57afb1 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2075,9 +2075,9 @@ def test_check_handle_timedout_buy_usercustom(default_conf_usdt, ticker_usdt, li default_conf_usdt["unfilledtimeout"] = {"buy": 1400, "sell": 30} limit_buy_order_old['id'] = open_trade.open_order_id rpc_mock = patch_RPCManager(mocker) - cancel_order_mock = MagicMock(return_value=limit_buy_order_old) cancel_buy_order = deepcopy(limit_buy_order_old) cancel_buy_order['status'] = 'canceled' + cancel_order_mock = MagicMock(return_value=limit_buy_order_old) cancel_order_wr_mock = MagicMock(return_value=cancel_buy_order) patch_exchange(mocker) @@ -2085,8 +2085,8 @@ def test_check_handle_timedout_buy_usercustom(default_conf_usdt, ticker_usdt, li 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt, fetch_order=MagicMock(return_value=limit_buy_order_old), - cancel_order_with_result=cancel_order_wr_mock, cancel_order=cancel_order_mock, + cancel_order_with_result=cancel_order_wr_mock, get_fee=fee ) freqtrade = FreqtradeBot(default_conf_usdt) @@ -2129,7 +2129,9 @@ def test_check_handle_timedout_buy_usercustom(default_conf_usdt, ticker_usdt, li def test_check_handle_timedout_buy(default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade, fee, mocker) -> None: rpc_mock = patch_RPCManager(mocker) - limit_buy_order_old['id'] = open_trade.open_order_id + open_trade.open_order_id = limit_buy_order_old['id'] + order = Order.parse_from_ccxt_object(limit_buy_order_old, 'mocked', 'buy') + open_trade.orders[0] = order limit_buy_cancel = deepcopy(limit_buy_order_old) limit_buy_cancel['status'] = 'canceled' cancel_order_mock = MagicMock(return_value=limit_buy_cancel) @@ -2214,8 +2216,9 @@ def test_check_handle_timedout_buy_exception(default_conf_usdt, ticker_usdt, def test_check_handle_timedout_sell_usercustom(default_conf_usdt, ticker_usdt, limit_sell_order_old, mocker, open_trade, caplog) -> None: default_conf_usdt["unfilledtimeout"] = {"buy": 1440, "sell": 1440, "exit_timeout_count": 1} - limit_sell_order_old['id'] = open_trade.open_order_id - + open_trade.open_order_id = limit_sell_order_old['id'] + order = Order.parse_from_ccxt_object(limit_sell_order_old, 'mocked', 'sell') + open_trade.orders[0] = order rpc_mock = patch_RPCManager(mocker) cancel_order_mock = MagicMock() patch_exchange(mocker) @@ -4877,45 +4880,26 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None: assert trade.is_open is False -@pytest.mark.parametrize('orders, results', [ +@pytest.mark.parametrize('data', [ ( - ( - # side ampunt, price - ('buy', 100, 10), - ('buy', 100, 15), - ('sell', 50, 12), - ('sell', 100, 20), - ('sell', 50, 5), - ), - ( - # amount, open_rate, stake_amount, cumulative_profit, realized_profit - (100.0, 10.0, 1000.0, 0.0, None,), - (200.0, 12.5, 2500.0, 0.0, None,), - (150.0, 12.5, 1875.0, -28.0625, -28.0625,), - (50.0, 12.5, 625.0, 713.8125, 741.875,), - (50.0, 12.5, 625.0, 713.8125, 336.625,), - ) + # tuple 1 - side amount, price + # tuple 2 - amount, open_rate, stake_amount, cumulative_profit, realized_profit + (('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None)), + (('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None)), + (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625)), + (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875)), + (('sell', 50, 5), (50.0, 12.5, 625.0, 713.8125, 336.625)), ), ( - ( - ('buy', 100, 3), - ('buy', 100, 7), - ('sell', 100, 11), - ('buy', 150, 15), - ('sell', 100, 19), - ('sell', 150, 23), - ), - ( - (100.0, 3.0, 300.0, 0.0, None,), - (200.0, 5.0, 1000.0, 0.0, None,), - (100.0, 5.0, 500.0, 596.0, 596.0,), - (250.0, 11.0, 2750.0, 596.0, 596.0,), - (150.0, 11.0, 1650.0, 1388.5, 792.5,), - (150.0, 11.0, 1650.0, 1388.5, 3175.75,), - ) - ), + (('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None)), + (('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None)), + (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0)), + (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0)), + (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5)), + (('sell', 150, 23), (150.0, 11.0, 1650.0, 1388.5, 3175.75)), + ) ]) -def test_position_adjust3(mocker, default_conf_usdt, fee, orders, results) -> None: +def test_position_adjust3(mocker, default_conf_usdt, fee, data) -> None: default_conf_usdt.update({ "position_adjustment_enable": True, "dry_run": False, @@ -4928,7 +4912,7 @@ def test_position_adjust3(mocker, default_conf_usdt, fee, orders, results) -> No freqtrade = FreqtradeBot(default_conf_usdt) trade = None freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) - for idx, (order, result) in enumerate(zip(orders, results)): + for idx, (order, result) in enumerate(data): amount = order[1] price = order[2] price_mock = MagicMock(return_value=price) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index d03034753..821e620d9 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -1215,7 +1215,7 @@ def test_update_order_from_ccxt(caplog): 'symbol': 'ETH/BTC', 'type': 'limit', 'price': 1234.5, - 'amount': 20.0, + 'amount': 20.0, 'filled': 9, 'remaining': 11, 'status': 'open', @@ -1641,7 +1641,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee): assert trade.open_trade_value == 2 * o1_trade_val assert trade.nr_of_successful_buys == 2 - # Just to make sure sell orders are ignored, let's calculate one more time. + # Just to make sure non partial sell orders are ignored, let's calculate one more time. sell1 = Order( ft_order_side='sell', ft_pair=trade.pair,