Compare commits

...

10 Commits

Author SHA1 Message Date
Jakub W.
bf088f3d4d
Merge 5ec04d168e into ae41ab101a 2024-09-15 21:34:58 +02:00
Jakub Werner (jakubikan)
5ec04d168e removing sandbox mode 2024-03-23 12:39:40 +01:00
Jakub Werner (jakubikan)
26afad8bc1 adding some addtional test and makine cache a bit better 2024-03-23 12:27:59 +01:00
Jakub Werner (jakubikan)
80dd586dc7 fix 2024-03-23 11:28:34 +01:00
Jakub Werner (jakubikan)
78d189564f JW; testing with sandbox mode 2024-03-23 11:26:26 +01:00
Jakub Werner (jakubikan)
2b0b85330e works also without __class__ 2024-03-22 21:40:36 +01:00
Jakub Werner (jakubikan)
4257e1ca96 JW: reverting pep8 changes 2024-03-22 21:33:38 +01:00
Jakub Werner (jakubikan)
ff2eaeb3b4 making ruff happy 2024-03-22 21:29:33 +01:00
Jakub Werner (jakubikan)
cbc98d384e Updating delisting function to return the time when it will delist if it is delisting 2024-03-22 21:17:17 +01:00
Jakub Werner (jakubikan)
4ef45314dd JW: adding first draft for deslist schedule 2024-03-22 20:18:52 +01:00
2 changed files with 75 additions and 0 deletions

View File

@ -6,6 +6,8 @@ from pathlib import Path
from typing import Dict, List, Optional, Tuple
import ccxt
from cachetools import TTLCache, cached
from threading import Lock
from freqtrade.enums import CandleType, MarginMode, PriceType, TradingMode
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
@ -53,6 +55,11 @@ class Binance(Exchange):
(TradingMode.FUTURES, MarginMode.ISOLATED)
]
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self._spot_delist_schedule_cache: TTLCache = TTLCache(maxsize=100, ttl=300)
self._spot_delist_schedule_cache_lock = Lock()
def get_tickers(self, symbols: Optional[List[str]] = None, cached: bool = False) -> Tickers:
tickers = super().get_tickers(symbols=symbols, cached=cached)
if self.trading_mode == TradingMode.FUTURES:
@ -214,3 +221,58 @@ class Binance(Exchange):
return self.get_leverage_tiers()
else:
return {}
@retrier
@cached(cache=TTLCache(maxsize=100, ttl=10), lock=Lock())
def get_deslist_schedule(self):
try:
delist_schedule = self._api.sapi_get_spot_delist_schedule()
return delist_schedule
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not get delist schedule {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
def get_spot_pair_delist_time(self, pair, refresh: bool = True) -> int | None:
"""
Get the delisting time for a pair if it will be delisted
:param pair: Pair to get the delisting time for
:param refresh: true if you need fresh data
:return: int: delisting time None if not delisting
"""
if not pair:
return
cache = self._spot_delist_schedule_cache
lock = self._spot_delist_schedule_cache_lock
schedule_pair = pair.replace('/', '')
if not refresh:
with lock:
delist_time = cache[f"{schedule_pair}"]
if delist_time:
return delist_time
delist_schedule = self.get_deslist_schedule()
if delist_schedule is None:
return None
with lock:
for schedule in delist_schedule:
for symbol in schedule['symbols']:
cache[f"{symbol}"] = int(schedule['delistTime'])
with lock:
return cache.get(f"{schedule_pair}")

View File

@ -723,3 +723,16 @@ def test_get_maintenance_ratio_and_amt_binance(
exchange._leverage_tiers = leverage_tiers
(result_ratio, result_amt) = exchange.get_maintenance_ratio_and_amt(pair, notional_value)
assert (round(result_ratio, 8), round(result_amt, 8)) == (mm_ratio, amt)
def test_get_spot_delist_schedule(mocker, default_conf) -> None:
exchange = get_patched_exchange(mocker, default_conf, id='binance')
return_value = [{
'delistTime': '1712113200000',
'symbols': ['DREPBTC', 'DREPUSDT', 'MOBBTC', 'MOBUSDT', 'PNTUSDT']
}]
exchange._api.sapi_get_spot_delist_schedule = MagicMock(return_value=return_value)
assert exchange.get_spot_pair_delist_time('DREP/USDT') == 1712113200000
assert exchange.get_spot_pair_delist_time('BTC/USDT') is None