ccxt 4.4.36__py2.py3-none-any.whl → 4.4.38__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.
Files changed (53) hide show
  1. ccxt/__init__.py +3 -3
  2. ccxt/abstract/bingx.py +0 -1
  3. ccxt/abstract/bitfinex.py +136 -65
  4. ccxt/abstract/bitfinex1.py +69 -0
  5. ccxt/async_support/__init__.py +3 -3
  6. ccxt/async_support/base/exchange.py +1 -1
  7. ccxt/async_support/binance.py +0 -2
  8. ccxt/async_support/bingx.py +89 -8
  9. ccxt/async_support/bitfinex.py +3005 -1084
  10. ccxt/async_support/bitfinex1.py +1704 -0
  11. ccxt/async_support/bitget.py +2 -4
  12. ccxt/async_support/bithumb.py +1 -1
  13. ccxt/async_support/bitmart.py +160 -13
  14. ccxt/async_support/bybit.py +3 -2
  15. ccxt/async_support/coinbase.py +86 -0
  16. ccxt/async_support/gate.py +1 -1
  17. ccxt/async_support/hyperliquid.py +124 -14
  18. ccxt/async_support/kucoin.py +75 -2
  19. ccxt/async_support/kucoinfutures.py +92 -5
  20. ccxt/async_support/ndax.py +5 -1
  21. ccxt/async_support/okx.py +0 -1
  22. ccxt/async_support/paradex.py +2 -2
  23. ccxt/async_support/probit.py +3 -1
  24. ccxt/base/exchange.py +9 -2
  25. ccxt/binance.py +0 -2
  26. ccxt/bingx.py +89 -8
  27. ccxt/bitfinex.py +3005 -1084
  28. ccxt/bitfinex1.py +1703 -0
  29. ccxt/bitget.py +2 -4
  30. ccxt/bithumb.py +1 -1
  31. ccxt/bitmart.py +160 -13
  32. ccxt/bybit.py +3 -2
  33. ccxt/coinbase.py +86 -0
  34. ccxt/gate.py +1 -1
  35. ccxt/hyperliquid.py +124 -14
  36. ccxt/kucoin.py +75 -2
  37. ccxt/kucoinfutures.py +92 -5
  38. ccxt/ndax.py +5 -1
  39. ccxt/okx.py +0 -1
  40. ccxt/paradex.py +2 -2
  41. ccxt/pro/__init__.py +3 -3
  42. ccxt/pro/bitfinex.py +725 -274
  43. ccxt/pro/bitfinex1.py +635 -0
  44. ccxt/pro/probit.py +1 -0
  45. ccxt/probit.py +3 -1
  46. ccxt/test/tests_async.py +5 -1
  47. ccxt/test/tests_sync.py +5 -1
  48. {ccxt-4.4.36.dist-info → ccxt-4.4.38.dist-info}/METADATA +8 -8
  49. {ccxt-4.4.36.dist-info → ccxt-4.4.38.dist-info}/RECORD +52 -49
  50. ccxt/abstract/bitfinex2.py +0 -140
  51. {ccxt-4.4.36.dist-info → ccxt-4.4.38.dist-info}/LICENSE.txt +0 -0
  52. {ccxt-4.4.36.dist-info → ccxt-4.4.38.dist-info}/WHEEL +0 -0
  53. {ccxt-4.4.36.dist-info → ccxt-4.4.38.dist-info}/top_level.txt +0 -0
@@ -928,6 +928,7 @@ class kucoin(Exchange, ImplicitAPI):
928
928
  'TRUE': 'true',
929
929
  'CS': 'cs',
930
930
  'ORAI': 'orai',
931
+ 'BASE': 'base',
931
932
  # below will be uncommented after consensus
932
933
  # 'BITCOINDIAMON': 'bcd',
933
934
  # 'BITCOINGOLD': 'btg',
@@ -1003,6 +1004,74 @@ class kucoin(Exchange, ImplicitAPI):
1003
1004
  'spot': 'TRADE',
1004
1005
  },
1005
1006
  },
1007
+ 'features': {
1008
+ 'spot': {
1009
+ 'sandbox': False,
1010
+ 'createOrder': {
1011
+ 'marginMode': True,
1012
+ 'triggerPrice': True,
1013
+ 'triggerPriceType': None,
1014
+ 'triggerDirection': False,
1015
+ 'stopLossPrice': True,
1016
+ 'takeProfitPrice': True,
1017
+ 'attachedStopLossTakeProfit': None, # not supported
1018
+ 'timeInForce': {
1019
+ 'IOC': True,
1020
+ 'FOK': True,
1021
+ 'PO': True,
1022
+ 'GTD': True,
1023
+ },
1024
+ 'hedged': False,
1025
+ 'trailing': False,
1026
+ # exchange-supported features
1027
+ # 'iceberg': True,
1028
+ # 'selfTradePrevention': True,
1029
+ # 'twap': False,
1030
+ # 'oco': False,
1031
+ },
1032
+ 'createOrders': {
1033
+ 'max': 5,
1034
+ },
1035
+ 'fetchMyTrades': {
1036
+ 'marginMode': True,
1037
+ 'limit': None,
1038
+ 'daysBack': None,
1039
+ 'untilDays': 7, # per implementation comments
1040
+ },
1041
+ 'fetchOrder': {
1042
+ 'marginMode': False,
1043
+ 'trigger': True,
1044
+ 'trailing': False,
1045
+ },
1046
+ 'fetchOpenOrders': {
1047
+ 'marginMode': True,
1048
+ 'limit': 500,
1049
+ 'trigger': True,
1050
+ 'trailing': False,
1051
+ },
1052
+ 'fetchOrders': None,
1053
+ 'fetchClosedOrders': {
1054
+ 'marginMode': True,
1055
+ 'limit': 500,
1056
+ 'daysBackClosed': None,
1057
+ 'daysBackCanceled': None,
1058
+ 'untilDays': 7,
1059
+ 'trigger': True,
1060
+ 'trailing': False,
1061
+ },
1062
+ 'fetchOHLCV': {
1063
+ 'limit': 1500,
1064
+ },
1065
+ },
1066
+ 'swap': {
1067
+ 'linear': None,
1068
+ 'inverse': None,
1069
+ },
1070
+ 'future': {
1071
+ 'linear': None,
1072
+ 'inverse': None,
1073
+ },
1074
+ },
1006
1075
  })
1007
1076
 
1008
1077
  def nonce(self):
@@ -2616,7 +2685,7 @@ class kucoin(Exchange, ImplicitAPI):
2616
2685
  await self.load_markets()
2617
2686
  lowercaseStatus = status.lower()
2618
2687
  until = self.safe_integer(params, 'until')
2619
- stop = self.safe_bool_2(params, 'stop', 'trigger', False)
2688
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
2620
2689
  hf = None
2621
2690
  hf, params = self.handle_hf_and_params(params)
2622
2691
  if hf and (symbol is None):
@@ -2642,7 +2711,7 @@ class kucoin(Exchange, ImplicitAPI):
2642
2711
  request['endAt'] = until
2643
2712
  request['tradeType'] = self.safe_string(self.options['marginModes'], marginMode, 'TRADE')
2644
2713
  response = None
2645
- if stop:
2714
+ if trigger:
2646
2715
  response = await self.privateGetStopOrder(self.extend(request, query))
2647
2716
  elif hf:
2648
2717
  if lowercaseStatus == 'active':
@@ -3054,6 +3123,10 @@ class kucoin(Exchange, ImplicitAPI):
3054
3123
  response = None
3055
3124
  request, params = self.handle_until_option('endAt', request, params)
3056
3125
  if hf:
3126
+ # does not return trades earlier than 2019-02-18T00:00:00Z
3127
+ if since is not None:
3128
+ # only returns trades up to one week after the since param
3129
+ request['startAt'] = since
3057
3130
  response = await self.privateGetHfFills(self.extend(request, params))
3058
3131
  elif method == 'private_get_fills':
3059
3132
  # does not return trades earlier than 2019-02-18T00:00:00Z
@@ -370,6 +370,91 @@ class kucoinfutures(kucoin, ImplicitAPI):
370
370
  # 'code': 'BTC',
371
371
  # },
372
372
  },
373
+ 'features': {
374
+ 'spot': None,
375
+ 'forDerivs': {
376
+ 'sandbox': False,
377
+ 'createOrder': {
378
+ 'marginMode': True,
379
+ 'triggerPrice': True,
380
+ 'triggerPriceType': {
381
+ 'last': True,
382
+ 'mark': True,
383
+ 'index': True,
384
+ },
385
+ 'triggerDirection': True,
386
+ 'stopLossPrice': True,
387
+ 'takeProfitPrice': True,
388
+ 'attachedStopLossTakeProfit': {
389
+ 'triggerPrice': None,
390
+ 'triggerPriceType': None,
391
+ 'limitPrice': True,
392
+ },
393
+ 'timeInForce': {
394
+ 'IOC': True,
395
+ 'FOK': False,
396
+ 'PO': True,
397
+ 'GTD': False,
398
+ },
399
+ 'hedged': False,
400
+ 'trailing': False,
401
+ # exchange-supported features
402
+ # 'iceberg': True,
403
+ # 'selfTradePrevention': True,
404
+ # 'twap': False,
405
+ # 'oco': False,
406
+ },
407
+ 'createOrders': {
408
+ 'max': 20,
409
+ },
410
+ 'fetchMyTrades': {
411
+ 'marginMode': True,
412
+ 'limit': 1000,
413
+ 'daysBack': None,
414
+ 'untilDays': 7,
415
+ },
416
+ 'fetchOrder': {
417
+ 'marginMode': False,
418
+ 'trigger': False,
419
+ 'trailing': False,
420
+ },
421
+ 'fetchOpenOrders': {
422
+ 'marginMode': False,
423
+ 'limit': 1000,
424
+ 'trigger': True,
425
+ 'trailing': False,
426
+ },
427
+ 'fetchOrders': None,
428
+ 'fetchClosedOrders': {
429
+ 'marginMode': False,
430
+ 'limit': 1000,
431
+ 'daysBackClosed': None,
432
+ 'daysBackCanceled': None,
433
+ 'untilDays': None,
434
+ 'trigger': True,
435
+ 'trailing': False,
436
+ },
437
+ 'fetchOHLCV': {
438
+ 'limit': 500,
439
+ },
440
+ },
441
+ 'swap': {
442
+ 'linear': {
443
+ 'extends': 'forDerivs',
444
+ },
445
+ 'inverse': {
446
+ 'extends': 'forDerivs',
447
+ },
448
+ },
449
+ 'future': {
450
+ 'linear': {
451
+ 'extends': 'forDerivs',
452
+ },
453
+ 'inverse': {
454
+ 'extends': 'forDerivs',
455
+ },
456
+ },
457
+ },
373
458
  })
374
459
 
375
460
  async def fetch_status(self, params={}):
@@ -1698,10 +1783,10 @@ class kucoinfutures(kucoin, ImplicitAPI):
1698
1783
  request: dict = {}
1699
1784
  if symbol is not None:
1700
1785
  request['symbol'] = self.market_id(symbol)
1701
- stop = self.safe_value_2(params, 'stop', 'trigger')
1786
+ trigger = self.safe_value_2(params, 'stop', 'trigger')
1702
1787
  params = self.omit(params, ['stop', 'trigger'])
1703
1788
  response = None
1704
- if stop:
1789
+ if trigger:
1705
1790
  response = await self.futuresPrivateDeleteStopOrders(self.extend(request, params))
1706
1791
  else:
1707
1792
  response = await self.futuresPrivateDeleteOrders(self.extend(request, params))
@@ -1882,7 +1967,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1882
1967
  paginate, params = self.handle_option_and_params(params, 'fetchOrdersByStatus', 'paginate')
1883
1968
  if paginate:
1884
1969
  return await self.fetch_paginated_call_dynamic('fetchOrdersByStatus', symbol, since, limit, params)
1885
- stop = self.safe_bool_2(params, 'stop', 'trigger')
1970
+ trigger = self.safe_bool_2(params, 'stop', 'trigger')
1886
1971
  until = self.safe_integer(params, 'until')
1887
1972
  params = self.omit(params, ['stop', 'until', 'trigger'])
1888
1973
  if status == 'closed':
@@ -1890,7 +1975,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1890
1975
  elif status == 'open':
1891
1976
  status = 'active'
1892
1977
  request: dict = {}
1893
- if not stop:
1978
+ if not trigger:
1894
1979
  request['status'] = status
1895
1980
  elif status != 'active':
1896
1981
  raise BadRequest(self.id + ' fetchOrdersByStatus() can only fetch untriggered stop orders')
@@ -1903,7 +1988,7 @@ class kucoinfutures(kucoin, ImplicitAPI):
1903
1988
  if until is not None:
1904
1989
  request['endAt'] = until
1905
1990
  response = None
1906
- if stop:
1991
+ if trigger:
1907
1992
  response = await self.futuresPrivateGetStopOrders(self.extend(request, params))
1908
1993
  else:
1909
1994
  response = await self.futuresPrivateGetOrders(self.extend(request, params))
@@ -2510,6 +2595,8 @@ class kucoinfutures(kucoin, ImplicitAPI):
2510
2595
  request['symbol'] = market['id']
2511
2596
  if since is not None:
2512
2597
  request['startAt'] = since
2598
+ if limit is not None:
2599
+ request['pageSize'] = min(1000, limit)
2513
2600
  request, params = self.handle_until_option('endAt', request, params)
2514
2601
  response = await self.futuresPrivateGetFills(self.extend(request, params))
2515
2602
  #
@@ -1069,8 +1069,10 @@ class ndax(Exchange, ImplicitAPI):
1069
1069
  omsId = self.safe_integer(self.options, 'omsId', 1)
1070
1070
  await self.load_markets()
1071
1071
  await self.load_accounts()
1072
- defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId', int(self.accounts[0]['id']))
1072
+ defaultAccountId = self.safe_integer_2(self.options, 'accountId', 'AccountId')
1073
1073
  accountId = self.safe_integer_2(params, 'accountId', 'AccountId', defaultAccountId)
1074
+ if accountId is None:
1075
+ accountId = int(self.accounts[0]['id'])
1074
1076
  params = self.omit(params, ['accountId', 'AccountId'])
1075
1077
  request: dict = {
1076
1078
  'omsId': omsId,
@@ -1348,6 +1350,7 @@ class ndax(Exchange, ImplicitAPI):
1348
1350
  :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1349
1351
  :param dict [params]: extra parameters specific to the exchange API endpoint
1350
1352
  :param float [params.triggerPrice]: the price at which a trigger order would be triggered
1353
+ :param str [params.clientOrderId]: a unique id for the order
1351
1354
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1352
1355
  """
1353
1356
  omsId = self.safe_integer(self.options, 'omsId', 1)
@@ -1578,6 +1581,7 @@ class ndax(Exchange, ImplicitAPI):
1578
1581
  :param str id: order id
1579
1582
  :param str symbol: unified symbol of the market the order was made in
1580
1583
  :param dict [params]: extra parameters specific to the exchange API endpoint
1584
+ :param str [params.clientOrderId]: a unique id for the order
1581
1585
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1582
1586
  """
1583
1587
  omsId = self.safe_integer(self.options, 'omsId', 1)
ccxt/async_support/okx.py CHANGED
@@ -1225,7 +1225,6 @@ class okx(Exchange, ImplicitAPI):
1225
1225
  'limitPrice': True,
1226
1226
  },
1227
1227
  'timeInForce': {
1228
- 'GTC': True,
1229
1228
  'IOC': True,
1230
1229
  'FOK': True,
1231
1230
  'PO': True,
@@ -276,6 +276,7 @@ class paradex(Exchange, ImplicitAPI):
276
276
  'commonCurrencies': {
277
277
  },
278
278
  'options': {
279
+ 'paradexAccount': None, # add {"privateKey": A, "publicKey": B, "address": C}
279
280
  'broker': 'CCXT',
280
281
  },
281
282
  })
@@ -964,10 +965,10 @@ class paradex(Exchange, ImplicitAPI):
964
965
  }
965
966
 
966
967
  async def retrieve_account(self):
967
- self.check_required_credentials()
968
968
  cachedAccount: dict = self.safe_dict(self.options, 'paradexAccount')
969
969
  if cachedAccount is not None:
970
970
  return cachedAccount
971
+ self.check_required_credentials()
971
972
  systemConfig = await self.get_system_config()
972
973
  domain = await self.prepare_paradex_domain(True)
973
974
  messageTypes = {
@@ -1956,7 +1957,6 @@ class paradex(Exchange, ImplicitAPI):
1956
1957
  if query:
1957
1958
  url += '?' + self.urlencode(query)
1958
1959
  elif api == 'private':
1959
- self.check_required_credentials()
1960
1960
  headers = {
1961
1961
  'Accept': 'application/json',
1962
1962
  'PARADEX-PARTNER': self.safe_string(self.options, 'broker', 'CCXT'),
@@ -287,6 +287,8 @@ class probit(Exchange, ImplicitAPI):
287
287
  base = self.safe_currency_code(baseId)
288
288
  quote = self.safe_currency_code(quoteId)
289
289
  closed = self.safe_bool(market, 'closed', False)
290
+ showInUI = self.safe_bool(market, 'show_in_ui', True)
291
+ active = not closed and showInUI
290
292
  takerFeeRate = self.safe_string(market, 'taker_fee_rate')
291
293
  taker = Precise.string_div(takerFeeRate, '100')
292
294
  makerFeeRate = self.safe_string(market, 'maker_fee_rate')
@@ -306,7 +308,7 @@ class probit(Exchange, ImplicitAPI):
306
308
  'swap': False,
307
309
  'future': False,
308
310
  'option': False,
309
- 'active': not closed,
311
+ 'active': active,
310
312
  'contract': False,
311
313
  'linear': None,
312
314
  'inverse': None,
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.36'
7
+ __version__ = '4.4.38'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2791,6 +2791,9 @@ class Exchange(object):
2791
2791
 
2792
2792
  def features_mapper(self, initialFeatures: Any, marketType: Str, subType: Str = None):
2793
2793
  featuresObj = initialFeatures[marketType][subType] if (subType is not None) else initialFeatures[marketType]
2794
+ # if exchange does not have that market-type(eg. future>inverse)
2795
+ if featuresObj is None:
2796
+ return None
2794
2797
  extendsStr: Str = self.safe_string(featuresObj, 'extends')
2795
2798
  if extendsStr is not None:
2796
2799
  featuresObj = self.omit(featuresObj, 'extends')
@@ -2804,9 +2807,13 @@ class Exchange(object):
2804
2807
  if value is not None:
2805
2808
  featuresObj['createOrder']['stopLoss'] = value
2806
2809
  featuresObj['createOrder']['takeProfit'] = value
2807
- # False 'hedged' for spot
2810
+ # for spot, default 'hedged' to False
2808
2811
  if marketType == 'spot':
2809
2812
  featuresObj['createOrder']['hedged'] = False
2813
+ # default 'GTC' to True
2814
+ gtcValue = self.safe_bool(featuresObj['createOrder']['timeInForce'], 'gtc')
2815
+ if gtcValue is None:
2816
+ featuresObj['createOrder']['timeInForce']['GTC'] = True
2810
2817
  return featuresObj
2811
2818
 
2812
2819
  def orderbook_checksum_message(self, symbol: Str):
ccxt/binance.py CHANGED
@@ -1591,7 +1591,6 @@ class binance(Exchange, ImplicitAPI):
1591
1591
  'takeProfitPrice': True,
1592
1592
  'attachedStopLossTakeProfit': None, # not supported
1593
1593
  'timeInForce': {
1594
- 'GTC': True,
1595
1594
  'IOC': True,
1596
1595
  'FOK': True,
1597
1596
  'PO': True,
@@ -1658,7 +1657,6 @@ class binance(Exchange, ImplicitAPI):
1658
1657
  'takeProfitPrice': True,
1659
1658
  'attachedStopLossTakeProfit': None, # not supported
1660
1659
  'timeInForce': {
1661
- 'GTC': True,
1662
1660
  'IOC': True,
1663
1661
  'FOK': True,
1664
1662
  'PO': True,
ccxt/bingx.py CHANGED
@@ -95,7 +95,7 @@ class bingx(Exchange, ImplicitAPI):
95
95
  'fetchPositionHistory': False,
96
96
  'fetchPositionMode': True,
97
97
  'fetchPositions': True,
98
- 'fetchPositionsHistory': False,
98
+ 'fetchPositionsHistory': True,
99
99
  'fetchTicker': True,
100
100
  'fetchTickers': True,
101
101
  'fetchTime': True,
@@ -219,7 +219,6 @@ class bingx(Exchange, ImplicitAPI):
219
219
  'private': {
220
220
  'get': {
221
221
  'positionSide/dual': 5,
222
- 'market/markPriceKlines': 1,
223
222
  'trade/batchCancelReplace': 5,
224
223
  'trade/fullOrder': 2,
225
224
  'maintMarginRatio': 2,
@@ -553,7 +552,6 @@ class bingx(Exchange, ImplicitAPI):
553
552
  'limitPrice': True,
554
553
  },
555
554
  'timeInForce': {
556
- 'GTC': True,
557
555
  'IOC': True,
558
556
  'FOK': True,
559
557
  'PO': True,
@@ -1015,7 +1013,7 @@ class bingx(Exchange, ImplicitAPI):
1015
1013
  https://bingx-api.github.io/docs/#/swapV2/market-api.html#K-Line%20Data
1016
1014
  https://bingx-api.github.io/docs/#/spot/market-api.html#Candlestick%20chart%20data
1017
1015
  https://bingx-api.github.io/docs/#/swapV2/market-api.html#%20K-Line%20Data
1018
- https://bingx-api.github.io/docs/#/en-us/swapV2/market-api.html#K-Line%20Data%20-%20Mark%20Price
1016
+ https://bingx-api.github.io/docs/#/en-us/swapV2/market-api.html#Mark%20Price%20Kline/Candlestick%20Data
1019
1017
  https://bingx-api.github.io/docs/#/en-us/cswap/market-api.html#Get%20K-line%20Data
1020
1018
 
1021
1019
  :param str symbol: unified symbol of the market to fetch OHLCV data for
@@ -1055,7 +1053,7 @@ class bingx(Exchange, ImplicitAPI):
1055
1053
  price = self.safe_string(params, 'price')
1056
1054
  params = self.omit(params, 'price')
1057
1055
  if price == 'mark':
1058
- response = self.swapV1PrivateGetMarketMarkPriceKlines(self.extend(request, params))
1056
+ response = self.swapV1PublicGetMarketMarkPriceKlines(self.extend(request, params))
1059
1057
  else:
1060
1058
  response = self.swapV3PublicGetQuoteKlines(self.extend(request, params))
1061
1059
  #
@@ -2264,6 +2262,67 @@ class bingx(Exchange, ImplicitAPI):
2264
2262
  result[code] = account
2265
2263
  return self.safe_balance(result)
2266
2264
 
2265
+ def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Position]:
2266
+ """
2267
+ fetches historical positions
2268
+
2269
+ https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#Query%20Position%20History
2270
+
2271
+ :param str symbol: unified contract symbol
2272
+ :param int [since]: the earliest time in ms to fetch positions for
2273
+ :param int [limit]: the maximum amount of records to fetch
2274
+ :param dict [params]: extra parameters specific to the exchange api endpoint
2275
+ :param int [params.until]: the latest time in ms to fetch positions for
2276
+ :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
2277
+ """
2278
+ self.load_markets()
2279
+ market = self.market(symbol)
2280
+ request: dict = {
2281
+ 'symbol': market['id'],
2282
+ }
2283
+ if limit is not None:
2284
+ request['pageSize'] = limit
2285
+ if since is not None:
2286
+ request['startTs'] = since
2287
+ request, params = self.handle_until_option('endTs', request, params)
2288
+ response = None
2289
+ if market['linear']:
2290
+ response = self.swapV1PrivateGetTradePositionHistory(self.extend(request, params))
2291
+ else:
2292
+ raise NotSupported(self.id + ' fetchPositionHistory() is not supported for inverse swap positions')
2293
+ #
2294
+ # {
2295
+ # "code": 0,
2296
+ # "msg": "",
2297
+ # "data": {
2298
+ # "positionHistory": [
2299
+ # {
2300
+ # "positionId": "1861675561156571136",
2301
+ # "symbol": "LTC-USDT",
2302
+ # "isolated": False,
2303
+ # "positionSide": "LONG",
2304
+ # "openTime": 1732693017000,
2305
+ # "updateTime": 1733310292000,
2306
+ # "avgPrice": "95.18",
2307
+ # "avgClosePrice": "129.48",
2308
+ # "realisedProfit": "102.89",
2309
+ # "netProfit": "99.63",
2310
+ # "positionAmt": "30.0",
2311
+ # "closePositionAmt": "30.0",
2312
+ # "leverage": 6,
2313
+ # "closeAllPositions": True,
2314
+ # "positionCommission": "-0.33699650000000003",
2315
+ # "totalFunding": "-2.921461693902908"
2316
+ # },
2317
+ # ]
2318
+ # }
2319
+ # }
2320
+ #
2321
+ data = self.safe_dict(response, 'data', {})
2322
+ records = self.safe_list(data, 'positionHistory', [])
2323
+ positions = self.parse_positions(records)
2324
+ return self.filter_by_symbol_since_limit(positions, symbol, since, limit)
2325
+
2267
2326
  def fetch_positions(self, symbols: Strings = None, params={}):
2268
2327
  """
2269
2328
  fetch all open positions
@@ -2503,12 +2562,34 @@ class bingx(Exchange, ImplicitAPI):
2503
2562
  # "positionAmt": "1.20365912",
2504
2563
  # }
2505
2564
  #
2565
+ # linear swap fetchPositionHistory
2566
+ #
2567
+ # {
2568
+ # "positionId": "1861675561156571136",
2569
+ # "symbol": "LTC-USDT",
2570
+ # "isolated": False,
2571
+ # "positionSide": "LONG",
2572
+ # "openTime": 1732693017000,
2573
+ # "updateTime": 1733310292000,
2574
+ # "avgPrice": "95.18",
2575
+ # "avgClosePrice": "129.48",
2576
+ # "realisedProfit": "102.89",
2577
+ # "netProfit": "99.63",
2578
+ # "positionAmt": "30.0",
2579
+ # "closePositionAmt": "30.0",
2580
+ # "leverage": 6,
2581
+ # "closeAllPositions": True,
2582
+ # "positionCommission": "-0.33699650000000003",
2583
+ # "totalFunding": "-2.921461693902908"
2584
+ # }
2585
+ #
2506
2586
  marketId = self.safe_string(position, 'symbol', '')
2507
2587
  marketId = marketId.replace('/', '-') # standard return different format
2508
2588
  isolated = self.safe_bool(position, 'isolated')
2509
2589
  marginMode = None
2510
2590
  if isolated is not None:
2511
2591
  marginMode = 'isolated' if isolated else 'cross'
2592
+ timestamp = self.safe_integer(position, 'openTime')
2512
2593
  return self.safe_position({
2513
2594
  'info': position,
2514
2595
  'id': self.safe_string(position, 'positionId'),
@@ -2526,8 +2607,8 @@ class bingx(Exchange, ImplicitAPI):
2526
2607
  'lastPrice': None,
2527
2608
  'side': self.safe_string_lower(position, 'positionSide'),
2528
2609
  'hedged': None,
2529
- 'timestamp': None,
2530
- 'datetime': None,
2610
+ 'timestamp': timestamp,
2611
+ 'datetime': self.iso8601(timestamp),
2531
2612
  'lastUpdateTimestamp': self.safe_integer(position, 'updateTime'),
2532
2613
  'maintenanceMargin': None,
2533
2614
  'maintenanceMarginPercentage': None,
@@ -6088,7 +6169,7 @@ class bingx(Exchange, ImplicitAPI):
6088
6169
  body = self.json(parsedParams)
6089
6170
  else:
6090
6171
  query = self.urlencode(parsedParams)
6091
- url += '?' + query + '&signature=' + signature
6172
+ url += '?' + query + '&' + 'signature=' + signature
6092
6173
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
6093
6174
 
6094
6175
  def nonce(self):