feat: add "current funding fee" endpoint

part of #12206
This commit is contained in:
Matthias
2025-09-06 10:06:59 +02:00
parent 816ca2ea15
commit 95ad756909
3 changed files with 45 additions and 2 deletions

View File

@@ -23,7 +23,7 @@ from freqtrade.data.history import get_datahandler, load_pair_history
from freqtrade.enums import CandleType, RPCMessageType, RunMode, TradingMode from freqtrade.enums import CandleType, RPCMessageType, RunMode, TradingMode
from freqtrade.exceptions import ExchangeError, OperationalException from freqtrade.exceptions import ExchangeError, OperationalException
from freqtrade.exchange import Exchange, timeframe_to_prev_date, timeframe_to_seconds 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.misc import append_candles_to_dataframe
from freqtrade.rpc import RPCManager from freqtrade.rpc import RPCManager
from freqtrade.rpc.rpc_types import RPCAnalyzedDFMsg from freqtrade.rpc.rpc_types import RPCAnalyzedDFMsg
@@ -548,6 +548,7 @@ class DataProvider:
def ticker(self, pair: str): def ticker(self, pair: str):
""" """
Return last ticker data from exchange Return last ticker data from exchange
Warning: Performs a network request - so use with common sense.
:param pair: Pair to get the data for :param pair: Pair to get the data for
:return: Ticker dict from exchange or empty dict if ticker is not available for the pair :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: def orderbook(self, pair: str, maximum: int) -> OrderBook:
""" """
Fetch latest l2 orderbook data 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 pair: pair to get the data for
:param maximum: Maximum number of orderbook entries to query :param maximum: Maximum number of orderbook entries to query
:return: dict including bids/asks with a total of `maximum` entries. :return: dict including bids/asks with a total of `maximum` entries.
@@ -570,6 +571,22 @@ class DataProvider:
raise OperationalException(NO_EXCHANGE_EXCEPTION) raise OperationalException(NO_EXCHANGE_EXCEPTION)
return self._exchange.fetch_l2_order_book(pair, maximum) 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: def send_msg(self, message: str, *, always_send: bool = False) -> None:
""" """
Send custom RPC Notifications from your bot. Send custom RPC Notifications from your bot.

View File

@@ -73,6 +73,7 @@ from freqtrade.exchange.exchange_types import (
CcxtOrder, CcxtOrder,
CcxtPosition, CcxtPosition,
FtHas, FtHas,
FundingRate,
OHLCVResponse, OHLCVResponse,
OrderBook, OrderBook,
Ticker, Ticker,
@@ -2001,6 +2002,28 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) from 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 @staticmethod
def get_next_limit_in_list( def get_next_limit_in_list(
limit: int, limit: int,

View File

@@ -1,5 +1,8 @@
from typing import Any, Literal, TypedDict from typing import Any, Literal, TypedDict
# Re-export for easier use
from ccxt.base.types import FundingRate # noqa: F401
from freqtrade.enums import CandleType from freqtrade.enums import CandleType