|
1 | 1 | import logging |
| 2 | +import time |
2 | 3 | from datetime import datetime, timedelta |
3 | 4 |
|
4 | 5 | import ccxt |
5 | 6 |
|
6 | 7 | from freqtrade.constants import BuySell |
7 | | -from freqtrade.enums import MarginMode, PriceType, TradingMode |
| 8 | +from freqtrade.enums import TRADE_MODES, MarginMode, PriceType, TradingMode |
8 | 9 | from freqtrade.exceptions import DDosProtection, ExchangeError, OperationalException, TemporaryError |
9 | 10 | from freqtrade.exchange import Exchange |
10 | 11 | from freqtrade.exchange.common import retrier |
11 | 12 | from freqtrade.exchange.exchange_types import CcxtOrder, FtHas |
12 | 13 | from freqtrade.misc import deep_merge_dicts |
| 14 | +from freqtrade.util.datetime_helpers import dt_from_ts |
13 | 15 |
|
14 | 16 |
|
15 | 17 | logger = logging.getLogger(__name__) |
@@ -54,6 +56,7 @@ class Bybit(Exchange): |
54 | 56 | "exchange_has_overrides": { |
55 | 57 | "fetchOrder": True, |
56 | 58 | }, |
| 59 | + "has_delisting": True, |
57 | 60 | } |
58 | 61 |
|
59 | 62 | _supported_trading_mode_margin_pairs: list[tuple[TradingMode, MarginMode]] = [ |
@@ -294,3 +297,35 @@ def get_leverage_tiers(self) -> dict[str, list[dict]]: |
294 | 297 |
|
295 | 298 | self.cache_leverage_tiers(tiers, self._config["stake_currency"]) |
296 | 299 | return tiers |
| 300 | + |
| 301 | + def check_delisting_time(self, pair: str) -> datetime | None: |
| 302 | + """ |
| 303 | + Check if the pair gonna be delisted. |
| 304 | + By default, it returns None. |
| 305 | + :param pair: Market symbol |
| 306 | + :return: Datetime if the pair gonna be delisted, None otherwise |
| 307 | + """ |
| 308 | + if self._config["runmode"] not in TRADE_MODES: |
| 309 | + return None |
| 310 | + |
| 311 | + if self.trading_mode == TradingMode.FUTURES: |
| 312 | + return self._check_delisting_futures(pair) |
| 313 | + return None |
| 314 | + |
| 315 | + def _check_delisting_futures(self, pair: str) -> datetime | None: |
| 316 | + delivery_time = self.markets.get(pair, {}).get("info", {}).get("deliveryTime", 0) |
| 317 | + if delivery_time: |
| 318 | + if isinstance(delivery_time, str) and (delivery_time != ""): |
| 319 | + delivery_time = int(delivery_time) |
| 320 | + |
| 321 | + if not isinstance(delivery_time, int) or delivery_time <= 0: |
| 322 | + return None |
| 323 | + |
| 324 | + max_delivery = int(time.time() * 1000) + ( |
| 325 | + 14 * 24 * 60 * 60 * 1000 |
| 326 | + ) # Assume exchange don't announce delisting more than 14 days in advance |
| 327 | + |
| 328 | + if delivery_time < max_delivery: |
| 329 | + return dt_from_ts(delivery_time) |
| 330 | + |
| 331 | + return None |
0 commit comments