diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 163c4faaa..5ef4888e0 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1160,6 +1160,23 @@ class FreqtradeBot: return False + def apply_fee_conditional(self, trade: Trade, trade_base_currency: str, + amount: float, fee: float) -> float: + """ + Applies the fee to amount (either from Order or from Trades). + Can eat into dust if more than the required asset is available. + """ + if fee != 0 and self.wallets.get_free(trade_base_currency) >= amount: + # Eat into dust if we own more than base currency + logger.info(f"Fee amount for {trade} was in base currency - " + f"Eating Fee {fee} into dust.") + elif fee != 0: + real_amount = self.exchange.amount_to_precision(trade.pair, amount - fee) + logger.info(f"Applying fee on amount for {trade} " + f"(from {amount} to {real_amount}).") + return real_amount + return amount + def get_real_amount(self, trade: Trade, order: Dict, order_amount: float = None) -> float: """ Detect and update trade fee. @@ -1181,11 +1198,12 @@ class FreqtradeBot: fee_cost, fee_currency, fee_rate = self.exchange.extract_cost_curr_rate(order) logger.info(f"Fee for Trade {trade} [{order.get('side')}]: " f"{fee_cost:.8g} {fee_currency} - rate: {fee_rate}") - if trade_base_currency == fee_currency: - order_amount = order_amount - fee_cost - logger.info(f"Applying fee on amount for {trade} (from {order['amount']} " - f"to {order_amount}) from Order") + trade.update_fee(fee_cost, fee_currency, fee_rate, order.get('side', '')) + if trade_base_currency == fee_currency: + # Apply fee to amount + return self.apply_fee_conditional(trade, trade_base_currency, + amount=order_amount, fee=fee_cost) return order_amount return self.fee_detection_from_trades(trade, order, order_amount) @@ -1218,15 +1236,15 @@ class FreqtradeBot: # Ensure at least one trade was found: if fee_currency: # fee_rate should use mean - fee_rate = sum(fee_rate_array) / float(len(fee_rate_array)) if fee_rate_array else None trade.update_fee(fee_cost, fee_currency, fee_rate, order.get('side', '')) if not isclose(amount, order_amount, abs_tol=constants.MATH_CLOSE_PREC): logger.warning(f"Amount {amount} does not match amount {trade.amount}") raise DependencyException("Half bought? Amounts don't match") - real_amount = amount - fee_abs + if fee_abs != 0: - logger.info(f"Applying fee on amount for {trade} " - f"(from {order_amount} to {real_amount}) from Trades") - return real_amount + return self.apply_fee_conditional(trade, trade_base_currency, + amount=amount, fee=fee_abs) + else: + return amount diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 19a094fab..4a28147fc 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -2221,7 +2221,7 @@ def test_check_handle_timedout_partial_fee(default_conf, ticker, open_trade, cap # and apply fees if necessary. freqtrade.check_handle_timedout() - assert log_has_re(r"Applying fee on amount for Trade.* Order", caplog) + assert log_has_re(r"Applying fee on amount for Trade.*", caplog) assert cancel_order_mock.call_count == 1 assert rpc_mock.call_count == 2 @@ -3301,7 +3301,7 @@ def test_get_real_amount_quote(default_conf, trades_for_order, buy_order_fee, fe # Amount is reduced by "fee" assert freqtrade.get_real_amount(trade, buy_order_fee) == amount - (amount * 0.001) assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, ' - 'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992) from Trades', + 'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992).', caplog) @@ -3409,7 +3409,7 @@ def test_get_real_amount_multi(default_conf, trades_for_order2, buy_order_fee, c # Amount is reduced by "fee" assert freqtrade.get_real_amount(trade, buy_order_fee) == amount - (amount * 0.001) assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, ' - 'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992) from Trades', + 'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992).', caplog) @@ -3435,7 +3435,7 @@ def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee # Amount is reduced by "fee" assert freqtrade.get_real_amount(trade, limit_buy_order) == amount - 0.004 assert log_has('Applying fee on amount for Trade(id=None, pair=LTC/ETH, amount=8.00000000, ' - 'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.996) from Order', + 'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.996).', caplog)