New method for combining all funding fees within a time period
This commit is contained in:
parent
6b40792f80
commit
3c509a1f9b
@ -24,5 +24,3 @@ class Bibox(Exchange):
|
|||||||
def _ccxt_config(self) -> Dict:
|
def _ccxt_config(self) -> Dict:
|
||||||
# Parameters to add directly to ccxt sync/async initialization.
|
# Parameters to add directly to ccxt sync/async initialization.
|
||||||
return {"has": {"fetchCurrencies": False}}
|
return {"has": {"fetchCurrencies": False}}
|
||||||
|
|
||||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
|
||||||
|
@ -29,8 +29,6 @@ class Binance(Exchange):
|
|||||||
"trades_pagination_arg": "fromId",
|
"trades_pagination_arg": "fromId",
|
||||||
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
|
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
|
||||||
}
|
}
|
||||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
|
||||||
# but the schedule won't check within this timeframe
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
|
@ -23,8 +23,6 @@ class Bybit(Exchange):
|
|||||||
"ohlcv_candle_limit": 200,
|
"ohlcv_candle_limit": 200,
|
||||||
}
|
}
|
||||||
|
|
||||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
|
# (TradingMode.FUTURES, Collateral.CROSS), # TODO-lev: Uncomment once supported
|
||||||
|
@ -73,10 +73,6 @@ class Exchange:
|
|||||||
}
|
}
|
||||||
_ft_has: Dict = {}
|
_ft_has: Dict = {}
|
||||||
|
|
||||||
# funding_fee_times is currently unused, but should ideally be used to properly
|
|
||||||
# schedule refresh times
|
|
||||||
funding_fee_times: List[int] = [] # hours of the day
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
]
|
]
|
||||||
@ -1711,21 +1707,6 @@ class Exchange:
|
|||||||
"""
|
"""
|
||||||
return open_date.minute > 0 or open_date.second > 0
|
return open_date.minute > 0 or open_date.second > 0
|
||||||
|
|
||||||
def _get_funding_fee_dates(self, start: datetime, end: datetime):
|
|
||||||
if self.funding_fee_cutoff(start):
|
|
||||||
start += timedelta(hours=1)
|
|
||||||
start = datetime(start.year, start.month, start.day, start.hour, tzinfo=timezone.utc)
|
|
||||||
end = datetime(end.year, end.month, end.day, end.hour, tzinfo=timezone.utc)
|
|
||||||
|
|
||||||
results = []
|
|
||||||
iterator = start
|
|
||||||
while iterator <= end:
|
|
||||||
if iterator.hour in self.funding_fee_times:
|
|
||||||
results.append(iterator)
|
|
||||||
iterator += timedelta(hours=1)
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
@retrier
|
@retrier
|
||||||
def set_margin_mode(self, pair: str, collateral: Collateral, params: dict = {}):
|
def set_margin_mode(self, pair: str, collateral: Collateral, params: dict = {}):
|
||||||
"""
|
"""
|
||||||
@ -1808,6 +1789,16 @@ class Exchange:
|
|||||||
:param close_date: The date and time that the trade ended
|
:param close_date: The date and time that the trade ended
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if self.funding_fee_cutoff(open_date):
|
||||||
|
open_date += timedelta(hours=1)
|
||||||
|
open_date = datetime(
|
||||||
|
open_date.year,
|
||||||
|
open_date.month,
|
||||||
|
open_date.day,
|
||||||
|
open_date.hour,
|
||||||
|
tzinfo=timezone.utc
|
||||||
|
)
|
||||||
|
|
||||||
fees: float = 0
|
fees: float = 0
|
||||||
if not close_date:
|
if not close_date:
|
||||||
close_date = datetime.now(timezone.utc)
|
close_date = datetime.now(timezone.utc)
|
||||||
@ -1821,29 +1812,20 @@ class Exchange:
|
|||||||
pair,
|
pair,
|
||||||
open_timestamp
|
open_timestamp
|
||||||
)
|
)
|
||||||
funding_fee_dates = self._get_funding_fee_dates(open_date, close_date)
|
for timestamp in funding_rate_history.keys():
|
||||||
for date in funding_fee_dates:
|
funding_rate = funding_rate_history[timestamp]
|
||||||
timestamp = int(date.timestamp()) * 1000
|
|
||||||
if timestamp in funding_rate_history:
|
|
||||||
funding_rate = funding_rate_history[timestamp]
|
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
f"Funding rate for {pair} at {date} not found in funding_rate_history"
|
|
||||||
f"Funding fee calculation may be incorrect"
|
|
||||||
)
|
|
||||||
if timestamp in mark_price_history:
|
if timestamp in mark_price_history:
|
||||||
mark_price = mark_price_history[timestamp]
|
mark_price = mark_price_history[timestamp]
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
f"Mark price for {pair} at {date} not found in funding_rate_history"
|
|
||||||
f"Funding fee calculation may be incorrect"
|
|
||||||
)
|
|
||||||
if funding_rate and mark_price:
|
|
||||||
fees += self._get_funding_fee(
|
fees += self._get_funding_fee(
|
||||||
size=amount,
|
size=amount,
|
||||||
mark_price=mark_price,
|
mark_price=mark_price,
|
||||||
funding_rate=funding_rate
|
funding_rate=funding_rate
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
f"Mark price for {pair} at timestamp {timestamp} not found in "
|
||||||
|
f"funding_rate_history Funding fee calculation may be incorrect"
|
||||||
|
)
|
||||||
|
|
||||||
return fees
|
return fees
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ class Ftx(Exchange):
|
|||||||
"ohlcv_candle_limit": 1500,
|
"ohlcv_candle_limit": 1500,
|
||||||
"mark_ohlcv_price": "index"
|
"mark_ohlcv_price": "index"
|
||||||
}
|
}
|
||||||
funding_fee_times: List[int] = list(range(0, 24))
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
|
@ -26,8 +26,6 @@ class Gateio(Exchange):
|
|||||||
|
|
||||||
_headers = {'X-Gate-Channel-Id': 'freqtrade'}
|
_headers = {'X-Gate-Channel-Id': 'freqtrade'}
|
||||||
|
|
||||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
|
# (TradingMode.MARGIN, Collateral.CROSS), # TODO-lev: Uncomment once supported
|
||||||
|
@ -21,5 +21,3 @@ class Hitbtc(Exchange):
|
|||||||
"ohlcv_candle_limit": 1000,
|
"ohlcv_candle_limit": 1000,
|
||||||
"ohlcv_params": {"sort": "DESC"}
|
"ohlcv_params": {"sort": "DESC"}
|
||||||
}
|
}
|
||||||
|
|
||||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
|
||||||
|
@ -23,7 +23,6 @@ class Kraken(Exchange):
|
|||||||
"trades_pagination": "id",
|
"trades_pagination": "id",
|
||||||
"trades_pagination_arg": "since",
|
"trades_pagination_arg": "since",
|
||||||
}
|
}
|
||||||
funding_fee_times: List[int] = [0, 4, 8, 12, 16, 20] # hours of the day
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
|
@ -24,5 +24,3 @@ class Kucoin(Exchange):
|
|||||||
"order_time_in_force": ['gtc', 'fok', 'ioc'],
|
"order_time_in_force": ['gtc', 'fok', 'ioc'],
|
||||||
"time_in_force_parameter": "timeInForce",
|
"time_in_force_parameter": "timeInForce",
|
||||||
}
|
}
|
||||||
|
|
||||||
funding_fee_times: List[int] = [4, 12, 20] # hours of the day
|
|
||||||
|
@ -17,7 +17,6 @@ class Okex(Exchange):
|
|||||||
_ft_has: Dict = {
|
_ft_has: Dict = {
|
||||||
"ohlcv_candle_limit": 100,
|
"ohlcv_candle_limit": 100,
|
||||||
}
|
}
|
||||||
funding_fee_times: List[int] = [0, 8, 16] # hours of the day
|
|
||||||
|
|
||||||
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
||||||
# TradingMode.SPOT always supported and not required in this list
|
# TradingMode.SPOT always supported and not required in this list
|
||||||
|
@ -2389,7 +2389,7 @@ def mark_ohlcv():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def funding_rate_history():
|
def funding_rate_history_hourly():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"symbol": "ADA/USDT",
|
"symbol": "ADA/USDT",
|
||||||
@ -2476,3 +2476,21 @@ def funding_rate_history():
|
|||||||
"datetime": "2021-09-01T13:00:00.000Z"
|
"datetime": "2021-09-01T13:00:00.000Z"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function')
|
||||||
|
def funding_rate_history_octohourly():
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"symbol": "ADA/USDT",
|
||||||
|
"fundingRate": -0.000008,
|
||||||
|
"timestamp": 1630454400000,
|
||||||
|
"datetime": "2021-09-01T00:00:00.000Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"symbol": "ADA/USDT",
|
||||||
|
"fundingRate": -0.000003,
|
||||||
|
"timestamp": 1630483200000,
|
||||||
|
"datetime": "2021-09-01T08:00:00.000Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
@ -3318,124 +3318,6 @@ def test__get_funding_fee(
|
|||||||
assert kraken._get_funding_fee(size, funding_rate, mark_price, time_in_ratio) == kraken_fee
|
assert kraken._get_funding_fee(size, funding_rate, mark_price, time_in_ratio) == kraken_fee
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('exchange,d1,d2,funding_times', [
|
|
||||||
(
|
|
||||||
'binance',
|
|
||||||
"2021-09-01 00:00:00",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
["2021-09-01 00", "2021-09-01 08"]
|
|
||||||
),
|
|
||||||
('binance', "2021-09-01 00:00:15", "2021-09-01 08:00:00", ["2021-09-01 00", "2021-09-01 08"]),
|
|
||||||
('binance', "2021-09-01 00:00:16", "2021-09-01 08:00:00", ["2021-09-01 08"]),
|
|
||||||
('binance', "2021-09-01 01:00:14", "2021-09-01 08:00:00", ["2021-09-01 08"]),
|
|
||||||
('binance', "2021-09-01 00:00:00", "2021-09-01 07:59:59", ["2021-09-01 00"]),
|
|
||||||
('binance', "2021-09-01 00:00:00", "2021-09-01 12:00:00", ["2021-09-01 00", "2021-09-01 08"]),
|
|
||||||
(
|
|
||||||
'binance',
|
|
||||||
"2021-09-01 00:00:01",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
["2021-09-01 00", "2021-09-01 08"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'kraken',
|
|
||||||
"2021-09-01 00:00:00",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
["2021-09-01 00", "2021-09-01 04", "2021-09-01 08"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'kraken',
|
|
||||||
"2021-09-01 00:00:15",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
["2021-09-01 04", "2021-09-01 08"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'kraken',
|
|
||||||
"2021-09-01 01:00:14",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
["2021-09-01 04", "2021-09-01 08"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'kraken',
|
|
||||||
"2021-09-01 00:00:00",
|
|
||||||
"2021-09-01 07:59:59",
|
|
||||||
["2021-09-01 00", "2021-09-01 04"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'kraken',
|
|
||||||
"2021-09-01 00:00:00",
|
|
||||||
"2021-09-01 12:00:00",
|
|
||||||
["2021-09-01 00", "2021-09-01 04", "2021-09-01 08", "2021-09-01 12"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'kraken',
|
|
||||||
"2021-09-01 00:00:01",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
["2021-09-01 04", "2021-09-01 08"]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'ftx',
|
|
||||||
"2021-09-01 00:00:00",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
[
|
|
||||||
"2021-09-01 00",
|
|
||||||
"2021-09-01 01",
|
|
||||||
"2021-09-01 02",
|
|
||||||
"2021-09-01 03",
|
|
||||||
"2021-09-01 04",
|
|
||||||
"2021-09-01 05",
|
|
||||||
"2021-09-01 06",
|
|
||||||
"2021-09-01 07",
|
|
||||||
"2021-09-01 08"
|
|
||||||
]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'ftx',
|
|
||||||
"2021-09-01 00:00:00",
|
|
||||||
"2021-09-01 12:00:00",
|
|
||||||
[
|
|
||||||
"2021-09-01 00",
|
|
||||||
"2021-09-01 01",
|
|
||||||
"2021-09-01 02",
|
|
||||||
"2021-09-01 03",
|
|
||||||
"2021-09-01 04",
|
|
||||||
"2021-09-01 05",
|
|
||||||
"2021-09-01 06",
|
|
||||||
"2021-09-01 07",
|
|
||||||
"2021-09-01 08",
|
|
||||||
"2021-09-01 09",
|
|
||||||
"2021-09-01 10",
|
|
||||||
"2021-09-01 11",
|
|
||||||
"2021-09-01 12"
|
|
||||||
]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'ftx',
|
|
||||||
"2021-09-01 00:00:01",
|
|
||||||
"2021-09-01 08:00:00",
|
|
||||||
[
|
|
||||||
"2021-09-01 01",
|
|
||||||
"2021-09-01 02",
|
|
||||||
"2021-09-01 03",
|
|
||||||
"2021-09-01 04",
|
|
||||||
"2021-09-01 05",
|
|
||||||
"2021-09-01 06",
|
|
||||||
"2021-09-01 07",
|
|
||||||
"2021-09-01 08"
|
|
||||||
]
|
|
||||||
),
|
|
||||||
('gateio', "2021-09-01 00:00:00", "2021-09-01 08:00:00", ["2021-09-01 00", "2021-09-01 08"]),
|
|
||||||
('gateio', "2021-09-01 00:00:00", "2021-09-01 12:00:00", ["2021-09-01 00", "2021-09-01 08"]),
|
|
||||||
('gateio', "2021-09-01 00:00:01", "2021-09-01 08:00:00", ["2021-09-01 08"]),
|
|
||||||
])
|
|
||||||
def test__get_funding_fee_dates(mocker, default_conf, exchange, d1, d2, funding_times):
|
|
||||||
expected_result = [datetime.strptime(f"{d} +0000", '%Y-%m-%d %H %z') for d in funding_times]
|
|
||||||
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')
|
|
||||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange)
|
|
||||||
result = exchange._get_funding_fee_dates(d1, d2)
|
|
||||||
assert result == expected_result
|
|
||||||
|
|
||||||
|
|
||||||
def test__get_mark_price_history(mocker, default_conf, mark_ohlcv):
|
def test__get_mark_price_history(mocker, default_conf, mark_ohlcv):
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.fetch_ohlcv = MagicMock(return_value=mark_ohlcv)
|
api_mock.fetch_ohlcv = MagicMock(return_value=mark_ohlcv)
|
||||||
@ -3473,9 +3355,9 @@ def test__get_mark_price_history(mocker, default_conf, mark_ohlcv):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_get_funding_rate_history(mocker, default_conf, funding_rate_history):
|
def test_get_funding_rate_history(mocker, default_conf, funding_rate_history_hourly):
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.fetch_funding_rate_history = MagicMock(return_value=funding_rate_history)
|
api_mock.fetch_funding_rate_history = MagicMock(return_value=funding_rate_history_hourly)
|
||||||
type(api_mock).has = PropertyMock(return_value={'fetchFundingRateHistory': True})
|
type(api_mock).has = PropertyMock(return_value={'fetchFundingRateHistory': True})
|
||||||
|
|
||||||
# mocker.patch('freqtrade.exchange.Exchange.get_funding_fees', lambda pair, since: y)
|
# mocker.patch('freqtrade.exchange.Exchange.get_funding_fees', lambda pair, since: y)
|
||||||
@ -3511,14 +3393,14 @@ def test_get_funding_rate_history(mocker, default_conf, funding_rate_history):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('exchange,d1,d2,amount,expected_fees', [
|
@pytest.mark.parametrize('exchange,rate_start,rate_end,d1,d2,amount,expected_fees', [
|
||||||
('binance', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
('binance', 0, 2, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
||||||
('binance', "2021-09-01 00:00:15", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
('binance', 0, 2, "2021-09-01 00:00:15", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
||||||
('binance', "2021-09-01 00:00:16", "2021-09-01 08:00:00", 30.0, -0.0002493),
|
('binance', 1, 2, "2021-09-01 01:00:14", "2021-09-01 08:00:00", 30.0, -0.0002493),
|
||||||
('binance', "2021-09-01 01:00:14", "2021-09-01 08:00:00", 30.0, -0.0002493),
|
('binance', 1, 2, "2021-09-01 00:00:16", "2021-09-01 08:00:00", 30.0, -0.0002493),
|
||||||
('binance', "2021-09-01 00:00:00", "2021-09-01 07:59:59", 30.0, -0.0006647999999999999),
|
('binance', 0, 1, "2021-09-01 00:00:00", "2021-09-01 07:59:59", 30.0, -0.0006647999999999999),
|
||||||
('binance', "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, -0.0009140999999999999),
|
('binance', 0, 2, "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, -0.0009140999999999999),
|
||||||
('binance', "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
('binance', 0, 2, "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
||||||
# TODO: Uncoment once _calculate_funding_fees can pas time_in_ratio to exchange._get_funding_fee
|
# TODO: Uncoment once _calculate_funding_fees can pas time_in_ratio to exchange._get_funding_fee
|
||||||
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0014937),
|
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0014937),
|
||||||
# ('kraken', "2021-09-01 00:00:15", "2021-09-01 08:00:00", 30.0, -0.0008289),
|
# ('kraken', "2021-09-01 00:00:15", "2021-09-01 08:00:00", 30.0, -0.0008289),
|
||||||
@ -3526,21 +3408,24 @@ def test_get_funding_rate_history(mocker, default_conf, funding_rate_history):
|
|||||||
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 07:59:59", 30.0, -0.0012443999999999999),
|
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 07:59:59", 30.0, -0.0012443999999999999),
|
||||||
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, 0.0045759),
|
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, 0.0045759),
|
||||||
# ('kraken', "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0008289),
|
# ('kraken', "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0008289),
|
||||||
('ftx', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, 0.0010008000000000003),
|
('ftx', 0, 9, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, 0.0010008000000000003),
|
||||||
('ftx', "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, 0.0146691),
|
('ftx', 0, 13, "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, 0.0146691),
|
||||||
('ftx', "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, 0.0016656000000000002),
|
('ftx', 1, 9, "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, 0.0016656000000000002),
|
||||||
('gateio', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
('gateio', 0, 2, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 30.0, -0.0009140999999999999),
|
||||||
('gateio', "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, -0.0009140999999999999),
|
('gateio', 0, 2, "2021-09-01 00:00:00", "2021-09-01 12:00:00", 30.0, -0.0009140999999999999),
|
||||||
('gateio', "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0002493),
|
('gateio', 1, 2, "2021-09-01 00:00:01", "2021-09-01 08:00:00", 30.0, -0.0002493),
|
||||||
('binance', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, -0.0015235000000000001),
|
('binance', 0, 2, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, -0.0015235000000000001),
|
||||||
# TODO: Uncoment once _calculate_funding_fees can pas time_in_ratio to exchange._get_funding_fee
|
# TODO: Uncoment once _calculate_funding_fees can pas time_in_ratio to exchange._get_funding_fee
|
||||||
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, -0.0024895),
|
# ('kraken', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, -0.0024895),
|
||||||
('ftx', "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, 0.0016680000000000002),
|
('ftx', 0, 9, "2021-09-01 00:00:00", "2021-09-01 08:00:00", 50.0, 0.0016680000000000002),
|
||||||
])
|
])
|
||||||
def test__calculate_funding_fees(
|
def test__calculate_funding_fees(
|
||||||
mocker,
|
mocker,
|
||||||
default_conf,
|
default_conf,
|
||||||
funding_rate_history,
|
funding_rate_history_hourly,
|
||||||
|
funding_rate_history_octohourly,
|
||||||
|
rate_start,
|
||||||
|
rate_end,
|
||||||
mark_ohlcv,
|
mark_ohlcv,
|
||||||
exchange,
|
exchange,
|
||||||
d1,
|
d1,
|
||||||
@ -3585,6 +3470,11 @@ def test__calculate_funding_fees(
|
|||||||
'''
|
'''
|
||||||
d1 = datetime.strptime(f"{d1} +0000", '%Y-%m-%d %H:%M:%S %z')
|
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')
|
d2 = datetime.strptime(f"{d2} +0000", '%Y-%m-%d %H:%M:%S %z')
|
||||||
|
funding_rate_history = {
|
||||||
|
'binance': funding_rate_history_octohourly,
|
||||||
|
'ftx': funding_rate_history_hourly,
|
||||||
|
'gateio': funding_rate_history_octohourly,
|
||||||
|
}[exchange][rate_start:rate_end]
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.fetch_funding_rate_history = MagicMock(return_value=funding_rate_history)
|
api_mock.fetch_funding_rate_history = MagicMock(return_value=funding_rate_history)
|
||||||
api_mock.fetch_ohlcv = MagicMock(return_value=mark_ohlcv)
|
api_mock.fetch_ohlcv = MagicMock(return_value=mark_ohlcv)
|
||||||
@ -3596,39 +3486,28 @@ def test__calculate_funding_fees(
|
|||||||
assert funding_fees == expected_fees
|
assert funding_fees == expected_fees
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('name,expected_fees_8,expected_fees_10,expected_fees_12', [
|
@ pytest.mark.parametrize('exchange,expected_fees', [
|
||||||
('binance', -0.0009140999999999999, -0.0009140999999999999, -0.0009140999999999999),
|
('binance', -0.0009140999999999999),
|
||||||
# TODO: Uncoment once _calculate_funding_fees can pas time_in_ratio to exchange._get_funding_fee
|
('gateio', -0.0009140999999999999),
|
||||||
# ('kraken', -0.0014937, -0.0014937, 0.0045759),
|
|
||||||
('ftx', 0.0010008000000000003, 0.0021084, 0.0146691),
|
|
||||||
('gateio', -0.0009140999999999999, -0.0009140999999999999, -0.0009140999999999999),
|
|
||||||
])
|
])
|
||||||
def test__calculate_funding_fees_datetime_called(
|
def test__calculate_funding_fees_datetime_called(
|
||||||
mocker,
|
mocker,
|
||||||
default_conf,
|
default_conf,
|
||||||
funding_rate_history,
|
funding_rate_history_octohourly,
|
||||||
mark_ohlcv,
|
mark_ohlcv,
|
||||||
name,
|
exchange,
|
||||||
time_machine,
|
time_machine,
|
||||||
expected_fees_8,
|
expected_fees
|
||||||
expected_fees_10,
|
|
||||||
expected_fees_12
|
|
||||||
):
|
):
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.fetch_ohlcv = MagicMock(return_value=mark_ohlcv)
|
api_mock.fetch_ohlcv = MagicMock(return_value=mark_ohlcv)
|
||||||
api_mock.fetch_funding_rate_history = MagicMock(return_value=funding_rate_history)
|
api_mock.fetch_funding_rate_history = MagicMock(return_value=funding_rate_history_octohourly)
|
||||||
type(api_mock).has = PropertyMock(return_value={'fetchOHLCV': True})
|
type(api_mock).has = PropertyMock(return_value={'fetchOHLCV': True})
|
||||||
type(api_mock).has = PropertyMock(return_value={'fetchFundingRateHistory': True})
|
type(api_mock).has = PropertyMock(return_value={'fetchFundingRateHistory': True})
|
||||||
|
|
||||||
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=name)
|
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange)
|
||||||
d1 = datetime.strptime("2021-09-01 00:00:00 +0000", '%Y-%m-%d %H:%M:%S %z')
|
d1 = datetime.strptime("2021-09-01 00:00:00 +0000", '%Y-%m-%d %H:%M:%S %z')
|
||||||
|
|
||||||
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
||||||
funding_fees = exchange._calculate_funding_fees('ADA/USDT', 30.0, d1)
|
funding_fees = exchange._calculate_funding_fees('ADA/USDT', 30.0, d1)
|
||||||
assert funding_fees == expected_fees_8
|
assert funding_fees == expected_fees
|
||||||
time_machine.move_to("2021-09-01 10:00:00 +00:00")
|
|
||||||
funding_fees = exchange._calculate_funding_fees('ADA/USDT', 30.0, d1)
|
|
||||||
assert funding_fees == expected_fees_10
|
|
||||||
time_machine.move_to("2021-09-01 12:00:00 +00:00")
|
|
||||||
funding_fees = exchange._calculate_funding_fees('ADA/USDT', 30.0, d1)
|
|
||||||
assert funding_fees == expected_fees_12
|
|
||||||
|
@ -4761,7 +4761,19 @@ def test_update_funding_fees(
|
|||||||
default_conf['collateral'] = 'isolated'
|
default_conf['collateral'] = 'isolated'
|
||||||
default_conf['dry_run'] = True
|
default_conf['dry_run'] = True
|
||||||
|
|
||||||
funding_rates = {
|
funding_rates_midnight = {
|
||||||
|
"LTC/BTC": {
|
||||||
|
1630454400000: 0.00032583,
|
||||||
|
},
|
||||||
|
"ETH/BTC": {
|
||||||
|
1630454400000: 0.0001,
|
||||||
|
},
|
||||||
|
"XRP/BTC": {
|
||||||
|
1630454400000: 0.00049426,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
funding_rates_eight = {
|
||||||
"LTC/BTC": {
|
"LTC/BTC": {
|
||||||
1630454400000: 0.00032583,
|
1630454400000: 0.00032583,
|
||||||
1630483200000: 0.00024472,
|
1630483200000: 0.00024472,
|
||||||
@ -4798,7 +4810,7 @@ def test_update_funding_fees(
|
|||||||
|
|
||||||
mocker.patch(
|
mocker.patch(
|
||||||
'freqtrade.exchange.Exchange.get_funding_rate_history',
|
'freqtrade.exchange.Exchange.get_funding_rate_history',
|
||||||
side_effect=lambda pair, since: funding_rates[pair]
|
side_effect=lambda pair, since: funding_rates_midnight[pair]
|
||||||
)
|
)
|
||||||
|
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
@ -4827,17 +4839,21 @@ def test_update_funding_fees(
|
|||||||
assert trade.funding_fees == (
|
assert trade.funding_fees == (
|
||||||
trade.amount *
|
trade.amount *
|
||||||
mark_prices[trade.pair][1630454400000] *
|
mark_prices[trade.pair][1630454400000] *
|
||||||
funding_rates[trade.pair][1630454400000]
|
funding_rates_midnight[trade.pair][1630454400000]
|
||||||
)
|
)
|
||||||
mocker.patch('freqtrade.exchange.Exchange.create_order', return_value=open_exit_order)
|
mocker.patch('freqtrade.exchange.Exchange.create_order', return_value=open_exit_order)
|
||||||
# create_mock_trades(fee, False)
|
# create_mock_trades(fee, False)
|
||||||
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
time_machine.move_to("2021-09-01 08:00:00 +00:00")
|
||||||
|
mocker.patch(
|
||||||
|
'freqtrade.exchange.Exchange.get_funding_rate_history',
|
||||||
|
side_effect=lambda pair, since: funding_rates_eight[pair]
|
||||||
|
)
|
||||||
if schedule_off:
|
if schedule_off:
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
assert trade.funding_fees == (
|
assert trade.funding_fees == (
|
||||||
trade.amount *
|
trade.amount *
|
||||||
mark_prices[trade.pair][1630454400000] *
|
mark_prices[trade.pair][1630454400000] *
|
||||||
funding_rates[trade.pair][1630454400000]
|
funding_rates_eight[trade.pair][1630454400000]
|
||||||
)
|
)
|
||||||
freqtrade.execute_trade_exit(
|
freqtrade.execute_trade_exit(
|
||||||
trade=trade,
|
trade=trade,
|
||||||
@ -4853,5 +4869,5 @@ def test_update_funding_fees(
|
|||||||
assert trade.funding_fees == sum([
|
assert trade.funding_fees == sum([
|
||||||
trade.amount *
|
trade.amount *
|
||||||
mark_prices[trade.pair][time] *
|
mark_prices[trade.pair][time] *
|
||||||
funding_rates[trade.pair][time] for time in mark_prices[trade.pair].keys()
|
funding_rates_eight[trade.pair][time] for time in mark_prices[trade.pair].keys()
|
||||||
])
|
])
|
||||||
|
Loading…
Reference in New Issue
Block a user