Merge pull request #13066 from ABSllk/fix-bitget-stoploss

Add pos_loss for Bitget futures stoploss cancellation
This commit is contained in:
Matthias
2026-04-20 20:55:31 +02:00
committed by GitHub
2 changed files with 50 additions and 1 deletions
+14
View File
@@ -7,6 +7,7 @@ from freqtrade.constants import BuySell
from freqtrade.enums import OPTIMIZE_MODES, CandleType, MarginMode, PriceType, TradingMode from freqtrade.enums import OPTIMIZE_MODES, CandleType, MarginMode, PriceType, TradingMode
from freqtrade.exceptions import ( from freqtrade.exceptions import (
DDosProtection, DDosProtection,
InvalidOrderException,
OperationalException, OperationalException,
RetryableOrderError, RetryableOrderError,
TemporaryError, TemporaryError,
@@ -142,6 +143,19 @@ class Bitget(Exchange):
return self._fetch_stop_order_fallback(order_id, pair) return self._fetch_stop_order_fallback(order_id, pair)
def cancel_stoploss_order(self, order_id: str, pair: str, params: dict | None = None) -> dict:
cancel_params = params.copy() if params else {}
cancel_params["stop"] = True
if self.trading_mode != TradingMode.FUTURES:
return self.cancel_order(order_id, pair, cancel_params)
try:
return self.cancel_order(order_id, pair, {**cancel_params, "planType": "pos_loss"})
except (InvalidOrderException, IndexError):
# Keep compatibility with stoploss orders created by older versions.
return self.cancel_order(order_id, pair, cancel_params)
@retrier @retrier
def additional_exchange_init(self) -> None: def additional_exchange_init(self) -> None:
""" """
+36 -1
View File
@@ -5,7 +5,7 @@ from unittest.mock import MagicMock, PropertyMock
import pytest import pytest
from freqtrade.enums import CandleType, MarginMode, RunMode, TradingMode from freqtrade.enums import CandleType, MarginMode, RunMode, TradingMode
from freqtrade.exceptions import OperationalException, RetryableOrderError from freqtrade.exceptions import InvalidOrderException, OperationalException, RetryableOrderError
from freqtrade.exchange.common import API_RETRY_COUNT from freqtrade.exchange.common import API_RETRY_COUNT
from freqtrade.util import dt_now, dt_ts, dt_utc from freqtrade.util import dt_now, dt_ts, dt_utc
from tests.conftest import EXMS, get_patched_exchange from tests.conftest import EXMS, get_patched_exchange
@@ -77,6 +77,41 @@ def test_fetch_stoploss_order_bitget_exceptions(default_conf_usdt, mocker):
) )
@pytest.mark.usefixtures("init_persistence")
def test_cancel_stoploss_order_bitget(default_conf_usdt, mocker):
default_conf_usdt["dry_run"] = False
api_mock = MagicMock()
exchange = get_patched_exchange(mocker, default_conf_usdt, api_mock, exchange="bitget")
# Spot scenario
exchange.cancel_order = MagicMock(return_value={"id": "1234"})
assert exchange.cancel_stoploss_order("1234", "ETH/USDT", {}) == {"id": "1234"}
assert exchange.cancel_order.call_count == 1
exchange.cancel_order.assert_called_once_with("1234", "ETH/USDT", {"stop": True})
# Futures scenario
default_conf_usdt["trading_mode"] = TradingMode.FUTURES
default_conf_usdt["margin_mode"] = MarginMode.ISOLATED
exchange = get_patched_exchange(mocker, default_conf_usdt, api_mock, exchange="bitget")
exchange.cancel_order = MagicMock(return_value={"id": "1234"})
assert exchange.cancel_stoploss_order("1234", "ETH/USDT:USDT", {}) == {"id": "1234"}
assert exchange.cancel_order.call_count == 1
exchange.cancel_order.assert_called_once_with(
"1234", "ETH/USDT:USDT", {"stop": True, "planType": "pos_loss"}
)
exchange.cancel_order = MagicMock(
side_effect=[InvalidOrderException("API error"), {"id": "1234"}]
)
assert exchange.cancel_stoploss_order("1234", "ETH/USDT:USDT", {}) == {"id": "1234"}
assert exchange.cancel_order.call_count == 2
exchange.cancel_order.assert_any_call(
"1234", "ETH/USDT:USDT", {"stop": True, "planType": "pos_loss"}
)
exchange.cancel_order.assert_any_call("1234", "ETH/USDT:USDT", {"stop": True})
def test_bitget_ohlcv_candle_limit(mocker, default_conf_usdt): def test_bitget_ohlcv_candle_limit(mocker, default_conf_usdt):
# This test is also a live test - so we're sure our limits are correct. # This test is also a live test - so we're sure our limits are correct.
api_mock = MagicMock() api_mock = MagicMock()