From 2f4b566d99d176865a9b9101e471fd76867a0415 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Wed, 8 Sep 2021 13:46:52 -0600 Subject: [PATCH] reverted back exchange.get_funding_fees method --- freqtrade/exchange/exchange.py | 32 +++++++- tests/exchange/test_exchange.py | 126 ++++++++++++++++---------------- 2 files changed, 94 insertions(+), 64 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index bfb6494e1..358fab6c4 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -9,7 +9,7 @@ import logging from copy import deepcopy from datetime import datetime, time, timezone from math import ceil -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple, Union import arrow import ccxt @@ -1525,6 +1525,36 @@ class Exchange: return self._api.fetch_funding_rates() + @retrier + def get_funding_fees(self, pair: str, since: Union[datetime, int]) -> float: + """ + Returns the sum of all funding fees that were exchanged for a pair within a timeframe + :param pair: (e.g. ADA/USDT) + :param since: The earliest time of consideration for calculating funding fees, + in unix time or as a datetime + """ + + if not self.exchange_has("fetchFundingHistory"): + raise OperationalException( + f"fetch_funding_history() has not been implemented on ccxt.{self.name}") + + if type(since) is datetime: + since = int(since.strftime('%s')) + + try: + funding_history = self._api.fetch_funding_history( + pair=pair, + since=since + ) + return sum(fee['amount'] for fee in funding_history) + except ccxt.DDoSProtection as e: + raise DDosProtection(e) from e + except (ccxt.NetworkError, ccxt.ExchangeError) as e: + raise TemporaryError( + f'Could not get funding fees due to {e.__class__.__name__}. Message: {e}') from e + except ccxt.BaseError as e: + raise OperationalException(e) from e + def hours_to_time(hours: List[int]) -> List[time]: ''' diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 8e4a099c5..e2a6639a3 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -2928,69 +2928,69 @@ def test_calculate_backoff(retrycount, max_retries, expected): assert calculate_backoff(retrycount, max_retries) == expected -# @pytest.mark.parametrize("exchange_name", ['binance', 'ftx']) -# def test_get_funding_fees(default_conf, mocker, exchange_name): -# api_mock = MagicMock() -# api_mock.fetch_funding_history = MagicMock(return_value=[ -# { -# 'amount': 0.14542341, -# 'code': 'USDT', -# 'datetime': '2021-09-01T08:00:01.000Z', -# 'id': '485478', -# 'info': {'asset': 'USDT', -# 'income': '0.14542341', -# 'incomeType': 'FUNDING_FEE', -# 'info': 'FUNDING_FEE', -# 'symbol': 'XRPUSDT', -# 'time': '1630512001000', -# 'tradeId': '', -# 'tranId': '4854789484855218760'}, -# 'symbol': 'XRP/USDT', -# 'timestamp': 1630512001000 -# }, -# { -# 'amount': -0.14642341, -# 'code': 'USDT', -# 'datetime': '2021-09-01T16:00:01.000Z', -# 'id': '485479', -# 'info': {'asset': 'USDT', -# 'income': '-0.14642341', -# 'incomeType': 'FUNDING_FEE', -# 'info': 'FUNDING_FEE', -# 'symbol': 'XRPUSDT', -# 'time': '1630512001000', -# 'tradeId': '', -# 'tranId': '4854789484855218760'}, -# 'symbol': 'XRP/USDT', -# 'timestamp': 1630512001000 -# } -# ]) -# type(api_mock).has = PropertyMock(return_value={'fetchFundingHistory': True}) +@pytest.mark.parametrize("exchange_name", ['binance', 'ftx']) +def test_get_funding_fees(default_conf, mocker, exchange_name): + api_mock = MagicMock() + api_mock.fetch_funding_history = MagicMock(return_value=[ + { + 'amount': 0.14542341, + 'code': 'USDT', + 'datetime': '2021-09-01T08:00:01.000Z', + 'id': '485478', + 'info': {'asset': 'USDT', + 'income': '0.14542341', + 'incomeType': 'FUNDING_FEE', + 'info': 'FUNDING_FEE', + 'symbol': 'XRPUSDT', + 'time': '1630512001000', + 'tradeId': '', + 'tranId': '4854789484855218760'}, + 'symbol': 'XRP/USDT', + 'timestamp': 1630512001000 + }, + { + 'amount': -0.14642341, + 'code': 'USDT', + 'datetime': '2021-09-01T16:00:01.000Z', + 'id': '485479', + 'info': {'asset': 'USDT', + 'income': '-0.14642341', + 'incomeType': 'FUNDING_FEE', + 'info': 'FUNDING_FEE', + 'symbol': 'XRPUSDT', + 'time': '1630512001000', + 'tradeId': '', + 'tranId': '4854789484855218760'}, + 'symbol': 'XRP/USDT', + 'timestamp': 1630512001000 + } + ]) + type(api_mock).has = PropertyMock(return_value={'fetchFundingHistory': True}) -# # mocker.patch('freqtrade.exchange.Exchange.get_funding_fees', lambda pair, since: y) -# exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) -# date_time = datetime.strptime("2021-09-01T00:00:01.000Z", '%Y-%m-%dT%H:%M:%S.%fZ') -# unix_time = int(date_time.strftime('%s')) -# expected_fees = -0.001 # 0.14542341 + -0.14642341 -# fees_from_datetime = exchange.get_funding_fees( -# pair='XRP/USDT', -# since=date_time -# ) -# fees_from_unix_time = exchange.get_funding_fees( -# pair='XRP/USDT', -# since=unix_time -# ) + # mocker.patch('freqtrade.exchange.Exchange.get_funding_fees', lambda pair, since: y) + exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) + date_time = datetime.strptime("2021-09-01T00:00:01.000Z", '%Y-%m-%dT%H:%M:%S.%fZ') + unix_time = int(date_time.strftime('%s')) + expected_fees = -0.001 # 0.14542341 + -0.14642341 + fees_from_datetime = exchange.get_funding_fees( + pair='XRP/USDT', + since=date_time + ) + fees_from_unix_time = exchange.get_funding_fees( + pair='XRP/USDT', + since=unix_time + ) -# assert(isclose(expected_fees, fees_from_datetime)) -# assert(isclose(expected_fees, fees_from_unix_time)) + assert(isclose(expected_fees, fees_from_datetime)) + assert(isclose(expected_fees, fees_from_unix_time)) -# ccxt_exceptionhandlers( -# mocker, -# default_conf, -# api_mock, -# exchange_name, -# "get_funding_fees", -# "fetch_funding_history", -# pair="XRP/USDT", -# since=unix_time -# ) + ccxt_exceptionhandlers( + mocker, + default_conf, + api_mock, + exchange_name, + "get_funding_fees", + "fetch_funding_history", + pair="XRP/USDT", + since=unix_time + )