switch to use dataprovider to give flexibility to users

This commit is contained in:
Stefano
2025-09-16 14:59:44 +09:00
parent d069f5477e
commit 03c67d6a3b
7 changed files with 51 additions and 44 deletions

View File

@@ -604,3 +604,19 @@ class DataProvider:
if always_send or message not in self.__msg_cache:
self._msg_queue.append(message)
self.__msg_cache[message] = True
def check_delisting(self, pair: str) -> datetime | None:
"""
Check if a pair gonna be delisted on the exchange.
Will only return datetime if the pair is gonna be delisted.
:param pair: Pair to check
:return: Datetime of the pair's delisting, None otherwise
"""
if self._exchange is None:
raise OperationalException(NO_EXCHANGE_EXCEPTION)
try:
return self._exchange.check_delisting_time(pair)
except ExchangeError:
logger.warning(f"Could not fetch market data for {pair}. Assuming no delisting.")
return None

View File

@@ -59,7 +59,6 @@ class Binance(Exchange):
"BNFCR": "USDC",
"BFUSD": "USDT",
},
"delivery_column": "deliveryDate",
}
_supported_trading_mode_margin_pairs: list[tuple[TradingMode, MarginMode]] = [
@@ -433,3 +432,31 @@ class Binance(Exchange):
return await super()._async_get_trade_history_id(
pair, until=until, since=since, from_id=from_id
)
def check_delisting_futures(self, pair: str) -> datetime | None:
delivery_time = self.markets.get(pair, {}).get("info", {}).get("deliveryDate", None)
if delivery_time:
if isinstance(delivery_time, str) and (delivery_time != ""):
delivery_time = int(delivery_time)
# Binance set a very high delivery time for all perpetuals.
# We compare with delivery time of BTC/USDT:USDT which assumed to never be delisted
btc_delivery_time = (
self.markets.get("BTC/USDT:USDT", {}).get("info", {}).get("deliveryDate", None)
)
if delivery_time == btc_delivery_time:
return None
delivery_time = dt_from_ts(delivery_time)
return delivery_time
def check_delisting_spot(self, pair: str) -> datetime | None:
return None
def check_delisting_time(self, pair: str) -> datetime | None:
if self.trading_mode == TradingMode.SPOT:
return self.check_delisting_spot(pair)
return self.check_delisting_futures(pair)

View File

@@ -59,7 +59,6 @@ class Bybit(Exchange):
"exchange_has_overrides": {
"fetchOrder": True,
},
"delivery_column": "deliveryTime",
}
_supported_trading_mode_margin_pairs: list[tuple[TradingMode, MarginMode]] = [

View File

@@ -3912,31 +3912,13 @@ class Exchange:
else:
raise ExchangeError(f"Cannot get maintenance ratio using {self.name}")
def check_delivery_time(self, pair: str) -> int:
def check_delisting_time(self, pair: str) -> datetime | None:
"""
Check if the futures contract is a delivery contract
Check if the pair gonna be delisted.
This function should be overridden by the exchange class if the exchange
provides such information.
By default, it returns None.
:param pair: Market symbol
:return: True if the contract is a delivery contract, False otherwise
:return: Datetime if the pair gonna be delisted, None otherwise
"""
if self.trading_mode != TradingMode.FUTURES:
return 0
column_to_check = self._ft_has.get("delivery_column", "")
delivery_time = self.markets.get(pair, {}).get("info", {}).get(column_to_check, None)
if delivery_time:
if isinstance(delivery_time, str) and (delivery_time != ""):
delivery_time = int(delivery_time)
if self.name == "Binance":
# Binance set a very high delivery time for all perpetuals.
# We compare with delivery time of BTC/USDT:USDT which assumed to never be delisted
btc_delivery_time = (
self.markets.get("BTC/USDT:USDT", {}).get("info", {}).get(column_to_check, None)
)
if delivery_time == btc_delivery_time:
return 0
return delivery_time
return 0
return None

View File

@@ -63,9 +63,6 @@ class FtHas(TypedDict, total=False):
# Websocket control
ws_enabled: bool
# Delisting checks
delivery_column: str
class Ticker(TypedDict):
symbol: str

View File

@@ -46,7 +46,6 @@ class Okx(Exchange):
},
"stoploss_blocks_assets": False,
"ws_enabled": True,
"delivery_column": "expTime",
}
_supported_trading_mode_margin_pairs: list[tuple[TradingMode, MarginMode]] = [

View File

@@ -661,19 +661,6 @@ class FreqtradeBot(LoggingMixin):
"""
logger.debug(f"create_trade for pair {pair}")
delivery_time = self.exchange.check_delivery_time(pair)
if delivery_time:
delivery_date = dt_from_ts(delivery_time)
logger.info(
f"Pair {pair} has a delivery time of "
f"{delivery_date.strftime(constants.DATETIME_PRINT_FORMAT)}."
)
if pair not in self.pairlists.blacklist:
self.pairlists.blacklist.append(pair)
return False
analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(pair, self.strategy.timeframe)
nowtime = analyzed_df.iloc[-1]["date"] if len(analyzed_df) > 0 else None