krakenfutures: move ohlcv cap to _ft_has and support futures-only online tests

This commit is contained in:
matstedt
2026-01-13 20:04:08 +01:00
committed by Matthias
parent d9629c4d67
commit 04ec24e737
4 changed files with 47 additions and 32 deletions
+1 -14
View File
@@ -53,6 +53,7 @@ class KrakenFutures(Exchange):
PriceType.MARK: "mark",
PriceType.INDEX: "index",
},
"ohlcv_candle_limit": 2000,
# override ccxt has-gaps
"exchange_has_overrides": {
"fetchOrder": True,
@@ -593,19 +594,5 @@ class KrakenFutures(Exchange):
return v.strip()
return "mark"
def ohlcv_candle_limit(
self,
timeframe: str,
candle_type: CandleType,
since_ms: int | None = None,
) -> int:
limit = super().ohlcv_candle_limit(
timeframe,
candle_type=candle_type,
since_ms=since_ms,
)
return min(limit, 2000)
class Krakenfutures(KrakenFutures):
pass
+2 -2
View File
@@ -23,11 +23,11 @@ def test_krakenfutures_get_ft_has():
def test_krakenfutures_ohlcv_candle_limit_caps_at_2000(mocker, default_conf):
"""Test that OHLCV candle limit is capped at 2000."""
mocker.patch.object(Exchange, "ohlcv_candle_limit", return_value=5000)
ex = get_patched_exchange(mocker, default_conf, exchange="krakenfutures")
assert isinstance(ex, KrakenFutures)
mocker.patch.object(ex, "features", return_value=5000)
assert ex.ohlcv_candle_limit("1m", candle_type=CandleType.FUTURES) == 2000
+38 -15
View File
@@ -548,6 +548,7 @@ EXCHANGES: dict[str, TestExchangeOnlineSetup] = {
"hasQuoteVolume": False,
"timeframe": "30m",
"futures": True,
"futures_only": True,
"candle_count": 5000,
"orderbook_max_entries": 20,
"futures_pair": "BTC/USDC:USDC",
@@ -559,6 +560,19 @@ EXCHANGES: dict[str, TestExchangeOnlineSetup] = {
# TODO: re-enable hyperliquid websocket tests
"skip_ws_tests": True,
},
"krakenfutures": {
"pair": "BTC/USD:USD",
"stake_currency": "USD",
"hasQuoteVolume": False,
"timeframe": "1h",
"futures": True,
"futures_only": True,
"candle_count": 2000,
"futures_pair": "BTC/USD:USD",
"hasQuoteVolumeFutures": False,
"leverage_tiers_public": False,
"leverage_in_spot_market": False,
},
}
EXCHANGES_FUTURES = [exch for exch, params in EXCHANGES.items() if params.get("futures")]
@@ -591,11 +605,15 @@ def set_test_proxy(config: Config, use_proxy: bool) -> Config:
return config
def get_exchange(exchange_name, exchange_conf):
def get_exchange(exchange_name, exchange_conf, class_mocker=None):
exchange_params = EXCHANGES[exchange_name]
if exchange_params.get("futures_only"):
pytest.skip(f"Exchange {exchange_name} is futures-only, skipping spot tests.")
exchange_conf = set_test_proxy(exchange_conf, exchange_params.get("use_ci_proxy", False))
exchange_conf["exchange"]["name"] = exchange_name
exchange_conf["stake_currency"] = exchange_params["stake_currency"]
if class_mocker:
class_mocker.patch(f"{EXMS}.ft_additional_exchange_init")
exchange = ExchangeResolver.load_exchange(
exchange_conf, validate=True, load_leverage_tiers=True
)
@@ -608,25 +626,30 @@ def get_futures_exchange(exchange_name, exchange_conf, class_mocker):
if exchange_params.get("futures") is not True:
pytest.skip(f"Exchange {exchange_name} does not support futures.")
else:
exchange_conf = deepcopy(exchange_conf)
exchange_conf = set_test_proxy(exchange_conf, exchange_params.get("use_ci_proxy", False))
exchange_conf["trading_mode"] = "futures"
exchange_conf["margin_mode"] = "isolated"
exchange_conf = deepcopy(exchange_conf)
exchange_conf = set_test_proxy(exchange_conf, exchange_params.get("use_ci_proxy", False))
exchange_conf["exchange"]["name"] = exchange_name
exchange_conf["stake_currency"] = exchange_params["stake_currency"]
exchange_conf["trading_mode"] = "futures"
exchange_conf["margin_mode"] = "isolated"
class_mocker.patch("freqtrade.exchange.binance.Binance.fill_leverage_tiers")
class_mocker.patch(f"{EXMS}.fetch_trading_fees")
class_mocker.patch(f"{EXMS}.ft_additional_exchange_init")
class_mocker.patch(f"{EXMS}.load_cached_leverage_tiers", return_value=None)
class_mocker.patch(f"{EXMS}.cache_leverage_tiers")
class_mocker.patch("freqtrade.exchange.binance.Binance.fill_leverage_tiers")
class_mocker.patch(f"{EXMS}.fetch_trading_fees")
class_mocker.patch(f"{EXMS}.ft_additional_exchange_init")
class_mocker.patch(f"{EXMS}.load_cached_leverage_tiers", return_value=None)
class_mocker.patch(f"{EXMS}.cache_leverage_tiers")
return get_exchange(exchange_name, exchange_conf)
exchange = ExchangeResolver.load_exchange(
exchange_conf, validate=True, load_leverage_tiers=True
)
return exchange, exchange_name
@pytest.fixture(params=EXCHANGES, scope="class")
def exchange(request, exchange_conf, class_mocker):
class_mocker.patch(f"{EXMS}.ft_additional_exchange_init")
exchange, name, exchange_params = get_exchange(request.param, exchange_conf)
exchange, name, exchange_params = get_exchange(
request.param, exchange_conf, class_mocker
)
yield exchange, name, exchange_params
exchange.close()
@@ -653,7 +676,7 @@ def exchange_ws(request, exchange_conf, exchange_mode, class_mocker):
if exchange_param.get("skip_ws_tests"):
pytest.skip(f"{request.param} does not support websocket tests.")
if exchange_mode == "spot":
exchange, name, _ = get_exchange(request.param, exchange_conf)
exchange, name, _ = get_exchange(request.param, exchange_conf, class_mocker)
pair = exchange_param["pair"]
elif exchange_param.get("futures"):
exchange, name, _ = get_futures_exchange(
+6 -1
View File
@@ -64,7 +64,12 @@ class TestCCXTExchange:
if not expected_count:
pytest.skip("No expected candle count for exchange")
assert exch.ohlcv_candle_limit("1m", CandleType.FUTURES) == expected_count
candle_type = (
CandleType.FUTURES
if exchange_params.get("futures_only")
else CandleType.SPOT
)
assert exch.ohlcv_candle_limit("1m", candle_type) == expected_count
def test_load_markets_futures(self, exchange_futures: EXCHANGE_FIXTURE_TYPE):
exchange, _, exchange_params = exchange_futures