diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index cb18b7f8e..8c2713c72 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -1,6 +1,6 @@ """ Binance exchange subclass """ import logging -from typing import Dict, List +from typing import Dict, List, Optional import ccxt from datetime import time @@ -90,3 +90,23 @@ class Binance(Exchange): f'Could not place sell order due to {e.__class__.__name__}. Message: {e}') from e except ccxt.BaseError as e: raise OperationalException(e) from e + + def _get_funding_fee( + self, + contract_size: float, + mark_price: float, + funding_rate: Optional[float], + ) -> float: + """ + Calculates a single funding fee + :param contract_size: The amount/quanity + :param mark_price: The price of the asset that the contract is based off of + :param funding_rate: the interest rate and the premium + - interest rate: 0.03% daily, BNBUSDT, LINKUSDT, and LTCUSDT are 0% + - premium: varies by price difference between the perpetual contract and mark price + """ + if funding_rate is None: + raise OperationalException("Funding rate cannot be None for Binance._get_funding_fee") + nominal_value = mark_price * contract_size + adjustment = nominal_value * funding_rate + return adjustment diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index df1bf28f3..cd41f2b13 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -1526,7 +1526,7 @@ class Exchange: return self._api.fetch_funding_rates() @retrier - def get_funding_fees(self, pair: str, since: Union[datetime, int]) -> float: + def get_funding_fees_from_exchange(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) @@ -1555,6 +1555,23 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e + def _get_funding_fee( + self, + contract_size: float, + mark_price: float, + funding_rate: Optional[float], + # index_price: float, + # interest_rate: float) + ) -> float: + """ + Calculates a single funding fee + :param contract_size: The amount/quanity + :param mark_price: The price of the asset that the contract is based off of + :param funding_rate: the interest rate and the premium + - premium: varies by price difference between the perpetual contract and mark price + """ + raise OperationalException(f"Funding fee has not been implemented for {self.name}") + def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool: return exchange_name in ccxt_exchanges(ccxt_module) diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index 5b7a9ffeb..c442924fa 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -1,6 +1,6 @@ """ FTX exchange subclass """ import logging -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional import ccxt from datetime import time @@ -153,3 +153,21 @@ class Ftx(Exchange): if order['type'] == 'stop': return safe_value_fallback2(order, order, 'id_stop', 'id') return order['id'] + + def _get_funding_fee( + self, + contract_size: float, + mark_price: float, + funding_rate: Optional[float], + # index_price: float, + # interest_rate: float) + ): + """ + Calculates a single funding fee + Always paid in USD on FTX # TODO: How do we account for this + :param contract_size: The amount/quanity + :param mark_price: The price of the asset that the contract is based off of + :param funding_rate: Must be None on ftx + """ + (contract_size * mark_price) / 24 + return