From 95ad75690969d3483a3fcf4975126a61bf95aa7a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Sep 2025 10:06:59 +0200 Subject: [PATCH] feat: add "current funding fee" endpoint part of #12206 --- freqtrade/data/dataprovider.py | 21 +++++++++++++++++++-- freqtrade/exchange/exchange.py | 23 +++++++++++++++++++++++ freqtrade/exchange/exchange_types.py | 3 +++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index a30e4cf27..d991733f9 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -23,7 +23,7 @@ from freqtrade.data.history import get_datahandler, load_pair_history from freqtrade.enums import CandleType, RPCMessageType, RunMode, TradingMode from freqtrade.exceptions import ExchangeError, OperationalException from freqtrade.exchange import Exchange, timeframe_to_prev_date, timeframe_to_seconds -from freqtrade.exchange.exchange_types import OrderBook +from freqtrade.exchange.exchange_types import FundingRate, OrderBook from freqtrade.misc import append_candles_to_dataframe from freqtrade.rpc import RPCManager from freqtrade.rpc.rpc_types import RPCAnalyzedDFMsg @@ -548,6 +548,7 @@ class DataProvider: def ticker(self, pair: str): """ Return last ticker data from exchange + Warning: Performs a network request - so use with common sense. :param pair: Pair to get the data for :return: Ticker dict from exchange or empty dict if ticker is not available for the pair """ @@ -561,7 +562,7 @@ class DataProvider: def orderbook(self, pair: str, maximum: int) -> OrderBook: """ Fetch latest l2 orderbook data - Warning: Does a network request - so use with common sense. + Warning: Performs a network request - so use with common sense. :param pair: pair to get the data for :param maximum: Maximum number of orderbook entries to query :return: dict including bids/asks with a total of `maximum` entries. @@ -570,6 +571,22 @@ class DataProvider: raise OperationalException(NO_EXCHANGE_EXCEPTION) return self._exchange.fetch_l2_order_book(pair, maximum) + def funding_rate(self, pair: str) -> FundingRate: + """ + Return Funding rate from the exchange + Warning: Performs a network request - so use with common sense. + :param pair: Pair to get the data for + :return: Funding rate dict from exchange or empty dict if funding rate is not available + If available, the "funding_rate" field will contain the funding rate. + Actually filled fields may vary between exchanges. + """ + if self._exchange is None: + raise OperationalException(NO_EXCHANGE_EXCEPTION) + try: + return self._exchange.fetch_funding_rate(pair) + except ExchangeError: + return {} + def send_msg(self, message: str, *, always_send: bool = False) -> None: """ Send custom RPC Notifications from your bot. diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index ee28f9f9e..5151b641e 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -73,6 +73,7 @@ from freqtrade.exchange.exchange_types import ( CcxtOrder, CcxtPosition, FtHas, + FundingRate, OHLCVResponse, OrderBook, Ticker, @@ -2001,6 +2002,28 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e + @retrier + def fetch_funding_rate(self, pair: str) -> FundingRate: + """ + Get current Funding rate from exchange. + On Futures markets, this is the interest rate for holding a position. + Won't work for non-futures markets + """ + try: + return self._api.fetch_funding_rate(pair) + except ccxt.NotSupported as e: + raise OperationalException( + f"Exchange {self._api.name} does not support fetching funding rate. Message: {e}" + ) from e + except ccxt.DDoSProtection as e: + raise DDosProtection(e) from e + except (ccxt.OperationFailed, ccxt.ExchangeError) as e: + raise TemporaryError( + f"Could not get funding rate due to {e.__class__.__name__}. Message: {e}" + ) from e + except ccxt.BaseError as e: + raise OperationalException(e) from e + @staticmethod def get_next_limit_in_list( limit: int, diff --git a/freqtrade/exchange/exchange_types.py b/freqtrade/exchange/exchange_types.py index d31863307..4859b9cf9 100644 --- a/freqtrade/exchange/exchange_types.py +++ b/freqtrade/exchange/exchange_types.py @@ -1,5 +1,8 @@ from typing import Any, Literal, TypedDict +# Re-export for easier use +from ccxt.base.types import FundingRate # noqa: F401 + from freqtrade.enums import CandleType