CryptoRobotFr / Live-Tools-V2

GNU General Public License v3.0
24 stars 12 forks source link

Erreur 45117 de Bitget : Currently holding positions or orders, the margin mode cannot be adjusted #2

Closed wikitab closed 5 months ago

wikitab commented 5 months ago

Hello,

J'ai une erreur lors de l'exécution :

Il y a eu une position prise sur MAGICUSDT mais sans stoploss.

--- Execution started at 2024-01-27 20:08:39 --- Pair REN/USDT not found, removing from params... Setting isolated x3 on 21 pairs... Getting data and indicators on 21 pairs... Balance: XXXXXXX USDT Getting open trigger orders... Canceling trigger orders... Getting open orders... Canceling limit orders... Getting live positions... Current position on MAGIC/USDT short - 162.8 ~ 184.71 $ Placing 2 close SL / limit order... Traceback (most recent call last): File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 443, in asyncio.run(main()) File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result() File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 439, in main raise e File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 381, in main await asyncio.gather(*tasks_close) # Limit orders when in positions File "/home/ubuntu/./Live-Tools-V2/utilities/bitget_perp.py", line 283, in place_order raise e File "/home/ubuntu/./Live-Tools-V2/utilities/bitget_perp.py", line 265, in place_order resp = await self._session.create_order( File "/home/ubuntu/.local/lib/python3.10/site-packages/ccxt/async_support/bitget.py", line 3918, in create_order response = await self.privateMixPostV2MixOrderPlaceOrder(request) File "/home/ubuntu/.local/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 759, in request return await self.fetch2(path, api, method, params, headers, body, config) File "/home/ubuntu/.local/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 756, in fetch2 return await self.fetch(request['url'], request['method'], request['headers'], request['body']) File "/home/ubuntu/.local/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 243, in fetch self.handle_errors(http_status_code, http_status_text, url, method, headers, http_response, json_response, request_headers, request_body) File "/home/ubuntu/.local/lib/python3.10/site-packages/ccxt/async_support/bitget.py", line 7694, in handle_errors raise ExchangeError(feedback) # unknown message ccxt.base.errors.ExchangeError: bitget {"code":"45117","msg":"Currently holding positions or orders, the margin mode cannot be adjusted","requestTime":1706386168418,"data":null}

Auriez-vous une idée ?? Merci les gars ;-)

michelflight commented 5 months ago

idem chez moi

michelflight commented 5 months ago

en fait comme très souvent, les libs c'est bullshit, ici ccxt, c'est un vrai merdier, pourquoi s'en servir alors qu'on peut tout simplement utiliser directement les endpoints de bitget. Je vais tout recoder moi même.

CryptoRobotFr commented 5 months ago

Hello je n'ai pas de problème de mon côté donc je pense que c'est un soucis de version de ccxt. J'ai ajusté un peu le répertoire pour utiliser un environnement virtuel et éviter les soucis de ce type. Pour ce faire ce que je vous conseille c'est reprendre de zéro. Pour ça supprimer le dossier :

sudo rm -r Live-Tools-V2/

Puis retélécharger :

git clone https://github.com/CryptoRobotFr/Live-Tools-V2.git
bash Live-Tools-V2/install.sh

Pensez à bien remettre votre clé api et normalement cela devrait être bon. Pour tester :

bash Live-Tools-V2/1hcron.sh

wikitab commented 5 months ago

Hello,

Merci pour ta réponse.

Je suis reparti de zéro avec les fichiers modifiés sur GIT (avec les packages avec les bonnes version), mais j'ai encore la même erreur après avoir fait un short manuel de 0.01 ETH.

Je ne sais pas si ça a un impact, mais lors de l'install, j'ai un message sur la console SSH : voir la capture d'écran 2024-01-29_20-19-49

--- Execution started at 2024-01-29 19:32:54 --- Pair REN/USDT not found, removing from params... Setting isolated x3 on 21 pairs... Getting data and indicators on 21 pairs... Balance: XXXXXXXXXX USDT Getting open trigger orders... Canceling trigger orders... Getting open orders... Canceling limit orders... Getting live positions... Current position on ETH/USDT short - 0.01 ~ 23.0 $ Placing 2 close SL / limit order... Traceback (most recent call last): File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 443, in asyncio.run(main()) File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result() File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 439, in main raise e File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 381, in main await asyncio.gather(*tasks_close) # Limit orders when in positions File "/home/ubuntu/./Live-Tools-V2/utilities/bitget_perp.py", line 283, in place_order raise e File "/home/ubuntu/./Live-Tools-V2/utilities/bitget_perp.py", line 265, in place_order resp = await self._session.create_order( File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/bitget.py", line 3908, in create_order response = await self.privateMixPostV2MixOrderPlaceOrder(request) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 753, in request return await self.fetch2(path, api, method, params, headers, body, config) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 750, in fetch2 return await self.fetch(request['url'], request['method'], request['headers'], request['body']) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 243, in fetch self.handle_errors(http_status_code, http_status_text, url, method, headers, http_response, json_response, request_headers, request_body) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/bitget.py", line 7684, in handle_errors raise ExchangeError(feedback) # unknown message ccxt.base.errors.ExchangeError: bitget {"code":"45117","msg":"Currently holding positions or orders, the margin mode cannot be adjusted","requestTime":1706556823067,"data":null} sys:1: RuntimeWarning: coroutine 'PerpBitget.place_trigger_order' was never awaited

A+ ;-)

alexthenx commented 5 months ago

Hello,

Exactement le même pb pour moi, j'ai tout essayé ccxt .20, .21, .22 et .23 et je viens une nouvelle fois de réinstaller le projet.

Les ordres ne se mettents plus dès que l'on a des positions ouvertes.

Voici la trace :

--- Execution started at 2024-01-31 13:45:48 --- Setting crossed x4 on 22 pairs... Getting data and indicators on 22 pairs... Balance: 406.32 USDT Getting open trigger orders... Canceling trigger orders... Getting open orders... Canceling limit orders... Getting live positions... Current position on ROSE/USDT long - 207.0 ~ 21.03 $ Placing 2 close SL / limit order... Traceback (most recent call last): File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 443, in asyncio.run(main()) File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result() File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 439, in main raise e File "/home/ubuntu/Live-Tools-V2/strategies/envelopes/multi_bitget.py", line 381, in main await asyncio.gather(*tasks_close) # Limit orders when in positions File "/home/ubuntu/./Live-Tools-V2/utilities/bitget_perp.py", line 283, in place_order raise e File "/home/ubuntu/./Live-Tools-V2/utilities/bitget_perp.py", line 265, in place_order resp = await self._session.create_order( File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/bitget.py", line 3908, in create_order response = await self.privateMixPostV2MixOrderPlaceOrder(request) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 753, in request return await self.fetch2(path, api, method, params, headers, body, config) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 750, in fetch2 return await self.fetch(request['url'], request['method'], request['headers'], request['body']) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/base/exchange.py", line 243, in fetch self.handle_errors(http_status_code, http_status_text, url, method, headers, http_response, json_response, request_headers, request_body) File "/home/ubuntu/Live-Tools-V2/.venv/lib/python3.10/site-packages/ccxt/async_support/bitget.py", line 7684, in handle_errors raise ExchangeError(feedback) # unknown message ccxt.base.errors.ExchangeError: bitget {"code":"45117","msg":"Currently holding positions or orders, the margin mode cannot be adjusted","requestTime":1706705190338,"data":null}

Merci,

alexthenx commented 5 months ago

Re,

J'ai décommenté les lignes margin_mode dans les fonctions place_order et place_trigger_order et tout fonctionne maintenant :

async def place_order(
    self,
    pair,
    side,
    price,
    size,
    type="limit",
    reduce=False,
    margin_mode="crossed",
    error=True,
) -> Order:
    try:
        pair = self.ext_pair_to_pair(pair)
        trade_side = "Open" if reduce is False else "Close"
        resp = await self._session.create_order(
            symbol=pair,
            type=type,
            side=side,
            amount=size,
            price=price,
            params={
                "reduceOnly": reduce,
                "tradeSide": trade_side,
                # "marginMode": margin_mode,
            },
        )
        order_id = resp["id"]
        pair = self.pair_to_ext_pair(resp["symbol"])
        order = await self.get_order_by_id(order_id, pair)
        return order
    except Exception as e:
        if error:
            raise e
        else:
            print(e)
            return None

async def place_trigger_order(
    self,
    pair,
    side,
    price,
    trigger_price,
    size,
    type="limit",
    reduce=False,
    margin_mode="crossed",
    error=True,
) -> Info:
    try:
        pair = self.ext_pair_to_pair(pair)
        trade_side = "Open" if reduce is False else "Close"
        trigger_order = await self._session.create_trigger_order(
            symbol=pair,
            type=type,
            side=side,
            amount=size,
            price=price,
            triggerPrice=trigger_price,
            params={
                "reduceOnly": reduce,
                "tradeSide": trade_side,
                # "marginMode": margin_mode,
            },
        )
        resp = Info(success=True, message="Trigger Order set up")
        return resp
    except Exception as e:
        if error:
            raise e
        else:
            print(e)
            return None

Voici la dernière trace :

--- Execution started at 2024-01-31 13:56:36 --- Setting crossed x4 on 22 pairs... Getting data and indicators on 22 pairs... Balance: 406.25 USDT Getting open trigger orders... Canceling trigger orders... Getting open orders... Canceling limit orders... Getting live positions... Current position on ROSE/USDT long - 207.0 ~ 20.99 $ Placing 2 close SL / limit order... Placing 202 open limit order... --- Execution finished at 2024-01-31 13:58:02 ---

@CryptoRobotFr peux-tu nous confirmer si c'était bien ça le pb ?

Merci beaucoup,

Alexandre.

alexthenx commented 5 months ago

Hello,

Pour info j'ai les deux scripts sur deux comptes (un en crossed et l'autre en isolated) --> l'erreur margin mode lorsqu'une position est ouverte ne se produit que sur les positions crossed. Il n'y a aucune erreur avec mon autre script qui est sur des positions isolated.

baribalfb commented 5 months ago

Re,

J'ai décommenté les lignes margin_mode dans les fonctions place_order et place_trigger_order et tout fonctionne maintenant :

async def place_order(
    self,
    pair,
    side,
    price,
    size,
    type="limit",
    reduce=False,
    margin_mode="crossed",
    error=True,
) -> Order:
    try:
        pair = self.ext_pair_to_pair(pair)
        trade_side = "Open" if reduce is False else "Close"
        resp = await self._session.create_order(
            symbol=pair,
            type=type,
            side=side,
            amount=size,
            price=price,
            params={
                "reduceOnly": reduce,
                "tradeSide": trade_side,
                # "marginMode": margin_mode,
            },
        )
        order_id = resp["id"]
        pair = self.pair_to_ext_pair(resp["symbol"])
        order = await self.get_order_by_id(order_id, pair)
        return order
    except Exception as e:
        if error:
            raise e
        else:
            print(e)
            return None

async def place_trigger_order(
    self,
    pair,
    side,
    price,
    trigger_price,
    size,
    type="limit",
    reduce=False,
    margin_mode="crossed",
    error=True,
) -> Info:
    try:
        pair = self.ext_pair_to_pair(pair)
        trade_side = "Open" if reduce is False else "Close"
        trigger_order = await self._session.create_trigger_order(
            symbol=pair,
            type=type,
            side=side,
            amount=size,
            price=price,
            triggerPrice=trigger_price,
            params={
                "reduceOnly": reduce,
                "tradeSide": trade_side,
                # "marginMode": margin_mode,
            },
        )
        resp = Info(success=True, message="Trigger Order set up")
        return resp
    except Exception as e:
        if error:
            raise e
        else:
            print(e)
            return None

Voici la dernière trace :

--- Execution started at 2024-01-31 13:56:36 --- Setting crossed x4 on 22 pairs... Getting data and indicators on 22 pairs... Balance: 406.25 USDT Getting open trigger orders... Canceling trigger orders... Getting open orders... Canceling limit orders... Getting live positions... Current position on ROSE/USDT long - 207.0 ~ 20.99 $ Placing 2 close SL / limit order... Placing 202 open limit order... --- Execution finished at 2024-01-31 13:58:02 ---

@CryptoRobotFr peux-tu nous confirmer si c'était bien ça le pb ?

Merci beaucoup,

Alexandre.

Je confirme. C'est dans le fichier "Live-Tools-V2/utilities/bitget_perp.py" qu'il faut apporter la modification.

zac667 commented 5 months ago

hello, moi j'ai toujours l'erreur, alors que je suis bien en isolated et j'ai également modifié le script vitget_perp.py Je met mon script en dessous.

Merci les gars :) :

`from typing import List import ccxt.async_support as ccxt import asyncio import pandas as pd import time import itertools from pydantic import BaseModel

class UsdtBalance(BaseModel): total: float free: float used: float

class Info(BaseModel): success: bool message: str

class Order(BaseModel): id: str pair: str type: str side: str price: float size: float reduce: bool filled: float remaining: float timestamp: int

class TriggerOrder(BaseModel): id: str pair: str type: str side: str price: float trigger_price: float size: float reduce: bool timestamp: int

class Position(BaseModel): pair: str side: str size: float usd_size: float entry_price: float current_price: float unrealizedPnl: float liquidation_price: float margin_mode: str leverage: float hedge_mode: bool open_timestamp: int take_profit_price: float stop_loss_price: float

class PerpBitget: def init(self, public_api=None, secret_api=None, password=None): bitget_auth_object = { "apiKey": public_api, "secret": secret_api, "password": password, "enableRateLimit": True, "rateLimit": 100, "options": { "defaultType": "future", }, } if bitget_auth_object["secret"] == None: self._auth = False self._session = ccxt.bitget() else: self._auth = True self._session = ccxt.bitget(bitget_auth_object)

async def load_markets(self):
    self.market = await self._session.load_markets()

async def close(self):
    await self._session.close()

def ext_pair_to_pair(self, ext_pair) -> str:
    return f"{ext_pair}:USDT"

def pair_to_ext_pair(self, pair) -> str:
    return pair.replace(":USDT", "")

def get_pair_info(self, ext_pair) -> str:
    pair = self.ext_pair_to_pair(ext_pair)
    if pair in self.market:
        return self.market[pair]
    else:
        return None

def amount_to_precision(self, pair: str, amount: float) -> float:
    pair = self.ext_pair_to_pair(pair)
    return self._session.amount_to_precision(pair, amount)

def price_to_precision(self, pair: str, price: float) -> float:
    pair = self.ext_pair_to_pair(pair)
    return self._session.price_to_precision(pair, price)

async def get_last_ohlcv(self, pair, timeframe, limit=1000) -> pd.DataFrame:
    pair = self.ext_pair_to_pair(pair)
    bitget_limit = 200
    ts_dict = {
        "1m": 1 * 60 * 1000,
        "5m": 5 * 60 * 1000,
        "15m": 15 * 60 * 1000,
        "1h": 60 * 60 * 1000,
        "2h": 2 * 60 * 60 * 1000,
        "4h": 4 * 60 * 60 * 1000,
        "1d": 24 * 60 * 60 * 1000,
    }
    end_ts = int(time.time() * 1000)
    start_ts = end_ts - ((limit) * ts_dict[timeframe])
    current_ts = start_ts
    tasks = []
    while current_ts < end_ts:
        req_end_ts = min(current_ts + (bitget_limit * ts_dict[timeframe]), end_ts)
        tasks.append(
            self._session.fetch_ohlcv(
                pair,
                timeframe,
                params={
                    "limit": bitget_limit,
                    "startTime": str(current_ts),
                    "endTime": str(req_end_ts),
                },
            )
        )
        current_ts += (bitget_limit * ts_dict[timeframe]) + 1
    ohlcv_unpack = await asyncio.gather(*tasks)
    ohlcv_list = list(itertools.chain.from_iterable(ohlcv_unpack))
    df = pd.DataFrame(
        ohlcv_list, columns=["date", "open", "high", "low", "close", "volume"]
    )
    df = df.set_index(df["date"])
    df.index = pd.to_datetime(df.index, unit="ms")
    df = df.sort_index()
    del df["date"]
    return df

async def get_balance(self) -> UsdtBalance:
    resp = await self._session.fetch_balance()
    return UsdtBalance(
        total=resp["USDT"]["total"],
        free=resp["USDT"]["free"],
        used=resp["USDT"]["used"],
    )

async def set_margin_mode_and_leverage(self, pair, margin_mode, leverage):
    if margin_mode not in ["crossed", "isolated"]:
        raise Exception("Margin mode must be either 'crossed' or 'isolated'")
    pair = self.ext_pair_to_pair(pair)
    try:
        await self._session.set_margin_mode(
            margin_mode,
            pair,
            params={"productType": "USDT-FUTURES", "marginCoin": "USDT"},
        )
    except Exception as e:
        pass
    try:
        if margin_mode == "isolated":
            tasks = []
            tasks.append(
                self._session.set_leverage(
                    leverage,
                    pair,
                    params={
                        "productType": "USDT-FUTURES",
                        "marginCoin": "USDT",
                        "holdSide": "long",
                    },
                )
            )
            tasks.append(
                self._session.set_leverage(
                    leverage,
                    pair,
                    params={
                        "productType": "USDT-FUTURES",
                        "marginCoin": "USDT",
                        "holdSide": "short",
                    },
                )
            )
            await asyncio.gather(*tasks)
        else:
            await self._session.set_leverage(
                leverage,
                pair,
                params={"productType": "USDT-FUTURES", "marginCoin": "USDT"},
            )
    except Exception as e:
        pass

    return Info(
        success=True,
        message=f"Margin mode and leverage set to {margin_mode} and {leverage}x",
    )

async def get_open_positions(self, pairs) -> List[Position]:
    pairs = [self.ext_pair_to_pair(pair) for pair in pairs]
    resp = await self._session.fetch_positions(
        symbols=pairs, params={"productType": "USDT-FUTURES", "marginCoin": "USDT"}
    )
    return_positions = []
    for position in resp:
        liquidation_price = 0
        take_profit_price = 0
        stop_loss_price = 0
        if position["liquidationPrice"]:
            liquidation_price = position["liquidationPrice"]
        if position["takeProfitPrice"]:
            take_profit_price = position["takeProfitPrice"]
        if position["stopLossPrice"]:
            stop_loss_price = position["stopLossPrice"]

        return_positions.append(
            Position(
                pair=self.pair_to_ext_pair(position["symbol"]),
                side=position["side"],
                size=position["contracts"] * position["contractSize"],
                usd_size=round(
                    (position["contracts"] * position["contractSize"])
                    * position["markPrice"],
                    2,
                ),
                entry_price=position["entryPrice"],
                current_price=position["markPrice"],
                unrealizedPnl=position["unrealizedPnl"],
                liquidation_price=liquidation_price,
                leverage=position["leverage"],
                margin_mode=position["marginMode"],
                hedge_mode=position["hedged"],
                open_timestamp=position["timestamp"],
                take_profit_price=take_profit_price,
                stop_loss_price=stop_loss_price,
            )
        )
    return return_positions

async def place_order(
    self,
    pair,
    side,
    price,
    size,
    type="limit",
    reduce=False,
    margin_mode="crossed",
    error=True,
) -> Order:
    try:
        pair = self.ext_pair_to_pair(pair)
        trade_side = "Open" if reduce is False else "Close"
        resp = await self._session.create_order(
            symbol=pair,
            type=type,
            side=side,
            amount=size,
            price=price,
            params={
                "reduceOnly": reduce,
                "tradeSide": trade_side,
                # "marginMode": margin_mode,
            },
        )
        order_id = resp["id"]
        pair = self.pair_to_ext_pair(resp["symbol"])
        order = await self.get_order_by_id(order_id, pair)
        return order
    except Exception as e:
        if error:
            raise e
        else:
            print(e)
            return None

async def place_trigger_order(
    self,
    pair,
    side,
    price,
    trigger_price,
    size,
    type="limit",
    reduce=False,
    margin_mode="crossed",
    error=True,
) -> Info:
    try:
        pair = self.ext_pair_to_pair(pair)
        trade_side = "Open" if reduce is False else "Close"
        trigger_order = await self._session.create_trigger_order(
            symbol=pair,
            type=type,
            side=side,
            amount=size,
            price=price,
            triggerPrice=trigger_price,
            params={
                "reduceOnly": reduce,
                "tradeSide": trade_side,
                # "marginMode": margin_mode,
            },
        )
        resp = Info(success=True, message="Trigger Order set up")
        return resp
    except Exception as e:
        if error:
            raise e
        else:
            print(e)
            return None

async def get_open_orders(self, pair) -> List[Order]:
    pair = self.ext_pair_to_pair(pair)
    resp = await self._session.fetch_open_orders(pair)
    return_orders = []
    for order in resp:
        return_orders.append(
            Order(
                id=order["id"],
                pair=self.pair_to_ext_pair(order["symbol"]),
                type=order["type"],
                side=order["side"],
                price=order["price"],
                size=order["amount"],
                reduce=order["reduceOnly"],
                filled=order["filled"],
                remaining=order["remaining"],
                timestamp=order["timestamp"],
            )
        )
    return return_orders

async def get_open_trigger_orders(self, pair) -> List[TriggerOrder]:
    pair = self.ext_pair_to_pair(pair)
    resp = await self._session.fetch_open_orders(pair, params={"stop": True})
    # print(resp)
    return_orders = []
    for order in resp:
        reduce = True if order["info"]["tradeSide"] == "close" else False
        price = order["price"] if order["price"] else 0.0
        return_orders.append(
            TriggerOrder(
                id=order["id"],
                pair=self.pair_to_ext_pair(order["symbol"]),
                type=order["type"],
                side=order["side"],
                price=price,
                trigger_price=order["triggerPrice"],
                size=order["amount"],
                reduce=reduce,
                timestamp=order["timestamp"],
            )
        )
    return return_orders

async def get_order_by_id(self, order_id, pair) -> Order:
    pair = self.ext_pair_to_pair(pair)
    resp = await self._session.fetch_order(order_id, pair)
    return Order(
        id=resp["id"],
        pair=self.pair_to_ext_pair(resp["symbol"]),
        type=resp["type"],
        side=resp["side"],
        price=resp["price"],
        size=resp["amount"],
        reduce=resp["reduceOnly"],
        filled=resp["filled"],
        remaining=resp["remaining"],
        timestamp=resp["timestamp"],
    )

async def cancel_orders(self, pair, ids=[]):
    try:
        pair = self.ext_pair_to_pair(pair)
        resp = await self._session.cancel_orders(
            ids=ids,
            symbol=pair,
        )
        return Info(success=True, message=f"{len(resp)} Orders cancelled")
    except Exception as e:
        return Info(success=False, message="Error or no orders to cancel")

async def cancel_trigger_orders(self, pair, ids=[]):
    try:
        pair = self.ext_pair_to_pair(pair)
        resp = await self._session.cancel_orders(
            ids=ids, symbol=pair, params={"stop": True}
        )
        return Info(success=True, message=f"{len(resp)} Trigger Orders cancelled")
    except Exception as e:
        return Info(success=False, message="Error or no orders to cancel")`