feat(bitget): stoploss order fetching attempts

This commit is contained in:
Matthias
2025-08-01 20:19:43 +02:00
parent 96aa214fc5
commit 4177809f71

View File

@@ -1,9 +1,18 @@
import logging
from datetime import timedelta
import ccxt
from freqtrade.enums import CandleType
from freqtrade.exceptions import (
DDosProtection,
OperationalException,
RetryableOrderError,
TemporaryError,
)
from freqtrade.exchange import Exchange
from freqtrade.exchange.exchange_types import FtHas
from freqtrade.exchange.common import API_RETRY_COUNT, retrier
from freqtrade.exchange.exchange_types import CcxtOrder, FtHas
from freqtrade.util.datetime_helpers import dt_now, dt_ts
@@ -21,6 +30,10 @@ class Bitget(Exchange):
"""
_ft_has: FtHas = {
"stoploss_on_exchange": True,
"stop_price_param": "stopPrice",
"stop_price_prop": "stopPrice",
"stoploss_order_types": {"limit": "limit", "market": "market"},
"ohlcv_candle_limit": 200, # 200 for historical candles, 1000 for recent ones.
"order_time_in_force": ["GTC", "FOK", "IOC", "PO"],
}
@@ -50,3 +63,55 @@ class Bitget(Exchange):
return 1000
return super().ohlcv_candle_limit(timeframe, candle_type, since_ms)
def _convert_stop_order(self, pair: str, order_id: str, order: CcxtOrder) -> CcxtOrder:
if (
order.get("status", "open") == "closed"
and (real_order_id := order.get("info", {}).get("ordId")) is not None
):
# Once a order triggered, we fetch the regular followup order.
order_reg = self.fetch_order(real_order_id, pair)
self._log_exchange_response("fetch_stoploss_order1", order_reg)
order_reg["id_stop"] = order_reg["id"]
order_reg["id"] = order_id
order_reg["type"] = "stoploss"
order_reg["status_stop"] = "triggered"
return order_reg
order = self._order_contracts_to_amount(order)
order["type"] = "stoploss"
return order
def _fetch_stop_order_fallback(self, order_id: str, pair: str) -> CcxtOrder:
params2 = {
"stop": True,
}
for method in (
self._api.fetch_open_orders,
self._api.fetch_closed_orders,
):
try:
orders = method(pair, params=params2)
orders_f = [order for order in orders if order["id"] == order_id]
if orders_f:
order = orders_f[0]
return self._convert_stop_order(pair, order_id, order)
except (ccxt.OrderNotFound, ccxt.InvalidOrder):
pass
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.OperationFailed, ccxt.ExchangeError) as e:
raise TemporaryError(
f"Could not get order due to {e.__class__.__name__}. Message: {e}"
) from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
raise RetryableOrderError(f"StoplossOrder not found (pair: {pair} id: {order_id}).")
@retrier(retries=API_RETRY_COUNT)
def fetch_stoploss_order(
self, order_id: str, pair: str, params: dict | None = None
) -> CcxtOrder:
if self._config["dry_run"]:
return self.fetch_dry_run_order(order_id)
return self._fetch_stop_order_fallback(order_id, pair)