exchange: fallback to canceled orders for krakenfutures fetch_order; add tests
This commit is contained in:
@@ -6,7 +6,7 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from freqtrade.enums import MarginMode, PriceType, TradingMode
|
||||
from freqtrade.exceptions import ExchangeError, RetryableOrderError
|
||||
from freqtrade.exceptions import ExchangeError, RetryableOrderError, TemporaryError
|
||||
from freqtrade.exchange.exchange import Exchange
|
||||
from freqtrade.exchange.exchange_types import FtHas
|
||||
|
||||
@@ -169,19 +169,33 @@ class Krakenfutures(Exchange):
|
||||
"""
|
||||
Kraken Futures fetchOrder is backed by /orders/status which only returns
|
||||
open orders or orders closed within the last 5 seconds.
|
||||
Fall back to fetchClosedOrders for older orders.
|
||||
Fall back to closed/canceled order endpoints for older orders.
|
||||
"""
|
||||
params = params or {}
|
||||
try:
|
||||
return super().fetch_order(order_id, pair, params=params)
|
||||
except RetryableOrderError as err:
|
||||
if not self.exchange_has("fetchClosedOrders"):
|
||||
raise
|
||||
except (RetryableOrderError, TemporaryError) as err:
|
||||
order = self._fetch_order_from_closed_or_canceled(order_id, pair, params)
|
||||
if order is not None:
|
||||
return order
|
||||
raise err
|
||||
|
||||
def _fetch_order_from_closed_or_canceled(
|
||||
self, order_id: str, pair: str, params: dict[str, Any]
|
||||
) -> dict[str, Any] | None:
|
||||
if self.exchange_has("fetchClosedOrders"):
|
||||
orders = self._api.fetch_closed_orders(pair, params=params)
|
||||
for order in orders or []:
|
||||
if str(order.get("id")) == str(order_id):
|
||||
return self._order_contracts_to_amount(order)
|
||||
raise err
|
||||
|
||||
if self.exchange_has("fetchCanceledOrders"):
|
||||
orders = self._api.fetch_canceled_orders(pair, params=params)
|
||||
for order in orders or []:
|
||||
if str(order.get("id")) == str(order_id):
|
||||
return self._order_contracts_to_amount(order)
|
||||
|
||||
return None
|
||||
|
||||
def get_funding_fees(self, pair: str, amount: float, is_short: bool, open_date) -> float:
|
||||
"""CCXT currently does not support Kraken Futures fetchFundingHistory."""
|
||||
|
||||
@@ -6,7 +6,7 @@ from copy import deepcopy
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from freqtrade.enums import CandleType, MarginMode, TradingMode
|
||||
from freqtrade.exceptions import RetryableOrderError
|
||||
from freqtrade.exceptions import RetryableOrderError, TemporaryError
|
||||
from freqtrade.exchange.exchange import Exchange
|
||||
from freqtrade.exchange.krakenfutures import Krakenfutures
|
||||
from tests.conftest import EXMS, get_patched_exchange
|
||||
@@ -35,10 +35,12 @@ def test_krakenfutures_fetch_order_falls_back_to_closed_orders(mocker, default_c
|
||||
"""Fallback to fetch_closed_orders when fetch_order can't find the order."""
|
||||
ex = get_patched_exchange(mocker, default_conf, exchange="krakenfutures")
|
||||
|
||||
mocker.patch.object(Exchange, "fetch_order", side_effect=RetryableOrderError("not found"))
|
||||
mocker.patch.object(
|
||||
Exchange, "fetch_order", side_effect=RetryableOrderError("not found")
|
||||
ex,
|
||||
"exchange_has",
|
||||
side_effect=lambda endpoint: endpoint == "fetchClosedOrders",
|
||||
)
|
||||
mocker.patch.object(ex, "exchange_has", return_value=True)
|
||||
mocker.patch.object(
|
||||
ex._api,
|
||||
"fetch_closed_orders",
|
||||
@@ -50,6 +52,29 @@ def test_krakenfutures_fetch_order_falls_back_to_closed_orders(mocker, default_c
|
||||
assert res["id"] == "abc"
|
||||
|
||||
|
||||
def test_krakenfutures_fetch_order_falls_back_to_canceled_orders(mocker, default_conf):
|
||||
"""Fallback to fetch_canceled_orders when closed orders don't contain the order."""
|
||||
ex = get_patched_exchange(mocker, default_conf, exchange="krakenfutures")
|
||||
|
||||
mocker.patch.object(
|
||||
Exchange, "fetch_order", side_effect=TemporaryError("UUID string too large")
|
||||
)
|
||||
mocker.patch.object(
|
||||
ex,
|
||||
"exchange_has",
|
||||
side_effect=lambda endpoint: endpoint == "fetchCanceledOrders",
|
||||
)
|
||||
mocker.patch.object(
|
||||
ex._api,
|
||||
"fetch_canceled_orders",
|
||||
return_value=[{"id": "def", "symbol": "BTC/USD:USD", "status": "canceled"}],
|
||||
create=True,
|
||||
)
|
||||
|
||||
res = ex.fetch_order("def", "BTC/USD:USD")
|
||||
assert res["id"] == "def"
|
||||
|
||||
|
||||
def test_krakenfutures_create_stoploss_uses_trigger_price_type(mocker, default_conf):
|
||||
"""Test create_stoploss uses triggerPrice, triggerSignal, and reduceOnly."""
|
||||
api_mock = MagicMock()
|
||||
|
||||
Reference in New Issue
Block a user