mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 02:12:01 +00:00
Compare commits
34 Commits
bf088f3d4d
...
954da3298f
Author | SHA1 | Date | |
---|---|---|---|
|
954da3298f | ||
|
2fe67edab3 | ||
|
167e43cbef | ||
|
d8cb407c25 | ||
|
9452afe3f7 | ||
|
8dc6d9ce7d | ||
|
bf4b8a318d | ||
|
20f6022050 | ||
|
65e6c737cd | ||
|
6d2572e347 | ||
|
52a35197c7 | ||
|
2b3a41db3e | ||
|
09c1459411 | ||
|
98f18b89da | ||
|
4249db4330 | ||
|
a7f46500ed | ||
|
c73fa2b0eb | ||
|
db4c4b971a | ||
|
e9ccc98ada | ||
|
11d6ec33b3 | ||
|
c3b6f4ca85 | ||
|
d37405a307 | ||
|
d7a9841328 | ||
|
cf3af42477 | ||
|
ad8e6e7d67 | ||
|
5ec04d168e | ||
|
26afad8bc1 | ||
|
80dd586dc7 | ||
|
78d189564f | ||
|
2b0b85330e | ||
|
4257e1ca96 | ||
|
ff2eaeb3b4 | ||
|
cbc98d384e | ||
|
4ef45314dd |
|
@ -16,7 +16,7 @@ repos:
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- types-cachetools==5.5.0.20240820
|
- types-cachetools==5.5.0.20240820
|
||||||
- types-filelock==3.2.7
|
- types-filelock==3.2.7
|
||||||
- types-requests==2.32.0.20240907
|
- types-requests==2.32.0.20240914
|
||||||
- types-tabulate==0.9.0.20240106
|
- types-tabulate==0.9.0.20240106
|
||||||
- types-python-dateutil==2.9.0.20240906
|
- types-python-dateutil==2.9.0.20240906
|
||||||
- SQLAlchemy==2.0.34
|
- SQLAlchemy==2.0.34
|
||||||
|
|
|
@ -6,6 +6,8 @@ from pathlib import Path
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import ccxt
|
import ccxt
|
||||||
|
from cachetools import TTLCache, cached
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
from freqtrade.enums import CandleType, MarginMode, PriceType, TradingMode
|
from freqtrade.enums import CandleType, MarginMode, PriceType, TradingMode
|
||||||
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
|
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
|
||||||
|
@ -53,6 +55,11 @@ class Binance(Exchange):
|
||||||
(TradingMode.FUTURES, MarginMode.ISOLATED)
|
(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:
|
def get_tickers(self, symbols: Optional[List[str]] = None, cached: bool = False) -> Tickers:
|
||||||
tickers = super().get_tickers(symbols=symbols, cached=cached)
|
tickers = super().get_tickers(symbols=symbols, cached=cached)
|
||||||
if self.trading_mode == TradingMode.FUTURES:
|
if self.trading_mode == TradingMode.FUTURES:
|
||||||
|
@ -214,3 +221,58 @@ class Binance(Exchange):
|
||||||
return self.get_leverage_tiers()
|
return self.get_leverage_tiers()
|
||||||
else:
|
else:
|
||||||
return {}
|
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}")
|
||||||
|
|
|
@ -3594,7 +3594,7 @@ class Exchange:
|
||||||
Wherein, "+" or "-" depends on whether the contract goes long or short:
|
Wherein, "+" or "-" depends on whether the contract goes long or short:
|
||||||
"-" for long, and "+" for short.
|
"-" for long, and "+" for short.
|
||||||
|
|
||||||
okex: https://www.okex.com/support/hc/en-us/articles/
|
okex: https://www.okx.com/support/hc/en-us/articles/
|
||||||
360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin
|
360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin
|
||||||
|
|
||||||
:param pair: Pair to calculate liquidation price for
|
:param pair: Pair to calculate liquidation price for
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
-r docs/requirements-docs.txt
|
-r docs/requirements-docs.txt
|
||||||
|
|
||||||
coveralls==4.0.1
|
coveralls==4.0.1
|
||||||
ruff==0.6.4
|
ruff==0.6.5
|
||||||
mypy==1.11.2
|
mypy==1.11.2
|
||||||
pre-commit==3.8.0
|
pre-commit==3.8.0
|
||||||
pytest==8.3.2
|
pytest==8.3.3
|
||||||
pytest-asyncio==0.24.0
|
pytest-asyncio==0.24.0
|
||||||
pytest-cov==5.0.0
|
pytest-cov==5.0.0
|
||||||
pytest-mock==3.14.0
|
pytest-mock==3.14.0
|
||||||
|
@ -27,6 +27,6 @@ nbconvert==7.16.4
|
||||||
# mypy types
|
# mypy types
|
||||||
types-cachetools==5.5.0.20240820
|
types-cachetools==5.5.0.20240820
|
||||||
types-filelock==3.2.7
|
types-filelock==3.2.7
|
||||||
types-requests==2.32.0.20240907
|
types-requests==2.32.0.20240914
|
||||||
types-tabulate==0.9.0.20240106
|
types-tabulate==0.9.0.20240106
|
||||||
types-python-dateutil==2.9.0.20240906
|
types-python-dateutil==2.9.0.20240906
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
-r requirements-plot.txt
|
-r requirements-plot.txt
|
||||||
|
|
||||||
# Required for freqai
|
# Required for freqai
|
||||||
scikit-learn==1.5.1
|
scikit-learn==1.5.2
|
||||||
joblib==1.4.2
|
joblib==1.4.2
|
||||||
catboost==1.2.7; 'arm' not in platform_machine
|
catboost==1.2.7; 'arm' not in platform_machine
|
||||||
# Pin Matplotlib - it's depended on by catboost
|
# Pin Matplotlib - it's depended on by catboost
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
# Required for hyperopt
|
# Required for hyperopt
|
||||||
scipy==1.14.1; python_version >= "3.10"
|
scipy==1.14.1; python_version >= "3.10"
|
||||||
scipy==1.13.1; python_version < "3.10"
|
scipy==1.13.1; python_version < "3.10"
|
||||||
scikit-learn==1.5.1
|
scikit-learn==1.5.2
|
||||||
ft-scikit-optimize==0.9.2
|
ft-scikit-optimize==0.9.2
|
||||||
filelock==3.16.0
|
filelock==3.16.0
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Include all requirements to run the bot.
|
# Include all requirements to run the bot.
|
||||||
-r requirements.txt
|
-r requirements.txt
|
||||||
|
|
||||||
plotly==5.24.0
|
plotly==5.24.1
|
||||||
|
|
|
@ -4,7 +4,7 @@ bottleneck==1.4.0
|
||||||
numexpr==2.10.1
|
numexpr==2.10.1
|
||||||
pandas-ta==0.3.14b
|
pandas-ta==0.3.14b
|
||||||
|
|
||||||
ccxt==4.3.98
|
ccxt==4.4.3
|
||||||
cryptography==42.0.8; platform_machine == 'armv7l'
|
cryptography==42.0.8; platform_machine == 'armv7l'
|
||||||
cryptography==43.0.1; platform_machine != 'armv7l'
|
cryptography==43.0.1; platform_machine != 'armv7l'
|
||||||
aiohttp==3.10.5
|
aiohttp==3.10.5
|
||||||
|
@ -15,7 +15,7 @@ httpx>=0.24.1
|
||||||
humanize==4.10.0
|
humanize==4.10.0
|
||||||
cachetools==5.5.0
|
cachetools==5.5.0
|
||||||
requests==2.32.3
|
requests==2.32.3
|
||||||
urllib3==2.2.2
|
urllib3==2.2.3
|
||||||
jsonschema==4.23.0
|
jsonschema==4.23.0
|
||||||
TA-Lib==0.4.32
|
TA-Lib==0.4.32
|
||||||
technical==1.4.4
|
technical==1.4.4
|
||||||
|
@ -26,7 +26,7 @@ jinja2==3.1.4
|
||||||
tables==3.9.1; python_version < "3.10"
|
tables==3.9.1; python_version < "3.10"
|
||||||
tables==3.10.1; python_version >= "3.10"
|
tables==3.10.1; python_version >= "3.10"
|
||||||
joblib==1.4.2
|
joblib==1.4.2
|
||||||
rich==13.8.0
|
rich==13.8.1
|
||||||
pyarrow==17.0.0; platform_machine != 'armv7l'
|
pyarrow==17.0.0; platform_machine != 'armv7l'
|
||||||
|
|
||||||
# find first, C search in arrays
|
# find first, C search in arrays
|
||||||
|
@ -41,8 +41,8 @@ orjson==3.10.7
|
||||||
sdnotify==0.3.2
|
sdnotify==0.3.2
|
||||||
|
|
||||||
# API Server
|
# API Server
|
||||||
fastapi==0.114.0
|
fastapi==0.114.2
|
||||||
pydantic==2.9.0
|
pydantic==2.9.1
|
||||||
uvicorn==0.30.6
|
uvicorn==0.30.6
|
||||||
pyjwt==2.9.0
|
pyjwt==2.9.0
|
||||||
aiofiles==24.1.0
|
aiofiles==24.1.0
|
||||||
|
@ -53,7 +53,7 @@ questionary==2.0.1
|
||||||
prompt-toolkit==3.0.36
|
prompt-toolkit==3.0.36
|
||||||
# Extensions to datetime library
|
# Extensions to datetime library
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
pytz==2024.1
|
pytz==2024.2
|
||||||
|
|
||||||
#Futures
|
#Futures
|
||||||
schedule==1.2.2
|
schedule==1.2.2
|
||||||
|
|
|
@ -723,3 +723,16 @@ def test_get_maintenance_ratio_and_amt_binance(
|
||||||
exchange._leverage_tiers = leverage_tiers
|
exchange._leverage_tiers = leverage_tiers
|
||||||
(result_ratio, result_amt) = exchange.get_maintenance_ratio_and_amt(pair, notional_value)
|
(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)
|
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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user