diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 7eda75450..49468ce29 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1807,8 +1807,8 @@ class Exchange: int(open_date.timestamp() * 1000) ) for date in self._get_funding_fee_dates(open_date, close_date): - funding_rate = funding_rate_history[int(date.timestamp()) * 1000] - mark_price = mark_price_history[int(date.timestamp()) * 1000] + funding_rate = funding_rate_history[int(date.timestamp() * 1000)] + mark_price = mark_price_history[int(date.timestamp() * 1000)] fees += self._get_funding_fee( contract_size=amount, mark_price=mark_price, diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index cfac786c0..a046f85b9 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -268,7 +268,8 @@ class FreqtradeBot(LoggingMixin): def update_funding_fees(self): if self.trading_mode == TradingMode.FUTURES: - for trade in Trade.get_open_trades(): + trades = Trade.get_open_trades() + for trade in trades: if self.config['dry_run']: funding_fees = self.exchange.calculate_funding_fees( trade.pair, diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 4fa429839..44e99e551 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -3536,39 +3536,39 @@ def test_calculate_funding_fees( expected_fees ): ''' - nominal_value = mark_price * contract_size - funding_fee = nominal_value * funding_rate - contract_size: 30 - time: 0, mark_price: 2.77, nominal_value: 83.1, fundingRate: -0.000008, fundingFee: -0.0006647999999999999 - time: 1, mark_price: 2.73, nominal_value: 81.9, fundingRate: -0.000004, fundingFee: -0.0003276 - time: 2, mark_price: 2.74, nominal_value: 82.2, fundingRate: 0.000012, fundingFee: 0.0009864000000000001 - time: 3, mark_price: 2.76, nominal_value: 82.8, fundingRate: -0.000003, fundingFee: -0.0002484 - time: 4, mark_price: 2.76, nominal_value: 82.8, fundingRate: -0.000007, fundingFee: -0.0005796 - time: 5, mark_price: 2.77, nominal_value: 83.1, fundingRate: 0.000003, fundingFee: 0.0002493 - time: 6, mark_price: 2.78, nominal_value: 83.39999999999999, fundingRate: 0.000019, fundingFee: 0.0015846 - time: 7, mark_price: 2.78, nominal_value: 83.39999999999999, fundingRate: 0.000003, fundingFee: 0.00025019999999999996 - time: 8, mark_price: 2.77, nominal_value: 83.1, fundingRate: -0.000003, fundingFee: -0.0002493 - time: 9, mark_price: 2.77, nominal_value: 83.1, fundingRate: 0, fundingFee: 0.0 - time: 10, mark_price: 2.84, nominal_value: 85.19999999999999, fundingRate: 0.000013, fundingFee: 0.0011075999999999998 - time: 11, mark_price: 2.81, nominal_value: 84.3, fundingRate: 0.000077, fundingFee: 0.0064911 - time: 12, mark_price: 2.81, nominal_value: 84.3, fundingRate: 0.000072, fundingFee: 0.0060696 - time: 13, mark_price: 2.82, nominal_value: 84.6, fundingRate: 0.000097, fundingFee: 0.008206199999999999 + nominal_value = mark_price * contract_size + funding_fee = nominal_value * funding_rate + contract_size: 30 + time: 0, mark: 2.77, nominal_value: 83.1, fundRate: -0.000008, fundFee: -0.0006648 + time: 1, mark: 2.73, nominal_value: 81.9, fundRate: -0.000004, fundFee: -0.0003276 + time: 2, mark: 2.74, nominal_value: 82.2, fundRate: 0.000012, fundFee: 0.0009864 + time: 3, mark: 2.76, nominal_value: 82.8, fundRate: -0.000003, fundFee: -0.0002484 + time: 4, mark: 2.76, nominal_value: 82.8, fundRate: -0.000007, fundFee: -0.0005796 + time: 5, mark: 2.77, nominal_value: 83.1, fundRate: 0.000003, fundFee: 0.0002493 + time: 6, mark: 2.78, nominal_value: 83.4, fundRate: 0.000019, fundFee: 0.0015846 + time: 7, mark: 2.78, nominal_value: 83.4, fundRate: 0.000003, fundFee: 0.0002502 + time: 8, mark: 2.77, nominal_value: 83.1, fundRate: -0.000003, fundFee: -0.0002493 + time: 9, mark: 2.77, nominal_value: 83.1, fundRate: 0, fundFee: 0.0 + time: 10, mark: 2.84, nominal_value: 85.2, fundRate: 0.000013, fundFee: 0.0011076 + time: 11, mark: 2.81, nominal_value: 84.3, fundRate: 0.000077, fundFee: 0.0064911 + time: 12, mark: 2.81, nominal_value: 84.3, fundRate: 0.000072, fundFee: 0.0060696 + time: 13, mark: 2.82, nominal_value: 84.6, fundRate: 0.000097, fundFee: 0.0082062 - contract_size: 50 - time: 0, mark_price: 2.77, nominal_value: 138.5, fundingRate: -0.000008, fundingFee: -0.001108 - time: 1, mark_price: 2.73, nominal_value: 136.5, fundingRate: -0.000004, fundingFee: -0.0005459999999999999 - time: 2, mark_price: 2.74, nominal_value: 137.0, fundingRate: 0.000012, fundingFee: 0.001644 - time: 3, mark_price: 2.76, nominal_value: 138.0, fundingRate: -0.000003, fundingFee: -0.00041400000000000003 - time: 4, mark_price: 2.76, nominal_value: 138.0, fundingRate: -0.000007, fundingFee: -0.000966 - time: 5, mark_price: 2.77, nominal_value: 138.5, fundingRate: 0.000003, fundingFee: 0.0004155 - time: 6, mark_price: 2.78, nominal_value: 139.0, fundingRate: 0.000019, fundingFee: 0.002641 - time: 7, mark_price: 2.78, nominal_value: 139.0, fundingRate: 0.000003, fundingFee: 0.000417 - time: 8, mark_price: 2.77, nominal_value: 138.5, fundingRate: -0.000003, fundingFee: -0.0004155 - time: 9, mark_price: 2.77, nominal_value: 138.5, fundingRate: 0, fundingFee: 0.0 - time: 10, mark_price: 2.84, nominal_value: 142.0, fundingRate: 0.000013, fundingFee: 0.001846 - time: 11, mark_price: 2.81, nominal_value: 140.5, fundingRate: 0.000077, fundingFee: 0.0108185 - time: 12, mark_price: 2.81, nominal_value: 140.5, fundingRate: 0.000072, fundingFee: 0.010116 - time: 13, mark_price: 2.82, nominal_value: 141.0, fundingRate: 0.000097, fundingFee: 0.013677 + contract_size: 50 + time: 0, mark: 2.77, nominal_value: 138.5, fundRate: -0.000008, fundFee: -0.001108 + time: 1, mark: 2.73, nominal_value: 136.5, fundRate: -0.000004, fundFee: -0.000546 + time: 2, mark: 2.74, nominal_value: 137.0, fundRate: 0.000012, fundFee: 0.001644 + time: 3, mark: 2.76, nominal_value: 138.0, fundRate: -0.000003, fundFee: -0.000414 + time: 4, mark: 2.76, nominal_value: 138.0, fundRate: -0.000007, fundFee: -0.000966 + time: 5, mark: 2.77, nominal_value: 138.5, fundRate: 0.000003, fundFee: 0.0004155 + time: 6, mark: 2.78, nominal_value: 139.0, fundRate: 0.000019, fundFee: 0.002641 + time: 7, mark: 2.78, nominal_value: 139.0, fundRate: 0.000003, fundFee: 0.000417 + time: 8, mark: 2.77, nominal_value: 138.5, fundRate: -0.000003, fundFee: -0.0004155 + time: 9, mark: 2.77, nominal_value: 138.5, fundRate: 0, fundFee: 0.0 + time: 10, mark: 2.84, nominal_value: 142.0, fundRate: 0.000013, fundFee: 0.001846 + time: 11, mark: 2.81, nominal_value: 140.5, fundRate: 0.000077, fundFee: 0.0108185 + time: 12, mark: 2.81, nominal_value: 140.5, fundRate: 0.000072, fundFee: 0.010116 + time: 13, mark: 2.82, nominal_value: 141.0, fundRate: 0.000097, fundFee: 0.013677 ''' d1 = datetime.strptime(f"{d1} +0000", '%Y-%m-%d %H:%M:%S %z') d2 = datetime.strptime(f"{d2} +0000", '%Y-%m-%d %H:%M:%S %z') diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 3d91d738b..9f05a6518 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -20,9 +20,9 @@ from freqtrade.persistence import Order, PairLocks, Trade from freqtrade.persistence.models import PairLock from freqtrade.strategy.interface import SellCheckTuple from freqtrade.worker import Worker -from tests.conftest import (create_mock_trades, get_patched_freqtradebot, get_patched_worker, - log_has, log_has_re, patch_edge, patch_exchange, patch_get_signal, - patch_wallet, patch_whitelist) +from tests.conftest import (create_mock_trades, create_mock_trades_usdt, get_patched_freqtradebot, + get_patched_worker, log_has, log_has_re, patch_edge, patch_exchange, + patch_get_signal, patch_wallet, patch_whitelist) from tests.conftest_trades import (MOCK_TRADE_COUNT, enter_side, exit_side, mock_order_1, mock_order_2, mock_order_2_sell, mock_order_3, mock_order_3_sell, mock_order_4, mock_order_5_stoploss, mock_order_6_sell) @@ -4682,8 +4682,8 @@ def test_leverage_prep(): ('futures', 33, "2021-08-31 23:59:59", "2021-09-01 08:00:07"), ('futures', 33, "2021-08-31 23:59:58", "2021-09-01 08:00:07"), ]) -def test_update_funding_fees(mocker, default_conf, trading_mode, calls, time_machine, - t1, t2): +def test_update_funding_fees_schedule(mocker, default_conf, trading_mode, calls, time_machine, + t1, t2): time_machine.move_to(f"{t1} +00:00") patch_RPCManager(mocker) @@ -4698,3 +4698,95 @@ def test_update_funding_fees(mocker, default_conf, trading_mode, calls, time_mac freqtrade._schedule.run_pending() assert freqtrade.update_funding_fees.call_count == calls + + +def test_update_funding_fees(mocker, default_conf, time_machine, fee): + ''' + nominal_value = mark_price * contract_size + funding_fee = nominal_value * funding_rate + contract_size = 123 + "LTC/BTC" + time: 0, mark: 3.3, fundRate: 0.00032583, nominal_value: 405.9, fundFee: 0.132254397 + time: 8, mark: 3.2, fundRate: 0.00024472, nominal_value: 393.6, fundFee: 0.096321792 + "ETH/BTC" + time: 0, mark: 2.4, fundRate: 0.0001, nominal_value: 295.2, fundFee: 0.02952 + time: 8, mark: 2.5, fundRate: 0.0001, nominal_value: 307.5, fundFee: 0.03075 + "ETC/BTC" + time: 0, mark: 4.3, fundRate: 0.00031077, nominal_value: 528.9, fundFee: 0.164366253 + time: 8, mark: 4.1, fundRate: 0.00022655, nominal_value: 504.3, fundFee: 0.114249165 + "XRP/BTC" + time: 0, mark: 1.2, fundRate: 0.00049426, nominal_value: 147.6, fundFee: 0.072952776 + time: 8, mark: 1.2, fundRate: 0.00032715, nominal_value: 147.6, fundFee: 0.04828734 + ''' + time_machine.move_to("2021-09-01 00:00:00") + + funding_rates = { + "LTC/BTC": { + 1630454400000: 0.00032583, + 1630483200000: 0.00024472, + }, + "ETH/BTC": { + 1630454400000: 0.0001, + 1630483200000: 0.0001, + }, + "ETC/BTC": { + 1630454400000: 0.00031077, + 1630483200000: 0.00022655, + }, + "XRP/BTC": { + 1630454400000: 0.00049426, + 1630483200000: 0.00032715, + } + } + + mark_prices = { + "LTC/BTC": { + 1630454400000: 3.3, + 1630483200000: 3.2, + }, + "ETH/BTC": { + 1630454400000: 2.4, + 1630483200000: 2.5, + }, + "ETC/BTC": { + 1630454400000: 4.3, + 1630483200000: 4.1, + }, + "XRP/BTC": { + 1630454400000: 1.2, + 1630483200000: 1.2, + } + } + + mocker.patch( + 'freqtrade.exchange.Exchange._get_mark_price_history', + side_effect=[ + mark_prices["LTC/BTC"], + mark_prices["ETH/BTC"], + mark_prices["ETC/BTC"], + mark_prices["XRP/BTC"], + ] + ) + mocker.patch( + 'freqtrade.exchange.Exchange.get_funding_rate_history', + side_effect=[ + funding_rates["LTC/BTC"], + funding_rates["ETH/BTC"], + funding_rates["ETC/BTC"], + funding_rates["XRP/BTC"], + ] + ) + patch_RPCManager(mocker) + patch_exchange(mocker) + default_conf['trading_mode'] = 'futures' + default_conf['collateral'] = 'isolated' + default_conf['dry_run'] = True + freqtrade = get_patched_freqtradebot(mocker, default_conf) + create_mock_trades(fee, False) + time_machine.move_to("2021-09-01 08:00:00 +00:00") + freqtrade._schedule.run_pending() + + trades = Trade.get_open_trades() + for trade in trades: + assert trade.funding_fees == 123 * mark_prices[trade.pair] * funding_rates[trade.pair] + return