ccxt 4.4.49__py2.py3-none-any.whl → 4.4.51__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 (71) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +1 -0
  3. ccxt/abstract/binancecoinm.py +1 -0
  4. ccxt/abstract/binanceus.py +1 -0
  5. ccxt/abstract/binanceusdm.py +1 -0
  6. ccxt/alpaca.py +63 -2
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/alpaca.py +63 -2
  9. ccxt/async_support/base/exchange.py +1 -1
  10. ccxt/async_support/binance.py +39 -20
  11. ccxt/async_support/blofin.py +5 -1
  12. ccxt/async_support/coinex.py +4 -4
  13. ccxt/async_support/coinmetro.py +16 -3
  14. ccxt/async_support/deribit.py +11 -3
  15. ccxt/async_support/gate.py +1 -1
  16. ccxt/async_support/hollaex.py +14 -17
  17. ccxt/async_support/htx.py +5 -3
  18. ccxt/async_support/kucoin.py +49 -69
  19. ccxt/async_support/mexc.py +24 -8
  20. ccxt/async_support/okcoin.py +13 -5
  21. ccxt/async_support/onetrading.py +1 -1
  22. ccxt/async_support/paradex.py +1 -1
  23. ccxt/async_support/paymium.py +42 -0
  24. ccxt/async_support/probit.py +77 -8
  25. ccxt/async_support/timex.py +67 -0
  26. ccxt/async_support/tokocrypto.py +81 -4
  27. ccxt/async_support/tradeogre.py +58 -1
  28. ccxt/async_support/vertex.py +65 -2
  29. ccxt/async_support/wavesexchange.py +73 -0
  30. ccxt/async_support/wazirx.py +59 -3
  31. ccxt/async_support/whitebit.py +79 -4
  32. ccxt/async_support/xt.py +112 -0
  33. ccxt/async_support/yobit.py +56 -0
  34. ccxt/async_support/zaif.py +55 -0
  35. ccxt/async_support/zonda.py +58 -0
  36. ccxt/base/exchange.py +72 -4
  37. ccxt/binance.py +39 -20
  38. ccxt/blofin.py +5 -1
  39. ccxt/coinex.py +4 -4
  40. ccxt/coinmetro.py +16 -3
  41. ccxt/deribit.py +11 -3
  42. ccxt/gate.py +1 -1
  43. ccxt/hollaex.py +14 -17
  44. ccxt/htx.py +5 -3
  45. ccxt/kucoin.py +49 -69
  46. ccxt/mexc.py +24 -8
  47. ccxt/okcoin.py +13 -5
  48. ccxt/onetrading.py +1 -1
  49. ccxt/paradex.py +1 -1
  50. ccxt/paymium.py +42 -0
  51. ccxt/pro/__init__.py +1 -1
  52. ccxt/pro/binance.py +2 -0
  53. ccxt/pro/blofin.py +8 -0
  54. ccxt/pro/coinex.py +4 -1
  55. ccxt/probit.py +77 -8
  56. ccxt/timex.py +67 -0
  57. ccxt/tokocrypto.py +81 -4
  58. ccxt/tradeogre.py +58 -1
  59. ccxt/vertex.py +65 -2
  60. ccxt/wavesexchange.py +73 -0
  61. ccxt/wazirx.py +59 -3
  62. ccxt/whitebit.py +79 -4
  63. ccxt/xt.py +112 -0
  64. ccxt/yobit.py +56 -0
  65. ccxt/zaif.py +55 -0
  66. ccxt/zonda.py +58 -0
  67. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/METADATA +18 -18
  68. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/RECORD +71 -71
  69. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/WHEEL +1 -1
  70. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/LICENSE.txt +0 -0
  71. {ccxt-4.4.49.dist-info → ccxt-4.4.51.dist-info}/top_level.txt +0 -0
ccxt/async_support/xt.py CHANGED
@@ -688,6 +688,118 @@ class xt(Exchange, ImplicitAPI):
688
688
  'createMarketBuyOrderRequiresPrice': True,
689
689
  'recvWindow': '5000', # in milliseconds, spot only
690
690
  },
691
+ 'features': {
692
+ 'default': {
693
+ 'sandbox': False,
694
+ 'createOrder': {
695
+ 'marginMode': False,
696
+ 'triggerPrice': False,
697
+ 'triggerDirection': False,
698
+ 'triggerPriceType': None,
699
+ 'stopLossPrice': False,
700
+ 'takeProfitPrice': False,
701
+ 'attachedStopLossTakeProfit': None,
702
+ 'timeInForce': {
703
+ 'IOC': True,
704
+ 'FOK': True,
705
+ 'PO': True,
706
+ 'GTD': False,
707
+ },
708
+ 'hedged': False,
709
+ 'trailing': False,
710
+ 'leverage': False,
711
+ 'marketBuyByCost': True,
712
+ 'marketBuyRequiresPrice': False,
713
+ 'selfTradePrevention': False,
714
+ 'iceberg': False,
715
+ },
716
+ 'createOrders': None,
717
+ 'fetchMyTrades': {
718
+ 'marginMode': True,
719
+ 'limit': 100,
720
+ 'daysBack': 100000, # todo
721
+ 'untilDays': 100000, # todo
722
+ 'marketType': True,
723
+ 'subType': True,
724
+ },
725
+ 'fetchOrder': {
726
+ 'marginMode': False,
727
+ 'trigger': True, # todo TPSL kind
728
+ 'trailing': False,
729
+ 'marketType': True,
730
+ 'subType': True,
731
+ },
732
+ 'fetchOpenOrders': {
733
+ 'marginMode': True,
734
+ 'limit': 100,
735
+ 'trigger': True, # todo TPSL
736
+ 'trailing': False,
737
+ 'marketType': True,
738
+ 'subType': True,
739
+ },
740
+ 'fetchOrders': {
741
+ 'marginMode': True,
742
+ 'limit': 100,
743
+ 'daysBack': 100000, # todo
744
+ 'untilDays': 100000, # todo
745
+ 'trigger': True, # todo TPSL
746
+ 'trailing': False,
747
+ 'marketType': True,
748
+ 'subType': True,
749
+ },
750
+ 'fetchClosedOrders': {
751
+ 'marginMode': True,
752
+ 'limit': 100,
753
+ 'daysBack': 100000, # todo
754
+ 'daysBackCanceled': 1, # todo
755
+ 'untilDays': 100000, # todo
756
+ 'trigger': True, # todo TPSL
757
+ 'trailing': False,
758
+ 'marketType': True,
759
+ 'subType': True,
760
+ },
761
+ 'fetchOHLCV': {
762
+ 'limit': 1000, # todo for derivatives
763
+ },
764
+ },
765
+ 'spot': {
766
+ 'extends': 'default',
767
+ },
768
+ 'forDerivatives': {
769
+ 'extends': 'default',
770
+ 'createOrder': {
771
+ 'triggerPrice': True,
772
+ # todo
773
+ 'triggerPriceType': {
774
+ 'last': True,
775
+ 'mark': True,
776
+ 'index': True,
777
+ },
778
+ 'stopLossPrice': True,
779
+ 'takeProfitPrice': True,
780
+ },
781
+ 'fetchMyTrades': {
782
+ 'daysBack': None,
783
+ 'untilDays': None,
784
+ },
785
+ },
786
+ 'swap': {
787
+ 'linear': {
788
+ 'extends': 'forDerivatives',
789
+ },
790
+ 'inverse': {
791
+ 'extends': 'forDerivatives',
792
+ },
793
+ },
794
+ 'future': {
795
+ 'linear': {
796
+ 'extends': 'forDerivatives',
797
+ },
798
+ 'inverse': {
799
+ 'extends': 'forDerivatives',
800
+ },
801
+ },
802
+ },
691
803
  })
692
804
 
693
805
  def nonce(self):
@@ -320,6 +320,62 @@ class yobit(Exchange, ImplicitAPI):
320
320
  'Rate Limited': RateLimitExceeded,
321
321
  },
322
322
  },
323
+ 'features': {
324
+ 'spot': {
325
+ 'sandbox': False,
326
+ 'createOrder': {
327
+ 'marginMode': False,
328
+ 'triggerPrice': False,
329
+ 'triggerDirection': False,
330
+ 'triggerPriceType': None,
331
+ 'stopLossPrice': False,
332
+ 'takeProfitPrice': False,
333
+ 'attachedStopLossTakeProfit': None,
334
+ 'timeInForce': {
335
+ 'IOC': False,
336
+ 'FOK': False,
337
+ 'PO': False,
338
+ 'GTD': False,
339
+ },
340
+ 'hedged': False,
341
+ 'trailing': False,
342
+ 'leverage': False,
343
+ 'marketBuyByCost': False,
344
+ 'marketBuyRequiresPrice': False,
345
+ 'selfTradePrevention': False,
346
+ 'iceberg': False,
347
+ },
348
+ 'createOrders': None,
349
+ 'fetchMyTrades': {
350
+ 'marginMode': False,
351
+ 'limit': 1000,
352
+ 'daysBack': 100000, # todo
353
+ 'untilDays': 100000, # todo
354
+ },
355
+ 'fetchOrder': {
356
+ 'marginMode': False,
357
+ 'trigger': False,
358
+ 'trailing': False,
359
+ },
360
+ 'fetchOpenOrders': {
361
+ 'marginMode': False,
362
+ 'limit': None,
363
+ 'trigger': False,
364
+ 'trailing': False,
365
+ },
366
+ 'fetchOrders': None,
367
+ 'fetchClosedOrders': None,
368
+ 'fetchOHLCV': None,
369
+ },
370
+ 'swap': {
371
+ 'linear': None,
372
+ 'inverse': None,
373
+ },
374
+ 'future': {
375
+ 'linear': None,
376
+ 'inverse': None,
377
+ },
378
+ },
323
379
  'orders': {}, # orders cache / emulation
324
380
  })
325
381
 
@@ -133,6 +133,61 @@ class zaif(Exchange, ImplicitAPI):
133
133
  },
134
134
  'options': {
135
135
  },
136
+ 'features': {
137
+ 'spot': {
138
+ 'sandbox': False,
139
+ 'createOrder': {
140
+ 'marginMode': True, # todo
141
+ 'triggerPrice': True, # todo implement
142
+ 'triggerDirection': False,
143
+ 'triggerPriceType': None,
144
+ 'stopLossPrice': False, # todo
145
+ 'takeProfitPrice': False, # todo
146
+ 'attachedStopLossTakeProfit': None,
147
+ 'timeInForce': {
148
+ 'IOC': False,
149
+ 'FOK': False,
150
+ 'PO': False,
151
+ 'GTD': False,
152
+ },
153
+ 'hedged': False,
154
+ 'trailing': False,
155
+ 'leverage': True, # todo implement
156
+ 'marketBuyByCost': False,
157
+ 'marketBuyRequiresPrice': False,
158
+ 'selfTradePrevention': False,
159
+ 'iceberg': False,
160
+ },
161
+ 'createOrders': None,
162
+ 'fetchMyTrades': None, # todo
163
+ 'fetchOrder': None,
164
+ 'fetchOpenOrders': {
165
+ 'marginMode': True, # todo
166
+ 'limit': None,
167
+ 'trigger': False,
168
+ 'trailing': False,
169
+ },
170
+ 'fetchOrders': None, # todo
171
+ 'fetchClosedOrders': {
172
+ 'marginMode': True, # todo
173
+ 'limit': 1000,
174
+ 'daysBack': 100000, # todo
175
+ 'daysBackCanceled': 1, # todo
176
+ 'untilDays': 100000, # todo
177
+ 'trigger': False,
178
+ 'trailing': False,
179
+ },
180
+ 'fetchOHLCV': None,
181
+ },
182
+ 'swap': {
183
+ 'linear': None,
184
+ 'inverse': None,
185
+ },
186
+ 'future': {
187
+ 'linear': None,
188
+ 'inverse': None,
189
+ },
190
+ },
136
191
  'precisionMode': TICK_SIZE,
137
192
  'exceptions': {
138
193
  'exact': {
@@ -303,6 +303,60 @@ class zonda(Exchange, ImplicitAPI):
303
303
  'fillResponseFromRequest': True,
304
304
  },
305
305
  },
306
+ 'features': {
307
+ 'spot': {
308
+ 'sandbox': False,
309
+ 'createOrder': {
310
+ 'marginMode': False,
311
+ 'triggerPrice': True, # todo remove
312
+ 'triggerDirection': False,
313
+ 'triggerPriceType': None,
314
+ 'stopLossPrice': False, # todo
315
+ 'takeProfitPrice': False, # todo
316
+ 'attachedStopLossTakeProfit': None,
317
+ 'timeInForce': {
318
+ 'IOC': True,
319
+ 'FOK': True,
320
+ 'PO': True,
321
+ 'GTD': False,
322
+ },
323
+ 'hedged': False,
324
+ 'trailing': False,
325
+ 'leverage': False,
326
+ 'marketBuyByCost': True,
327
+ 'marketBuyRequiresPrice': False,
328
+ 'selfTradePrevention': False,
329
+ 'iceberg': False,
330
+ },
331
+ 'createOrders': None,
332
+ 'fetchMyTrades': {
333
+ 'marginMode': False,
334
+ 'limit': None,
335
+ 'daysBack': 100000, # todo
336
+ 'untilDays': 100000, # todo
337
+ },
338
+ 'fetchOrder': None,
339
+ 'fetchOpenOrders': {
340
+ 'marginMode': False,
341
+ 'limit': 100,
342
+ 'trigger': False,
343
+ 'trailing': False,
344
+ },
345
+ 'fetchOrders': None,
346
+ 'fetchClosedOrders': None, # todo
347
+ 'fetchOHLCV': {
348
+ 'limit': None,
349
+ },
350
+ },
351
+ 'swap': {
352
+ 'linear': None,
353
+ 'inverse': None,
354
+ },
355
+ 'future': {
356
+ 'linear': None,
357
+ 'inverse': None,
358
+ },
359
+ },
306
360
  'precisionMode': TICK_SIZE,
307
361
  'exceptions': {
308
362
  '400': ExchangeError, # At least one parameter wasn't set
@@ -455,6 +509,7 @@ class zonda(Exchange, ImplicitAPI):
455
509
  """
456
510
  await self.load_markets()
457
511
  request: dict = {}
512
+ # todo pair
458
513
  response = await self.v1_01PrivateGetTradingOffer(self.extend(request, params))
459
514
  items = self.safe_list(response, 'items', [])
460
515
  return self.parse_orders(items, None, since, limit, {'status': 'open'})
@@ -1364,6 +1419,9 @@ class zonda(Exchange, ImplicitAPI):
1364
1419
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1365
1420
  """
1366
1421
  create a trade order
1422
+
1423
+ https://docs.zondacrypto.exchange/reference/new-order
1424
+
1367
1425
  :param str symbol: unified symbol of the market to create an order in
1368
1426
  :param str type: 'market' or 'limit'
1369
1427
  :param str side: 'buy' or 'sell'
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.49'
7
+ __version__ = '4.4.51'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2724,6 +2724,11 @@ class Exchange(object):
2724
2724
  res = self.parse_to_numeric((value % 1))
2725
2725
  return res == 0
2726
2726
 
2727
+ def safe_number_omit_zero(self, obj: object, key: IndexType, defaultValue: Num = None):
2728
+ value = self.safe_string(obj, key)
2729
+ final = self.parse_number(self.omit_zero(value))
2730
+ return defaultValue if (final is None) else final
2731
+
2727
2732
  def safe_integer_omit_zero(self, obj: object, key: IndexType, defaultValue: Int = None):
2728
2733
  timestamp = self.safe_integer(obj, key, defaultValue)
2729
2734
  if timestamp is None or timestamp == 0:
@@ -2808,12 +2813,14 @@ class Exchange(object):
2808
2813
  if value is not None:
2809
2814
  featuresObj['createOrder']['stopLoss'] = value
2810
2815
  featuresObj['createOrder']['takeProfit'] = value
2811
- # for spot, default 'hedged' to False
2812
2816
  if marketType == 'spot':
2817
+ # default 'hedged': False
2813
2818
  featuresObj['createOrder']['hedged'] = False
2819
+ # default 'leverage': False
2820
+ if not ('leverage' in featuresObj['createOrder']):
2821
+ featuresObj['createOrder']['leverage'] = False
2814
2822
  # default 'GTC' to True
2815
- gtcValue = self.safe_bool(featuresObj['createOrder']['timeInForce'], 'gtc')
2816
- if gtcValue is None:
2823
+ if self.safe_bool(featuresObj['createOrder']['timeInForce'], 'GTC') is None:
2817
2824
  featuresObj['createOrder']['timeInForce']['GTC'] = True
2818
2825
  return featuresObj
2819
2826
 
@@ -2876,6 +2883,67 @@ class Exchange(object):
2876
2883
  }
2877
2884
 
2878
2885
  def safe_currency_structure(self, currency: object):
2886
+ # derive data from networks: deposit, withdraw, active, fee, limits, precision
2887
+ networks = self.safe_dict(currency, 'networks', {})
2888
+ keys = list(networks.keys())
2889
+ length = len(keys)
2890
+ if length != 0:
2891
+ for i in range(0, length):
2892
+ network = networks[keys[i]]
2893
+ deposit = self.safe_bool(network, 'deposit')
2894
+ if currency['deposit'] is None or deposit:
2895
+ currency['deposit'] = deposit
2896
+ withdraw = self.safe_bool(network, 'withdraw')
2897
+ if currency['withdraw'] is None or withdraw:
2898
+ currency['withdraw'] = withdraw
2899
+ active = self.safe_bool(network, 'active')
2900
+ if currency['active'] is None or active:
2901
+ currency['active'] = active
2902
+ # find lowest fee(which is more desired)
2903
+ fee = self.safe_string(network, 'fee')
2904
+ feeMain = self.safe_string(currency, 'fee')
2905
+ if feeMain is None or Precise.string_lt(fee, feeMain):
2906
+ currency['fee'] = self.parse_number(fee)
2907
+ # find lowest precision(which is more desired)
2908
+ precision = self.safe_string(network, 'precision')
2909
+ precisionMain = self.safe_string(currency, 'precision')
2910
+ if precisionMain is None or Precise.string_lt(precision, precisionMain):
2911
+ currency['precision'] = self.parse_number(precision)
2912
+ # limits
2913
+ limits = self.safe_dict(network, 'limits')
2914
+ limitsMain = self.safe_dict(currency, 'limits')
2915
+ if limitsMain is None:
2916
+ currency['limits'] = {}
2917
+ # deposits
2918
+ limitsDeposit = self.safe_dict(limits, 'deposit')
2919
+ limitsDepositMain = self.safe_dict(limitsMain, 'deposit')
2920
+ if limitsDepositMain is None:
2921
+ currency['limits']['deposit'] = {}
2922
+ limitsDepositMin = self.safe_string(limitsDeposit, 'min')
2923
+ limitsDepositMax = self.safe_string(limitsDeposit, 'max')
2924
+ limitsDepositMinMain = self.safe_string(limitsDepositMain, 'min')
2925
+ limitsDepositMaxMain = self.safe_string(limitsDepositMain, 'max')
2926
+ # find min
2927
+ if limitsDepositMinMain is None or Precise.string_lt(limitsDepositMin, limitsDepositMinMain):
2928
+ currency['limits']['deposit']['min'] = self.parse_number(limitsDepositMin)
2929
+ # find max
2930
+ if limitsDepositMaxMain is None or Precise.string_gt(limitsDepositMax, limitsDepositMaxMain):
2931
+ currency['limits']['deposit']['max'] = self.parse_number(limitsDepositMax)
2932
+ # withdrawals
2933
+ limitsWithdraw = self.safe_dict(limits, 'withdraw')
2934
+ limitsWithdrawMain = self.safe_dict(limitsMain, 'withdraw')
2935
+ if limitsWithdrawMain is None:
2936
+ currency['limits']['withdraw'] = {}
2937
+ limitsWithdrawMin = self.safe_string(limitsWithdraw, 'min')
2938
+ limitsWithdrawMax = self.safe_string(limitsWithdraw, 'max')
2939
+ limitsWithdrawMinMain = self.safe_string(limitsWithdrawMain, 'min')
2940
+ limitsWithdrawMaxMain = self.safe_string(limitsWithdrawMain, 'max')
2941
+ # find min
2942
+ if limitsWithdrawMinMain is None or Precise.string_lt(limitsWithdrawMin, limitsWithdrawMinMain):
2943
+ currency['limits']['withdraw']['min'] = self.parse_number(limitsWithdrawMin)
2944
+ # find max
2945
+ if limitsWithdrawMaxMain is None or Precise.string_gt(limitsWithdrawMax, limitsWithdrawMaxMain):
2946
+ currency['limits']['withdraw']['max'] = self.parse_number(limitsWithdrawMax)
2879
2947
  return self.extend({
2880
2948
  'info': None,
2881
2949
  'id': None,
ccxt/binance.py CHANGED
@@ -502,6 +502,7 @@ class binance(Exchange, ImplicitAPI):
502
502
  'portfolio/repay-futures-switch': 3, # Weight(IP): 30 => cost = 0.1 * 30 = 3
503
503
  'portfolio/margin-asset-leverage': 5, # Weight(IP): 50 => cost = 0.1 * 50 = 5
504
504
  'portfolio/balance': 2,
505
+ 'portfolio/negative-balance-exchange-record': 2,
505
506
  # staking
506
507
  'staking/productList': 0.1,
507
508
  'staking/position': 0.1,
@@ -1598,7 +1599,7 @@ class binance(Exchange, ImplicitAPI):
1598
1599
  'triggerDirection': False,
1599
1600
  'stopLossPrice': True,
1600
1601
  'takeProfitPrice': True,
1601
- 'attachedStopLossTakeProfit': None, # not supported
1602
+ 'attachedStopLossTakeProfit': None,
1602
1603
  'timeInForce': {
1603
1604
  'IOC': True,
1604
1605
  'FOK': True,
@@ -1607,12 +1608,16 @@ class binance(Exchange, ImplicitAPI):
1607
1608
  },
1608
1609
  'hedged': True,
1609
1610
  'leverage': False,
1610
- 'marketBuyRequiresPrice': False,
1611
1611
  'marketBuyByCost': True,
1612
- # exchange-supported features
1613
- 'selfTradePrevention': True, # todo
1614
- 'trailing': True,
1615
- 'iceberg': True, # todo implementation
1612
+ 'marketBuyRequiresPrice': False,
1613
+ 'selfTradePrevention': {
1614
+ 'expire_maker': True,
1615
+ 'expire_taker': True,
1616
+ 'expire_both': True,
1617
+ 'none': True,
1618
+ },
1619
+ 'trailing': False, # todo: self is different from standard trailing https://github.com/binance/binance-spot-api-docs/blob/master/faqs/trailing-stop-faq.md
1620
+ 'icebergAmount': True,
1616
1621
  },
1617
1622
  'createOrders': None,
1618
1623
  'fetchMyTrades': {
@@ -1653,7 +1658,7 @@ class binance(Exchange, ImplicitAPI):
1653
1658
  'limit': 1000,
1654
1659
  },
1655
1660
  },
1656
- 'default': {
1661
+ 'forDerivatives': {
1657
1662
  'sandbox': True,
1658
1663
  'createOrder': {
1659
1664
  'marginMode': False,
@@ -1725,18 +1730,18 @@ class binance(Exchange, ImplicitAPI):
1725
1730
  },
1726
1731
  'swap': {
1727
1732
  'linear': {
1728
- 'extends': 'default',
1733
+ 'extends': 'forDerivatives',
1729
1734
  },
1730
1735
  'inverse': {
1731
- 'extends': 'default',
1736
+ 'extends': 'forDerivatives',
1732
1737
  },
1733
1738
  },
1734
1739
  'future': {
1735
1740
  'linear': {
1736
- 'extends': 'default',
1741
+ 'extends': 'forDerivatives',
1737
1742
  },
1738
1743
  'inverse': {
1739
- 'extends': 'default',
1744
+ 'extends': 'forDerivatives',
1740
1745
  },
1741
1746
  },
1742
1747
  },
@@ -4400,12 +4405,11 @@ class binance(Exchange, ImplicitAPI):
4400
4405
  type = 'spot' if (timestamp is None) else 'swap'
4401
4406
  marketId = self.safe_string(entry, 'symbol')
4402
4407
  market = self.safe_market(marketId, market, None, type)
4403
- price = self.safe_number(entry, 'price')
4404
4408
  return {
4405
4409
  'symbol': market['symbol'],
4406
4410
  'timestamp': timestamp,
4407
4411
  'datetime': self.iso8601(timestamp),
4408
- 'price': price,
4412
+ 'price': self.safe_number_omit_zero(entry, 'price'),
4409
4413
  'side': None,
4410
4414
  'info': entry,
4411
4415
  }
@@ -5000,11 +5004,13 @@ class binance(Exchange, ImplicitAPI):
5000
5004
  until = self.safe_integer(params, 'until')
5001
5005
  if until is not None:
5002
5006
  request['endTime'] = until
5003
- if limit is not None:
5004
- isFutureOrSwap = (market['swap'] or market['future'])
5005
- request['limit'] = min(limit, 1000) if isFutureOrSwap else limit # default = 500, maximum = 1000
5006
5007
  method = self.safe_string(self.options, 'fetchTradesMethod')
5007
5008
  method = self.safe_string_2(params, 'fetchTradesMethod', 'method', method)
5009
+ if limit is not None:
5010
+ isFutureOrSwap = (market['swap'] or market['future'])
5011
+ isHistoricalEndpoint = (method is not None) and (method.find('GetHistoricalTrades') >= 0)
5012
+ maxLimitForContractHistorical = 500 if isHistoricalEndpoint else 1000
5013
+ request['limit'] = min(limit, maxLimitForContractHistorical) if isFutureOrSwap else limit # default = 500, maximum = 1000
5008
5014
  params = self.omit(params, ['until', 'fetchTradesMethod'])
5009
5015
  response = None
5010
5016
  if market['option'] or method == 'eapiPublicGetTrades':
@@ -6018,7 +6024,7 @@ class binance(Exchange, ImplicitAPI):
6018
6024
  """
6019
6025
  create a trade order
6020
6026
 
6021
- https://developers.binance.com/docs/binance-spot-api-docs/rest-api/public-api-endpoints#new-order-trade
6027
+ https://developers.binance.com/docs/binance-spot-api-docs/rest-api/trading-endpoints#new-order-trade
6022
6028
  https://developers.binance.com/docs/binance-spot-api-docs/rest-api/public-api-endpoints#test-new-order-trade
6023
6029
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/New-Order
6024
6030
  https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/New-Order
@@ -6047,6 +6053,8 @@ class binance(Exchange, ImplicitAPI):
6047
6053
  :param float [params.stopLossPrice]: the price that a stop loss order is triggered at
6048
6054
  :param float [params.takeProfitPrice]: the price that a take profit order is triggered at
6049
6055
  :param boolean [params.portfolioMargin]: set to True if you would like to create an order in a portfolio margin account
6056
+ :param str [params.selfTradePrevention]: set unified value for stp(see .features for available values)
6057
+ :param float [params.icebergAmount]: set iceberg amount for limit orders
6050
6058
  :param str [params.stopLossOrTakeProfit]: 'stopLoss' or 'takeProfit', required for spot trailing orders
6051
6059
  :param str [params.positionSide]: *swap and portfolio margin only* "BOTH" for one-way mode, "LONG" for buy side of hedged mode, "SHORT" for sell side of hedged mode
6052
6060
  :param bool [params.hedged]: *swap and portfolio margin only* True for hedged mode, False for one way mode, default is False
@@ -6340,7 +6348,7 @@ class binance(Exchange, ImplicitAPI):
6340
6348
  if stopPrice is not None:
6341
6349
  request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
6342
6350
  if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None) and (self.safe_string(request, 'timeInForce') is None):
6343
- request['timeInForce'] = self.options['defaultTimeInForce'] # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
6351
+ request['timeInForce'] = self.safe_string(self.options, 'defaultTimeInForce') # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
6344
6352
  if not isPortfolioMargin and market['contract'] and postOnly:
6345
6353
  request['timeInForce'] = 'GTX'
6346
6354
  # remove timeInForce from params because PO is only used by self.is_post_only and it's not a valid value for Binance
@@ -6352,7 +6360,17 @@ class binance(Exchange, ImplicitAPI):
6352
6360
  params = self.omit(params, 'reduceOnly')
6353
6361
  side = 'sell' if (side == 'buy') else 'buy'
6354
6362
  request['positionSide'] = 'LONG' if (side == 'buy') else 'SHORT'
6355
- requestParams = self.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent', 'quoteOrderQty', 'cost', 'test', 'hedged'])
6363
+ # unified stp
6364
+ selfTradePrevention = self.safe_string(params, 'selfTradePrevention')
6365
+ if selfTradePrevention is not None:
6366
+ if market['spot']:
6367
+ request['selfTradePreventionMode'] = selfTradePrevention.upper() # binance enums exactly match the unified ccxt enums(but needs uppercase)
6368
+ # unified iceberg
6369
+ icebergAmount = self.safe_number(params, 'icebergAmount')
6370
+ if icebergAmount is not None:
6371
+ if market['spot']:
6372
+ request['icebergQty'] = self.amount_to_precision(symbol, icebergAmount)
6373
+ requestParams = self.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent', 'quoteOrderQty', 'cost', 'test', 'hedged', 'selfTradePrevention', 'icebergAmount'])
6356
6374
  return self.extend(request, requestParams)
6357
6375
 
6358
6376
  def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
@@ -6836,6 +6854,7 @@ class binance(Exchange, ImplicitAPI):
6836
6854
  :param str symbol: unified market symbol
6837
6855
  :param dict [params]: extra parameters specific to the exchange API endpoint
6838
6856
  :param str [params.trigger]: set to True if you would like to fetch portfolio margin account stop or conditional orders
6857
+ :param boolean [params.portfolioMargin]: set to True if you would like to fetch for a portfolio margin account
6839
6858
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
6840
6859
  """
6841
6860
  if symbol is None:
@@ -10158,7 +10177,7 @@ class binance(Exchange, ImplicitAPI):
10158
10177
  # }
10159
10178
  #
10160
10179
  marketId = self.safe_string(position, 'symbol')
10161
- market = self.safe_market(marketId, market)
10180
+ market = self.safe_market(marketId, market, None, 'swap')
10162
10181
  symbol = market['symbol']
10163
10182
  side = self.safe_string_lower(position, 'side')
10164
10183
  quantity = self.safe_string(position, 'quantity')
ccxt/blofin.py CHANGED
@@ -166,6 +166,9 @@ class blofin(Exchange, ImplicitAPI):
166
166
  'api': {
167
167
  'rest': 'https://openapi.blofin.com',
168
168
  },
169
+ 'test': {
170
+ 'rest': 'https://demo-trading-openapi.blofin.com',
171
+ },
169
172
  'referral': {
170
173
  'url': 'https://blofin.com/register?referral_code=f79EsS',
171
174
  'discount': 0.05,
@@ -295,7 +298,7 @@ class blofin(Exchange, ImplicitAPI):
295
298
  'trailing': False,
296
299
  },
297
300
  'fetchOHLCV': {
298
- 'max': 1440,
301
+ 'limit': 1440,
299
302
  },
300
303
  },
301
304
  'spot': {
@@ -323,6 +326,7 @@ class blofin(Exchange, ImplicitAPI):
323
326
  'attachedStopLossTakeProfit': {
324
327
  'triggerPriceType': None,
325
328
  'limit': True,
329
+ 'price': None,
326
330
  },
327
331
  'hedged': True,
328
332
  },
ccxt/coinex.py CHANGED
@@ -480,7 +480,7 @@ class coinex(Exchange, ImplicitAPI):
480
480
  'ERC20': 'ERC20',
481
481
  'BRC20': 'BRC20',
482
482
  'SOL': 'SOL',
483
- 'TON': 'SOL',
483
+ 'TON': 'TON',
484
484
  'BSV': 'BSV',
485
485
  'AVAXC': 'AVA_C',
486
486
  'AVAXX': 'AVA',
@@ -3766,7 +3766,7 @@ class coinex(Exchange, ImplicitAPI):
3766
3766
  'currency': self.safe_currency_code(None, currency),
3767
3767
  'network': None,
3768
3768
  'address': address,
3769
- 'tag': tag,
3769
+ 'tag': self.safe_string(depositAddress, 'memo', tag),
3770
3770
  }
3771
3771
 
3772
3772
  def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -4608,13 +4608,13 @@ class coinex(Exchange, ImplicitAPI):
4608
4608
  self.check_address(address)
4609
4609
  self.load_markets()
4610
4610
  currency = self.currency(code)
4611
- if tag:
4612
- address = address + ':' + tag
4613
4611
  request: dict = {
4614
4612
  'ccy': currency['id'],
4615
4613
  'to_address': address, # must be authorized, inter-user transfer by a registered mobile phone number or an email address is supported
4616
4614
  'amount': self.number_to_string(amount), # the actual amount without fees, https://www.coinex.com/fees
4617
4615
  }
4616
+ if tag is not None:
4617
+ request['memo'] = tag
4618
4618
  networkCode = None
4619
4619
  networkCode, params = self.handle_network_code_and_params(params)
4620
4620
  if networkCode is not None: