ccxt 4.3.8__py2.py3-none-any.whl → 4.3.10__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

@@ -171,6 +171,7 @@ class coinmetro(Exchange, ImplicitAPI):
171
171
  'private': {
172
172
  'get': {
173
173
  'users/balances': 1,
174
+ 'users/wallets': 1,
174
175
  'users/wallets/history/{since}': 1.67,
175
176
  'exchange/orders/status/{orderID}': 1,
176
177
  'exchange/orders/active': 1,
@@ -910,49 +911,48 @@ class coinmetro(Exchange, ImplicitAPI):
910
911
  async def fetch_balance(self, params={}) -> Balances:
911
912
  """
912
913
  query for balance and get the amount of funds available for trading or funds locked in orders
913
- :see: https://documenter.getpostman.com/view/3653795/SVfWN6KS#698ae067-43dd-4e19-a0ac-d9ba91381816
914
+ :see: https://documenter.getpostman.com/view/3653795/SVfWN6KS#741a1dcc-7307-40d0-acca-28d003d1506a
914
915
  :param dict [params]: extra parameters specific to the exchange API endpoint
915
916
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
916
917
  """
917
918
  await self.load_markets()
918
- response = await self.privateGetUsersBalances(params)
919
- return self.parse_balance(response)
919
+ response = await self.privateGetUsersWallets(params)
920
+ list = self.safe_list(response, 'list', [])
921
+ return self.parse_balance(list)
920
922
 
921
- def parse_balance(self, response) -> Balances:
923
+ def parse_balance(self, balances) -> Balances:
922
924
  #
923
- # {
924
- # "USDC": {
925
- # "USDC": 99,
926
- # "EUR": 91.16,
927
- # "BTC": 0.002334
928
- # },
929
- # "XCM": {
930
- # "XCM": 0,
931
- # "EUR": 0,
932
- # "BTC": 0
933
- # },
934
- # "TOTAL": {
935
- # "EUR": 91.16,
936
- # "BTC": 0.002334
925
+ # [
926
+ # {
927
+ # "xcmLocks": [],
928
+ # "xcmLockAmounts": [],
929
+ # "refList": [],
930
+ # "balanceHistory": [],
931
+ # "_id": "5fecd3c998e75c2e4d63f7c3",
932
+ # "currency": "BTC",
933
+ # "label": "BTC",
934
+ # "userId": "5fecd3c97fbfed1521db23bd",
935
+ # "__v": 0,
936
+ # "balance": 0.5,
937
+ # "createdAt": "2020-12-30T19:23:53.646Z",
938
+ # "disabled": False,
939
+ # "updatedAt": "2020-12-30T19:23:53.653Z",
940
+ # "reserved": 0,
941
+ # "id": "5fecd3c998e75c2e4d63f7c3"
937
942
  # },
938
- # "REF": {
939
- # "XCM": 0,
940
- # "EUR": 0,
941
- # "BTC": 0
942
- # }
943
- # }
943
+ # ...
944
+ # ]
944
945
  #
945
946
  result = {
946
- 'info': response,
947
+ 'info': balances,
947
948
  }
948
- balances = self.omit(response, ['TOTAL', 'REF'])
949
- currencyIds = list(balances.keys())
950
- for i in range(0, len(currencyIds)):
951
- currencyId = currencyIds[i]
949
+ for i in range(0, len(balances)):
950
+ balanceEntry = self.safe_dict(balances, i, {})
951
+ currencyId = self.safe_string(balanceEntry, 'currency')
952
952
  code = self.safe_currency_code(currencyId)
953
953
  account = self.account()
954
- currency = self.safe_value(balances, currencyId, {})
955
- account['total'] = self.safe_string(currency, currencyId)
954
+ account['total'] = self.safe_string(balanceEntry, 'balance')
955
+ account['used'] = self.safe_string(balanceEntry, 'reserved')
956
956
  result[code] = account
957
957
  return self.safe_balance(result)
958
958
 
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.kucoin import kucoin
7
7
  from ccxt.abstract.kucoinfutures import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
8
+ from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
9
9
  from typing import List
10
10
  from ccxt.base.errors import AuthenticationError
11
11
  from ccxt.base.errors import PermissionDenied
@@ -94,13 +94,14 @@ class kucoinfutures(kucoin, ImplicitAPI):
94
94
  'fetchPositionHistory': False,
95
95
  'fetchPositionMode': False,
96
96
  'fetchPositions': True,
97
- 'fetchPositionsHistory': False,
97
+ 'fetchPositionsHistory': True,
98
98
  'fetchPremiumIndexOHLCV': False,
99
99
  'fetchStatus': True,
100
100
  'fetchTicker': True,
101
101
  'fetchTickers': True,
102
102
  'fetchTime': True,
103
103
  'fetchTrades': True,
104
+ 'fetchTradingFee': True,
104
105
  'fetchTransactionFee': False,
105
106
  'fetchWithdrawals': True,
106
107
  'setLeverage': False,
@@ -177,6 +178,8 @@ class kucoinfutures(kucoin, ImplicitAPI):
177
178
  'funding-history': 4.44,
178
179
  'sub/api-key': 1,
179
180
  'trade-statistics': 1,
181
+ 'trade-fees': 1,
182
+ 'history-positions': 1,
180
183
  },
181
184
  'post': {
182
185
  'withdrawals': 1,
@@ -1107,6 +1110,71 @@ class kucoinfutures(kucoin, ImplicitAPI):
1107
1110
  data = self.safe_list(response, 'data')
1108
1111
  return self.parse_positions(data, symbols)
1109
1112
 
1113
+ async def fetch_positions_history(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
1114
+ """
1115
+ fetches historical positions
1116
+ :see: https://www.kucoin.com/docs/rest/futures-trading/positions/get-positions-history
1117
+ :param str[] [symbols]: list of unified market symbols
1118
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1119
+ :param int [params.until]: closing end time
1120
+ :param int [params.pageId]: page id
1121
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
1122
+ """
1123
+ await self.load_markets()
1124
+ if limit is None:
1125
+ limit = 200
1126
+ request = {
1127
+ 'limit': limit,
1128
+ }
1129
+ if since is not None:
1130
+ request['from'] = since
1131
+ until = self.safe_integer(params, 'until')
1132
+ if until is not None:
1133
+ params = self.omit(params, 'until')
1134
+ request['to'] = until
1135
+ response = await self.futuresPrivateGetHistoryPositions(self.extend(request, params))
1136
+ #
1137
+ # {
1138
+ # "success": True,
1139
+ # "code": "200",
1140
+ # "msg": "success",
1141
+ # "retry": False,
1142
+ # "data": {
1143
+ # "currentPage": 1,
1144
+ # "pageSize": 10,
1145
+ # "totalNum": 25,
1146
+ # "totalPage": 3,
1147
+ # "items": [
1148
+ # {
1149
+ # "closeId": "300000000000000030",
1150
+ # "positionId": "300000000000000009",
1151
+ # "uid": 99996908309485,
1152
+ # "userId": "6527d4fc8c7f3d0001f40f5f",
1153
+ # "symbol": "XBTUSDM",
1154
+ # "settleCurrency": "XBT",
1155
+ # "leverage": "0.0",
1156
+ # "type": "LIQUID_LONG",
1157
+ # "side": null,
1158
+ # "closeSize": null,
1159
+ # "pnl": "-1.0000003793999999",
1160
+ # "realisedGrossCost": "0.9993849748999999",
1161
+ # "withdrawPnl": "0.0",
1162
+ # "roe": null,
1163
+ # "tradeFee": "0.0006154045",
1164
+ # "fundingFee": "0.0",
1165
+ # "openTime": 1713785751181,
1166
+ # "closeTime": 1713785752784,
1167
+ # "openPrice": null,
1168
+ # "closePrice": null
1169
+ # }
1170
+ # ]
1171
+ # }
1172
+ # }
1173
+ #
1174
+ data = self.safe_dict(response, 'data')
1175
+ items = self.safe_list(data, 'items', [])
1176
+ return self.parse_positions(items, symbols)
1177
+
1110
1178
  def parse_position(self, position, market: Market = None):
1111
1179
  #
1112
1180
  # {
@@ -1153,16 +1221,46 @@ class kucoinfutures(kucoin, ImplicitAPI):
1153
1221
  # }
1154
1222
  # ]
1155
1223
  # }
1224
+ # position history
1225
+ # {
1226
+ # "closeId": "300000000000000030",
1227
+ # "positionId": "300000000000000009",
1228
+ # "uid": 99996908309485,
1229
+ # "userId": "6527d4fc8c7f3d0001f40f5f",
1230
+ # "symbol": "XBTUSDM",
1231
+ # "settleCurrency": "XBT",
1232
+ # "leverage": "0.0",
1233
+ # "type": "LIQUID_LONG",
1234
+ # "side": null,
1235
+ # "closeSize": null,
1236
+ # "pnl": "-1.0000003793999999",
1237
+ # "realisedGrossCost": "0.9993849748999999",
1238
+ # "withdrawPnl": "0.0",
1239
+ # "roe": null,
1240
+ # "tradeFee": "0.0006154045",
1241
+ # "fundingFee": "0.0",
1242
+ # "openTime": 1713785751181,
1243
+ # "closeTime": 1713785752784,
1244
+ # "openPrice": null,
1245
+ # "closePrice": null
1246
+ # }
1156
1247
  #
1157
1248
  symbol = self.safe_string(position, 'symbol')
1158
1249
  market = self.safe_market(symbol, market)
1159
1250
  timestamp = self.safe_integer(position, 'currentTimestamp')
1160
1251
  size = self.safe_string(position, 'currentQty')
1161
1252
  side = None
1162
- if Precise.string_gt(size, '0'):
1163
- side = 'long'
1164
- elif Precise.string_lt(size, '0'):
1165
- side = 'short'
1253
+ type = self.safe_string_lower(position, 'type')
1254
+ if size is not None:
1255
+ if Precise.string_gt(size, '0'):
1256
+ side = 'long'
1257
+ elif Precise.string_lt(size, '0'):
1258
+ side = 'short'
1259
+ elif type is not None:
1260
+ if type.find('long') > -1:
1261
+ side = 'long'
1262
+ else:
1263
+ side = 'short'
1166
1264
  notional = Precise.string_abs(self.safe_string(position, 'posCost'))
1167
1265
  initialMargin = self.safe_string(position, 'posInit')
1168
1266
  initialMarginPercentage = Precise.string_div(initialMargin, notional)
@@ -1170,25 +1268,27 @@ class kucoinfutures(kucoin, ImplicitAPI):
1170
1268
  unrealisedPnl = self.safe_string(position, 'unrealisedPnl')
1171
1269
  crossMode = self.safe_value(position, 'crossMode')
1172
1270
  # currently crossMode is always set to False and only isolated positions are supported
1173
- marginMode = 'cross' if crossMode else 'isolated'
1271
+ marginMode = None
1272
+ if crossMode is not None:
1273
+ marginMode = 'cross' if crossMode else 'isolated'
1174
1274
  return self.safe_position({
1175
1275
  'info': position,
1176
- 'id': self.safe_string(position, 'id'),
1276
+ 'id': self.safe_string_2(position, 'id', 'positionId'),
1177
1277
  'symbol': self.safe_string(market, 'symbol'),
1178
1278
  'timestamp': timestamp,
1179
1279
  'datetime': self.iso8601(timestamp),
1180
- 'lastUpdateTimestamp': None,
1280
+ 'lastUpdateTimestamp': self.safe_integer(position, 'closeTime'),
1181
1281
  'initialMargin': self.parse_number(initialMargin),
1182
1282
  'initialMarginPercentage': self.parse_number(initialMarginPercentage),
1183
1283
  'maintenanceMargin': self.safe_number(position, 'posMaint'),
1184
1284
  'maintenanceMarginPercentage': self.safe_number(position, 'maintMarginReq'),
1185
- 'entryPrice': self.safe_number(position, 'avgEntryPrice'),
1285
+ 'entryPrice': self.safe_number_2(position, 'avgEntryPrice', 'openPrice'),
1186
1286
  'notional': self.parse_number(notional),
1187
- 'leverage': self.safe_number(position, 'realLeverage'),
1287
+ 'leverage': self.safe_number_2(position, 'realLeverage', 'leverage'),
1188
1288
  'unrealizedPnl': self.parse_number(unrealisedPnl),
1189
1289
  'contracts': self.parse_number(Precise.string_abs(size)),
1190
1290
  'contractSize': self.safe_value(market, 'contractSize'),
1191
- 'realizedPnl': self.safe_number(position, 'realisedPnl'),
1291
+ 'realizedPnl': self.safe_number_2(position, 'realisedPnl', 'pnl'),
1192
1292
  'marginRatio': None,
1193
1293
  'liquidationPrice': self.safe_number(position, 'liquidationPrice'),
1194
1294
  'markPrice': self.safe_number(position, 'markPrice'),
@@ -2560,3 +2660,39 @@ class kucoinfutures(kucoin, ImplicitAPI):
2560
2660
  else:
2561
2661
  response = await self.futuresPrivatePostOrders(self.extend(request, params))
2562
2662
  return self.parse_order(response, market)
2663
+
2664
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2665
+ """
2666
+ fetch the trading fees for a market
2667
+ :see: https://www.kucoin.com/docs/rest/funding/trade-fee/trading-pair-actual-fee-futures
2668
+ :param str symbol: unified market symbol
2669
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2670
+ :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
2671
+ """
2672
+ await self.load_markets()
2673
+ market = self.market(symbol)
2674
+ request = {
2675
+ 'symbols': market['id'],
2676
+ }
2677
+ response = await self.privateGetTradeFees(self.extend(request, params))
2678
+ #
2679
+ # {
2680
+ # "code": "200000",
2681
+ # "data": {
2682
+ # "symbol": "XBTUSDTM",
2683
+ # "takerFeeRate": "0.0006",
2684
+ # "makerFeeRate": "0.0002"
2685
+ # }
2686
+ # }
2687
+ #
2688
+ data = self.safe_list(response, 'data', [])
2689
+ first = self.safe_dict(data, 0)
2690
+ marketId = self.safe_string(first, 'symbol')
2691
+ return {
2692
+ 'info': response,
2693
+ 'symbol': self.safe_symbol(marketId, market),
2694
+ 'maker': self.safe_number(first, 'makerFeeRate'),
2695
+ 'taker': self.safe_number(first, 'takerFeeRate'),
2696
+ 'percentage': True,
2697
+ 'tierBased': True,
2698
+ }
ccxt/async_support/okx.py CHANGED
@@ -2548,6 +2548,8 @@ class okx(Exchange, ImplicitAPI):
2548
2548
  takeProfitDefined = (takeProfit is not None)
2549
2549
  trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRatio')
2550
2550
  isTrailingPercentOrder = trailingPercent is not None
2551
+ trigger = (triggerPrice is not None) or (type == 'trigger')
2552
+ isReduceOnly = self.safe_value(params, 'reduceOnly', False)
2551
2553
  defaultMarginMode = self.safe_string_2(self.options, 'defaultMarginMode', 'marginMode', 'cross')
2552
2554
  marginMode = self.safe_string_2(params, 'marginMode', 'tdMode') # cross or isolated, tdMode not ommited so be extended into the request
2553
2555
  margin = False
@@ -2569,6 +2571,20 @@ class okx(Exchange, ImplicitAPI):
2569
2571
  positionSide, params = self.handle_option_and_params(params, 'createOrder', 'positionSide')
2570
2572
  if positionSide is not None:
2571
2573
  request['posSide'] = positionSide
2574
+ else:
2575
+ hedged = None
2576
+ hedged, params = self.handle_option_and_params(params, 'createOrder', 'hedged')
2577
+ if hedged:
2578
+ isBuy = (side == 'buy')
2579
+ isProtective = (takeProfitPrice is not None) or (stopLossPrice is not None) or isReduceOnly
2580
+ if isProtective:
2581
+ # in case of protective orders, the posSide should be opposite of position side
2582
+ # reduceOnly is emulated and not natively supported by the exchange
2583
+ request['posSide'] = 'short' if isBuy else 'long'
2584
+ if isReduceOnly:
2585
+ params = self.omit(params, 'reduceOnly')
2586
+ else:
2587
+ request['posSide'] = 'long' if isBuy else 'short'
2572
2588
  request['tdMode'] = marginMode
2573
2589
  isMarketOrder = type == 'market'
2574
2590
  postOnly = False
@@ -2576,7 +2592,6 @@ class okx(Exchange, ImplicitAPI):
2576
2592
  params = self.omit(params, ['currency', 'ccy', 'marginMode', 'timeInForce', 'stopPrice', 'triggerPrice', 'clientOrderId', 'stopLossPrice', 'takeProfitPrice', 'slOrdPx', 'tpOrdPx', 'margin', 'stopLoss', 'takeProfit', 'trailingPercent'])
2577
2593
  ioc = (timeInForce == 'IOC') or (type == 'ioc')
2578
2594
  fok = (timeInForce == 'FOK') or (type == 'fok')
2579
- trigger = (triggerPrice is not None) or (type == 'trigger')
2580
2595
  conditional = (stopLossPrice is not None) or (takeProfitPrice is not None) or (type == 'conditional')
2581
2596
  marketIOC = (isMarketOrder and ioc) or (type == 'optimal_limit_ioc')
2582
2597
  defaultTgtCcy = self.safe_string(self.options, 'tgtCcy', 'base_ccy')
@@ -2735,6 +2750,7 @@ class okx(Exchange, ImplicitAPI):
2735
2750
  :param str [params.positionSide]: if position mode is one-way: set to 'net', if position mode is hedge-mode: set to 'long' or 'short'
2736
2751
  :param str [params.trailingPercent]: the percent to trail away from the current market price
2737
2752
  :param str [params.tpOrdKind]: 'condition' or 'limit', the default is 'condition'
2753
+ :param str [params.hedged]: True/false, to automatically set exchange-specific params needed when trading in hedge mode
2738
2754
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2739
2755
  """
2740
2756
  await self.load_markets()
@@ -5852,6 +5868,36 @@ class okx(Exchange, ImplicitAPI):
5852
5868
  #
5853
5869
  return response
5854
5870
 
5871
+ async def fetch_position_mode(self, symbol: Str = None, params={}):
5872
+ """
5873
+ :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-account-configuration
5874
+ fetchs the position mode, hedged or one way, hedged for binance is set identically for all linear markets or all inverse markets
5875
+ :param str symbol: unified symbol of the market to fetch the order book for
5876
+ :param dict [params]: extra parameters specific to the exchange API endpoint
5877
+ :param str [param.accountId]: if you have multiple accounts, you must specify the account id to fetch the position mode
5878
+ :returns dict: an object detailing whether the market is in hedged or one-way mode
5879
+ """
5880
+ accounts = await self.fetch_accounts()
5881
+ length = len(accounts)
5882
+ selectedAccount = None
5883
+ if length > 1:
5884
+ accountId = self.safe_string(params, 'accountId')
5885
+ if accountId is None:
5886
+ accountIds = self.get_list_from_object_values(accounts, 'id')
5887
+ raise ExchangeError(self.id + ' fetchPositionMode() can not detect position mode, because you have multiple accounts. Set params["accountId"] to desired id from: ' + ', '.join(accountIds))
5888
+ else:
5889
+ accountsById = self.index_by(accounts, 'id')
5890
+ selectedAccount = self.safe_dict(accountsById, accountId)
5891
+ else:
5892
+ selectedAccount = accounts[0]
5893
+ mainAccount = selectedAccount['info']
5894
+ posMode = self.safe_string(mainAccount, 'posMode') # long_short_mode, net_mode
5895
+ isHedged = posMode == 'long_short_mode'
5896
+ return {
5897
+ 'info': mainAccount,
5898
+ 'hedged': isHedged,
5899
+ }
5900
+
5855
5901
  async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
5856
5902
  """
5857
5903
  set hedged to True or False for a market
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.8'
7
+ __version__ = '4.3.10'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -5693,15 +5693,15 @@ class Exchange(object):
5693
5693
  fromId = self.safe_string(entry, fromCurrencyKey)
5694
5694
  toId = self.safe_string(entry, toCurrencyKey)
5695
5695
  if fromId is not None:
5696
- fromCurrency = self.currency(fromId)
5696
+ fromCurrency = self.safe_currency(fromId)
5697
5697
  if toId is not None:
5698
- toCurrency = self.currency(toId)
5698
+ toCurrency = self.safe_currency(toId)
5699
5699
  conversion = self.extend(self.parseConversion(entry, fromCurrency, toCurrency), params)
5700
5700
  result.append(conversion)
5701
5701
  sorted = self.sort_by(result, 'timestamp')
5702
5702
  currency = None
5703
5703
  if code is not None:
5704
- currency = self.currency(code)
5704
+ currency = self.safe_currency(code)
5705
5705
  code = currency['code']
5706
5706
  if code is None:
5707
5707
  return self.filter_by_since_limit(sorted, since, limit)
ccxt/base/types.py CHANGED
@@ -176,6 +176,8 @@ class Order(TypedDict):
176
176
  stopLossPrice: Num
177
177
  cost: Num
178
178
  trades: List[Trade]
179
+ reduceOnly: Bool
180
+ postOnly: Bool
179
181
  fee: Fee
180
182
 
181
183
 
ccxt/bingx.py CHANGED
@@ -303,7 +303,6 @@ class bingx(Exchange, ImplicitAPI):
303
303
  'get': {
304
304
  'list': 3,
305
305
  'assets': 3,
306
- 'apiKey/query': 1,
307
306
  },
308
307
  'post': {
309
308
  'create': 3,
@@ -320,6 +319,7 @@ class bingx(Exchange, ImplicitAPI):
320
319
  'private': {
321
320
  'get': {
322
321
  'uid': 1,
322
+ 'apiKey/query': 1,
323
323
  },
324
324
  'post': {
325
325
  'innerTransfer/authorizeSubAccount': 3,
@@ -1755,6 +1755,12 @@ class bingx(Exchange, ImplicitAPI):
1755
1755
  }
1756
1756
  isMarketOrder = type == 'MARKET'
1757
1757
  isSpot = marketType == 'spot'
1758
+ stopLossPrice = self.safe_string(params, 'stopLossPrice')
1759
+ takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1760
+ triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
1761
+ isTriggerOrder = triggerPrice is not None
1762
+ isStopLossPriceOrder = stopLossPrice is not None
1763
+ isTakeProfitPriceOrder = takeProfitPrice is not None
1758
1764
  exchangeClientOrderId = 'newClientOrderId' if isSpot else 'clientOrderID'
1759
1765
  clientOrderId = self.safe_string_2(params, exchangeClientOrderId, 'clientOrderId')
1760
1766
  if clientOrderId is not None:
@@ -1767,7 +1773,6 @@ class bingx(Exchange, ImplicitAPI):
1767
1773
  request['timeInForce'] = 'IOC'
1768
1774
  elif timeInForce == 'GTC':
1769
1775
  request['timeInForce'] = 'GTC'
1770
- triggerPrice = self.safe_string_2(params, 'stopPrice', 'triggerPrice')
1771
1776
  if isSpot:
1772
1777
  cost = self.safe_number_2(params, 'cost', 'quoteOrderQty')
1773
1778
  params = self.omit(params, 'cost')
@@ -1790,17 +1795,19 @@ class bingx(Exchange, ImplicitAPI):
1790
1795
  request['type'] = 'TRIGGER_LIMIT'
1791
1796
  elif type == 'MARKET':
1792
1797
  request['type'] = 'TRIGGER_MARKET'
1798
+ elif (stopLossPrice is not None) or (takeProfitPrice is not None):
1799
+ stopTakePrice = stopLossPrice if (stopLossPrice is not None) else takeProfitPrice
1800
+ if type == 'LIMIT':
1801
+ request['type'] = 'TAKE_STOP_LIMIT'
1802
+ elif type == 'MARKET':
1803
+ request['type'] = 'TAKE_STOP_MARKET'
1804
+ request['stopPrice'] = self.parse_to_numeric(self.price_to_precision(symbol, stopTakePrice))
1793
1805
  else:
1794
1806
  if timeInForce == 'FOK':
1795
1807
  request['timeInForce'] = 'FOK'
1796
- stopLossPrice = self.safe_string(params, 'stopLossPrice')
1797
- takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
1798
1808
  trailingAmount = self.safe_string(params, 'trailingAmount')
1799
1809
  trailingPercent = self.safe_string_2(params, 'trailingPercent', 'priceRate')
1800
1810
  trailingType = self.safe_string(params, 'trailingType', 'TRAILING_STOP_MARKET')
1801
- isTriggerOrder = triggerPrice is not None
1802
- isStopLossPriceOrder = stopLossPrice is not None
1803
- isTakeProfitPriceOrder = takeProfitPrice is not None
1804
1811
  isTrailingAmountOrder = trailingAmount is not None
1805
1812
  isTrailingPercentOrder = trailingPercent is not None
1806
1813
  isTrailing = isTrailingAmountOrder or isTrailingPercentOrder
@@ -1878,7 +1885,7 @@ class bingx(Exchange, ImplicitAPI):
1878
1885
  positionSide = 'LONG' if (side == 'buy') else 'SHORT'
1879
1886
  request['positionSide'] = positionSide
1880
1887
  request['quantity'] = self.parse_to_numeric(self.amount_to_precision(symbol, amount))
1881
- params = self.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'trailingType', 'takeProfit', 'stopLoss', 'clientOrderId'])
1888
+ params = self.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'trailingType', 'takeProfit', 'stopLoss', 'clientOrderId'])
1882
1889
  return self.extend(request, params)
1883
1890
 
1884
1891
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
@@ -1896,9 +1903,9 @@ class bingx(Exchange, ImplicitAPI):
1896
1903
  :param bool [params.postOnly]: True to place a post only order
1897
1904
  :param str [params.timeInForce]: spot supports 'PO', 'GTC' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1898
1905
  :param bool [params.reduceOnly]: *swap only* True or False whether the order is reduce only
1899
- :param float [params.triggerPrice]: *swap only* triggerPrice at which the attached take profit / stop loss order will be triggered
1900
- :param float [params.stopLossPrice]: *swap only* stop loss trigger price
1901
- :param float [params.takeProfitPrice]: *swap only* take profit trigger price
1906
+ :param float [params.triggerPrice]: triggerPrice at which the attached take profit / stop loss order will be triggered
1907
+ :param float [params.stopLossPrice]: stop loss trigger price
1908
+ :param float [params.takeProfitPrice]: take profit trigger price
1902
1909
  :param float [params.cost]: the quote quantity that can be used alternative for the amount
1903
1910
  :param float [params.trailingAmount]: *swap only* the quote amount to trail away from the current market price
1904
1911
  :param float [params.trailingPercent]: *swap only* the percent to trail away from the current market price
ccxt/bitget.py CHANGED
@@ -7863,7 +7863,7 @@ class bitget(Exchange, ImplicitAPI):
7863
7863
  """
7864
7864
  fetches historical positions
7865
7865
  :see: https://www.bitget.com/api-doc/contract/position/Get-History-Position
7866
- :param str [symbol]: unified contract symbols
7866
+ :param str[] [symbols]: unified contract symbols
7867
7867
  :param int [since]: timestamp in ms of the earliest position to fetch, default=3 months ago, max range for params["until"] - since is 3 months
7868
7868
  :param int [limit]: the maximum amount of records to fetch, default=20, max=100
7869
7869
  :param dict params: extra parameters specific to the exchange api endpoint