diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 0f30c7aa4..a87a5dc55 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -1,7 +1,7 @@ """ Binance exchange subclass """ import logging from datetime import datetime -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional import arrow import ccxt @@ -27,6 +27,13 @@ class Binance(Exchange): "l2_limit_range": [5, 10, 20, 50, 100, 500, 1000], } funding_fee_times: List[int] = [0, 8, 16] # hours of the day + _funding_interest_rates: Dict = {} # TODO-lev: delete + + def __init__(self, config: Dict[str, Any], validate: bool = True) -> None: + super().__init__(config, validate) + # TODO-lev: Uncomment once lev-exchange merged in + # if self.trading_mode == TradingMode.FUTURES: + # self._funding_interest_rates = self._get_funding_interest_rates() def stoploss_adjust(self, stop_loss: float, order: Dict) -> bool: """ @@ -94,12 +101,27 @@ class Binance(Exchange): except ccxt.BaseError as e: raise OperationalException(e) from e + def _get_premium_index(self, pair: str, date: datetime) -> float: + raise OperationalException(f'_get_premium_index has not been implemented on {self.name}') + + def _get_mark_price(self, pair: str, date: datetime) -> float: + raise OperationalException(f'_get_mark_price has not been implemented on {self.name}') + + def _get_funding_interest_rates(self): + rates = self._api.fetch_funding_rates() + interest_rates = {} + for pair, data in rates.items(): + interest_rates[pair] = data['interestRate'] + return interest_rates + def _calculate_funding_rate(self, pair: str, premium_index: float) -> Optional[float]: """ Get's the funding_rate for a pair at a specific date and time in the past """ - # TODO-lev: implement - raise OperationalException("_get_funding_rate has not been implement on binance") + return ( + premium_index + + max(min(self._funding_interest_rates[pair] - premium_index, 0.0005), -0.0005) + ) def _get_funding_fee( self, @@ -117,13 +139,12 @@ class Binance(Exchange): - premium: varies by price difference between the perpetual contract and mark price """ if premium_index is None: - raise OperationalException("Funding rate cannot be None for Binance._get_funding_fee") + raise OperationalException("Premium index cannot be None for Binance._get_funding_fee") nominal_value = mark_price * contract_size funding_rate = self._calculate_funding_rate(pair, premium_index) if funding_rate is None: raise OperationalException("Funding rate should never be none on Binance") - adjustment = nominal_value * funding_rate - return adjustment + return nominal_value * funding_rate async def _async_get_historic_ohlcv(self, pair: str, timeframe: str, since_ms: int, is_new_pair: bool diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index e58493f60..7e1fb9e57 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1567,6 +1567,12 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e + def _get_premium_index(self, pair: str, date: datetime) -> float: + raise OperationalException(f'_get_premium_index has not been implemented on {self.name}') + + def _get_mark_price(self, pair: str, date: datetime) -> float: + raise OperationalException(f'_get_mark_price has not been implemented on {self.name}') + def _get_funding_rate(self, pair: str, when: datetime): """ Get's the funding_rate for a pair at a specific date and time in the past @@ -1625,9 +1631,14 @@ class Exchange: fees: float = 0 for date in self._get_funding_fee_dates(open_date, close_date): - funding_rate = self._get_funding_rate(pair, date) + premium_index = self._get_premium_index(pair, date) mark_price = self._get_mark_price(pair, date) - fees += self._get_funding_fee(amount, mark_price, funding_rate) + fees += self._get_funding_fee( + pair=pair, + contract_size=amount, + mark_price=mark_price, + premium_index=premium_index + ) return fees