Merge pull request #4057 from freqtrade/avoid_high_fee_wrong_reports
Avoid high fee wrong reports
This commit is contained in:
commit
1436dc58f5
@ -1448,13 +1448,16 @@ class FreqtradeBot:
|
|||||||
fee_cost, fee_currency, fee_rate = self.exchange.extract_cost_curr_rate(order)
|
fee_cost, fee_currency, fee_rate = self.exchange.extract_cost_curr_rate(order)
|
||||||
logger.info(f"Fee for Trade {trade} [{order.get('side')}]: "
|
logger.info(f"Fee for Trade {trade} [{order.get('side')}]: "
|
||||||
f"{fee_cost:.8g} {fee_currency} - rate: {fee_rate}")
|
f"{fee_cost:.8g} {fee_currency} - rate: {fee_rate}")
|
||||||
|
if fee_rate is None or fee_rate < 0.02:
|
||||||
trade.update_fee(fee_cost, fee_currency, fee_rate, order.get('side', ''))
|
# Reject all fees that report as > 2%.
|
||||||
if trade_base_currency == fee_currency:
|
# These are most likely caused by a parsing bug in ccxt
|
||||||
# Apply fee to amount
|
# due to multiple trades (https://github.com/ccxt/ccxt/issues/8025)
|
||||||
return self.apply_fee_conditional(trade, trade_base_currency,
|
trade.update_fee(fee_cost, fee_currency, fee_rate, order.get('side', ''))
|
||||||
amount=order_amount, fee_abs=fee_cost)
|
if trade_base_currency == fee_currency:
|
||||||
return order_amount
|
# Apply fee to amount
|
||||||
|
return self.apply_fee_conditional(trade, trade_base_currency,
|
||||||
|
amount=order_amount, fee_abs=fee_cost)
|
||||||
|
return order_amount
|
||||||
return self.fee_detection_from_trades(trade, order, order_amount)
|
return self.fee_detection_from_trades(trade, order, order_amount)
|
||||||
|
|
||||||
def fee_detection_from_trades(self, trade: Trade, order: Dict, order_amount: float) -> float:
|
def fee_detection_from_trades(self, trade: Trade, order: Dict, order_amount: float) -> float:
|
||||||
|
@ -1588,16 +1588,7 @@ def fetch_trades_result():
|
|||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def trades_for_order2():
|
def trades_for_order2():
|
||||||
return [{'info': {'id': 34567,
|
return [{'info': {},
|
||||||
'orderId': 123456,
|
|
||||||
'price': '0.24544100',
|
|
||||||
'qty': '8.00000000',
|
|
||||||
'commission': '0.00800000',
|
|
||||||
'commissionAsset': 'LTC',
|
|
||||||
'time': 1521663363189,
|
|
||||||
'isBuyer': True,
|
|
||||||
'isMaker': False,
|
|
||||||
'isBestMatch': True},
|
|
||||||
'timestamp': 1521663363189,
|
'timestamp': 1521663363189,
|
||||||
'datetime': '2018-03-21T20:16:03.189Z',
|
'datetime': '2018-03-21T20:16:03.189Z',
|
||||||
'symbol': 'LTC/ETH',
|
'symbol': 'LTC/ETH',
|
||||||
@ -1609,16 +1600,7 @@ def trades_for_order2():
|
|||||||
'cost': 1.963528,
|
'cost': 1.963528,
|
||||||
'amount': 4.0,
|
'amount': 4.0,
|
||||||
'fee': {'cost': 0.004, 'currency': 'LTC'}},
|
'fee': {'cost': 0.004, 'currency': 'LTC'}},
|
||||||
{'info': {'id': 34567,
|
{'info': {},
|
||||||
'orderId': 123456,
|
|
||||||
'price': '0.24544100',
|
|
||||||
'qty': '8.00000000',
|
|
||||||
'commission': '0.00800000',
|
|
||||||
'commissionAsset': 'LTC',
|
|
||||||
'time': 1521663363189,
|
|
||||||
'isBuyer': True,
|
|
||||||
'isMaker': False,
|
|
||||||
'isBestMatch': True},
|
|
||||||
'timestamp': 1521663363189,
|
'timestamp': 1521663363189,
|
||||||
'datetime': '2018-03-21T20:16:03.189Z',
|
'datetime': '2018-03-21T20:16:03.189Z',
|
||||||
'symbol': 'LTC/ETH',
|
'symbol': 'LTC/ETH',
|
||||||
@ -1632,6 +1614,14 @@ def trades_for_order2():
|
|||||||
'fee': {'cost': 0.004, 'currency': 'LTC'}}]
|
'fee': {'cost': 0.004, 'currency': 'LTC'}}]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def trades_for_order3(trades_for_order2):
|
||||||
|
# Different fee currencies for each trade
|
||||||
|
trades_for_order = deepcopy(trades_for_order2)
|
||||||
|
trades_for_order[0]['fee'] = {'cost': 0.02, 'currency': 'BNB'}
|
||||||
|
return trades_for_order
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def buy_order_fee():
|
def buy_order_fee():
|
||||||
return {
|
return {
|
||||||
|
@ -3718,6 +3718,48 @@ def test_get_real_amount_multi(default_conf, trades_for_order2, buy_order_fee, c
|
|||||||
'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992).',
|
'open_rate=0.24544100, open_since=closed) (from 8.0 to 7.992).',
|
||||||
caplog)
|
caplog)
|
||||||
|
|
||||||
|
assert trade.fee_open == 0.001
|
||||||
|
assert trade.fee_close == 0.001
|
||||||
|
assert trade.fee_open_cost is not None
|
||||||
|
assert trade.fee_open_currency is not None
|
||||||
|
assert trade.fee_close_cost is None
|
||||||
|
assert trade.fee_close_currency is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_real_amount_multi2(default_conf, trades_for_order3, buy_order_fee, caplog, fee,
|
||||||
|
mocker, markets):
|
||||||
|
# Different fee currency on both trades
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order3)
|
||||||
|
amount = float(sum(x['amount'] for x in trades_for_order3))
|
||||||
|
default_conf['stake_currency'] = 'ETH'
|
||||||
|
trade = Trade(
|
||||||
|
pair='LTC/ETH',
|
||||||
|
amount=amount,
|
||||||
|
exchange='binance',
|
||||||
|
fee_open=fee.return_value,
|
||||||
|
fee_close=fee.return_value,
|
||||||
|
open_rate=0.245441,
|
||||||
|
open_order_id="123456"
|
||||||
|
)
|
||||||
|
# Fake markets entry to enable fee parsing
|
||||||
|
markets['BNB/ETH'] = markets['ETH/BTC']
|
||||||
|
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets))
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
|
||||||
|
return_value={'ask': 0.19, 'last': 0.2})
|
||||||
|
|
||||||
|
# Amount is reduced by "fee"
|
||||||
|
assert freqtrade.get_real_amount(trade, buy_order_fee) == amount - (amount * 0.0005)
|
||||||
|
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).',
|
||||||
|
caplog)
|
||||||
|
# Overall fee is average of both trade's fee
|
||||||
|
assert trade.fee_open == 0.001518575
|
||||||
|
assert trade.fee_open_cost is not None
|
||||||
|
assert trade.fee_open_currency is not None
|
||||||
|
assert trade.fee_close_cost is None
|
||||||
|
assert trade.fee_close_currency is None
|
||||||
|
|
||||||
|
|
||||||
def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee, fee,
|
def test_get_real_amount_fromorder(default_conf, trades_for_order, buy_order_fee, fee,
|
||||||
caplog, mocker):
|
caplog, mocker):
|
||||||
@ -4264,7 +4306,7 @@ def test_update_closed_trades_without_assigned_fees(mocker, default_conf, fee):
|
|||||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
|
||||||
def patch_with_fee(order):
|
def patch_with_fee(order):
|
||||||
order.update({'fee': {'cost': 0.1, 'rate': 0.2,
|
order.update({'fee': {'cost': 0.1, 'rate': 0.01,
|
||||||
'currency': order['symbol'].split('/')[0]}})
|
'currency': order['symbol'].split('/')[0]}})
|
||||||
return order
|
return order
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user