feat: add futures validation to validate_exchange

This commit is contained in:
Matthias
2026-01-02 11:02:04 +01:00
parent f2dfe1788a
commit 4d4fee9874
3 changed files with 14 additions and 5 deletions

View File

@@ -47,7 +47,7 @@ def check_exchange(config: Config, check_for_bad: bool = True) -> bool:
f"{', '.join(available_exchanges())}"
)
valid, reason, _ = validate_exchange(exchange)
valid, reason, _, _ = validate_exchange(exchange)
if not valid:
if check_for_bad:
raise OperationalException(

View File

@@ -22,6 +22,7 @@ from ccxt import (
from freqtrade.exchange.common import (
BAD_EXCHANGES,
EXCHANGE_HAS_OPTIONAL,
EXCHANGE_HAS_OPTIONAL_FUTURES,
EXCHANGE_HAS_REQUIRED,
MAP_EXCHANGE_CHILDCLASS,
SUPPORTED_EXCHANGES,
@@ -68,7 +69,7 @@ def _exchange_has_helper(ex_mod: ccxt.Exchange, required: dict[str, list[str]])
]
def validate_exchange(exchange: str) -> tuple[bool, str, ccxt.Exchange | None]:
def validate_exchange(exchange: str) -> tuple[bool, str, str, ccxt.Exchange | None]:
"""
returns: can_use, reason, exchange_object
with Reason including both missing and missing_opt
@@ -79,10 +80,11 @@ def validate_exchange(exchange: str) -> tuple[bool, str, ccxt.Exchange | None]:
ex_mod = getattr(ccxt.async_support, exchange.lower())()
if not ex_mod or not ex_mod.has:
return False, "", None
return False, "", "", None
result = True
reasons = []
reasons_fut = ""
missing = _exchange_has_helper(ex_mod, EXCHANGE_HAS_REQUIRED)
if missing:
result = False
@@ -90,6 +92,8 @@ def validate_exchange(exchange: str) -> tuple[bool, str, ccxt.Exchange | None]:
missing_opt = _exchange_has_helper(ex_mod, EXCHANGE_HAS_OPTIONAL)
missing_futures = _exchange_has_helper(ex_mod, EXCHANGE_HAS_OPTIONAL_FUTURES)
if exchange.lower() in BAD_EXCHANGES:
result = False
reasons.append(BAD_EXCHANGES.get(exchange.lower(), ""))
@@ -97,14 +101,17 @@ def validate_exchange(exchange: str) -> tuple[bool, str, ccxt.Exchange | None]:
if missing_opt:
reasons.append(f"missing opt: {', '.join(missing_opt)}")
return result, "; ".join(reasons), ex_mod
if missing_futures:
reasons_fut = f"missing futures opt: {', '.join(missing_futures)}"
return result, "; ".join(reasons), reasons_fut, ex_mod
def _build_exchange_list_entry(
exchange_name: str, exchangeClasses: dict[str, Any]
) -> ValidExchangesType:
exchange_name = exchange_name.lower()
valid, comment, ex_mod = validate_exchange(exchange_name)
valid, comment, comment_fut, ex_mod = validate_exchange(exchange_name)
mapped_exchange_name = MAP_EXCHANGE_CHILDCLASS.get(exchange_name, exchange_name).lower()
is_alias = getattr(ex_mod, "alias", False)
result: ValidExchangesType = {
@@ -113,6 +120,7 @@ def _build_exchange_list_entry(
"valid": valid,
"supported": mapped_exchange_name in SUPPORTED_EXCHANGES and not is_alias,
"comment": comment,
"comment_futures": comment_fut,
"dex": getattr(ex_mod, "dex", False),
"is_alias": is_alias,
"alias_for": inspect.getmro(ex_mod.__class__)[1]().id

View File

@@ -14,6 +14,7 @@ class ValidExchangesType(TypedDict):
valid: bool
supported: bool
comment: str
comment_futures: str
dex: bool
is_alias: bool
alias_for: str | None