ccxt 4.4.50__py2.py3-none-any.whl → 4.4.52__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 (59) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/alpaca.py +1 -1
  3. ccxt/async_support/__init__.py +1 -1
  4. ccxt/async_support/alpaca.py +1 -1
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +31 -16
  7. ccxt/async_support/blofin.py +4 -0
  8. ccxt/async_support/coinex.py +1 -1
  9. ccxt/async_support/coinmetro.py +16 -3
  10. ccxt/async_support/deribit.py +18 -3
  11. ccxt/async_support/gate.py +1 -1
  12. ccxt/async_support/hollaex.py +2 -1
  13. ccxt/async_support/htx.py +5 -3
  14. ccxt/async_support/kucoin.py +2 -2
  15. ccxt/async_support/mexc.py +21 -6
  16. ccxt/async_support/onetrading.py +1 -1
  17. ccxt/async_support/paradex.py +1 -1
  18. ccxt/async_support/probit.py +9 -7
  19. ccxt/async_support/vertex.py +65 -2
  20. ccxt/async_support/wavesexchange.py +73 -0
  21. ccxt/async_support/wazirx.py +59 -3
  22. ccxt/async_support/whitebit.py +69 -0
  23. ccxt/async_support/xt.py +112 -0
  24. ccxt/async_support/yobit.py +56 -0
  25. ccxt/async_support/zaif.py +55 -0
  26. ccxt/async_support/zonda.py +58 -0
  27. ccxt/base/exchange.py +32 -4
  28. ccxt/binance.py +31 -16
  29. ccxt/blofin.py +4 -0
  30. ccxt/coinex.py +1 -1
  31. ccxt/coinmetro.py +16 -3
  32. ccxt/deribit.py +18 -3
  33. ccxt/gate.py +1 -1
  34. ccxt/hollaex.py +2 -1
  35. ccxt/htx.py +5 -3
  36. ccxt/kucoin.py +2 -2
  37. ccxt/mexc.py +21 -6
  38. ccxt/onetrading.py +1 -1
  39. ccxt/paradex.py +1 -1
  40. ccxt/pro/__init__.py +1 -1
  41. ccxt/pro/binance.py +2 -0
  42. ccxt/pro/blofin.py +8 -0
  43. ccxt/pro/coinex.py +4 -1
  44. ccxt/probit.py +9 -7
  45. ccxt/test/tests_async.py +0 -1
  46. ccxt/test/tests_sync.py +0 -1
  47. ccxt/vertex.py +65 -2
  48. ccxt/wavesexchange.py +73 -0
  49. ccxt/wazirx.py +59 -3
  50. ccxt/whitebit.py +69 -0
  51. ccxt/xt.py +112 -0
  52. ccxt/yobit.py +56 -0
  53. ccxt/zaif.py +55 -0
  54. ccxt/zonda.py +58 -0
  55. {ccxt-4.4.50.dist-info → ccxt-4.4.52.dist-info}/METADATA +18 -18
  56. {ccxt-4.4.50.dist-info → ccxt-4.4.52.dist-info}/RECORD +59 -59
  57. {ccxt-4.4.50.dist-info → ccxt-4.4.52.dist-info}/WHEEL +1 -1
  58. {ccxt-4.4.50.dist-info → ccxt-4.4.52.dist-info}/LICENSE.txt +0 -0
  59. {ccxt-4.4.50.dist-info → ccxt-4.4.52.dist-info}/top_level.txt +0 -0
@@ -217,6 +217,62 @@ class wazirx(Exchange, ImplicitAPI):
217
217
  # You can get network from fetchCurrencies
218
218
  },
219
219
  },
220
+ 'features': {
221
+ 'spot': {
222
+ 'sandbox': False,
223
+ 'createOrder': {
224
+ 'marginMode': False,
225
+ 'triggerPrice': True,
226
+ 'triggerDirection': False,
227
+ 'triggerPriceType': None,
228
+ 'stopLossPrice': False, # todo
229
+ 'takeProfitPrice': False, # todo
230
+ 'attachedStopLossTakeProfit': None,
231
+ 'timeInForce': {
232
+ 'IOC': False,
233
+ 'FOK': False,
234
+ 'PO': False,
235
+ 'GTD': False,
236
+ },
237
+ 'hedged': False,
238
+ 'trailing': False,
239
+ 'leverage': False,
240
+ 'marketBuyByCost': False,
241
+ 'marketBuyRequiresPrice': False,
242
+ 'selfTradePrevention': False,
243
+ 'iceberg': False,
244
+ },
245
+ 'createOrders': None,
246
+ 'fetchMyTrades': None,
247
+ 'fetchOrder': None, # todo
248
+ 'fetchOpenOrders': {
249
+ 'marginMode': False,
250
+ 'limit': None,
251
+ 'trigger': False,
252
+ 'trailing': False,
253
+ },
254
+ 'fetchOrders': {
255
+ 'marginMode': False,
256
+ 'limit': 1000,
257
+ 'daysBack': 100000, # todo
258
+ 'untilDays': 100000, # todo
259
+ 'trigger': False,
260
+ 'trailing': False,
261
+ },
262
+ 'fetchClosedOrders': None,
263
+ 'fetchOHLCV': {
264
+ 'limit': 2000,
265
+ },
266
+ },
267
+ 'swap': {
268
+ 'linear': None,
269
+ 'inverse': None,
270
+ },
271
+ 'future': {
272
+ 'linear': None,
273
+ 'inverse': None,
274
+ },
275
+ },
220
276
  })
221
277
 
222
278
  async def fetch_markets(self, params={}) -> List[Market]:
@@ -878,10 +934,10 @@ class wazirx(Exchange, ImplicitAPI):
878
934
  'type': 'limit',
879
935
  }
880
936
  request['price'] = self.price_to_precision(symbol, price)
881
- stopPrice = self.safe_string(params, 'stopPrice')
882
- if stopPrice is not None:
937
+ triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
938
+ if triggerPrice is not None:
883
939
  request['type'] = 'stop_limit'
884
- request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
940
+ request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
885
941
  response = await self.privatePostOrder(self.extend(request, params))
886
942
  # {
887
943
  # "id": 28,
@@ -291,6 +291,75 @@ class whitebit(Exchange, ImplicitAPI):
291
291
  'defaultType': 'spot',
292
292
  'brokerId': 'ccxt',
293
293
  },
294
+ 'features': {
295
+ 'default': {
296
+ 'sandbox': False,
297
+ 'createOrder': {
298
+ 'marginMode': True,
299
+ 'triggerPrice': True,
300
+ 'triggerDirection': False,
301
+ 'triggerPriceType': None,
302
+ 'stopLossPrice': False, # todo
303
+ 'takeProfitPrice': False, # todo
304
+ 'attachedStopLossTakeProfit': None,
305
+ 'timeInForce': {
306
+ 'IOC': True, # todo
307
+ 'FOK': False,
308
+ 'PO': True, # todo
309
+ 'GTD': False,
310
+ },
311
+ 'hedged': False,
312
+ 'trailing': False,
313
+ 'leverage': False,
314
+ 'marketBuyByCost': True,
315
+ 'marketBuyRequiresPrice': False,
316
+ 'selfTradePrevention': False,
317
+ 'iceberg': False,
318
+ },
319
+ 'createOrders': None,
320
+ 'fetchMyTrades': {
321
+ 'marginMode': False,
322
+ 'limit': 100,
323
+ 'daysBack': None,
324
+ 'untilDays': None,
325
+ },
326
+ 'fetchOrder': None,
327
+ 'fetchOpenOrders': {
328
+ 'marginMode': False,
329
+ 'limit': 100,
330
+ 'trigger': False,
331
+ 'trailing': False,
332
+ },
333
+ 'fetchOrders': None, # todo
334
+ 'fetchClosedOrders': {
335
+ 'marginMode': False,
336
+ 'limit': 100,
337
+ 'daysBack': None,
338
+ 'daysBackCanceled': None,
339
+ 'untilDays': None,
340
+ 'trigger': False,
341
+ 'trailing': False,
342
+ },
343
+ 'fetchOHLCV': {
344
+ 'limit': 1440,
345
+ },
346
+ },
347
+ 'spot': {
348
+ 'extends': 'default',
349
+ },
350
+ 'swap': {
351
+ 'linear': {
352
+ 'extends': 'default',
353
+ },
354
+ 'inverse': {
355
+ 'extends': 'default',
356
+ },
357
+ },
358
+ 'future': {
359
+ 'linear': None,
360
+ 'inverse': None,
361
+ },
362
+ },
294
363
  'precisionMode': TICK_SIZE,
295
364
  'exceptions': {
296
365
  'exact': {
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.50'
7
+ __version__ = '4.4.52'
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
 
@@ -5721,6 +5728,27 @@ class Exchange(object):
5721
5728
  symbol = None if (market is None) else market['symbol']
5722
5729
  return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
5723
5730
 
5731
+ def handle_trigger_direction_and_params(self, params, exchangeSpecificKey: Str = None, allowEmpty: Bool = False):
5732
+ """
5733
+ @ignore
5734
+ :returns [str, dict]: the trigger-direction value and omited params
5735
+ """
5736
+ triggerDirection = self.safe_string(params, 'triggerDirection')
5737
+ exchangeSpecificDefined = (exchangeSpecificKey is not None) and (exchangeSpecificKey in params)
5738
+ if triggerDirection is not None:
5739
+ params = self.omit(params, 'triggerDirection')
5740
+ # raise exception if:
5741
+ # A) if provided value is not unified(support old "up/down" strings too)
5742
+ # B) if exchange specific "trigger direction key"(eg. "stopPriceSide") was not provided
5743
+ if not self.in_array(triggerDirection, ['ascending', 'descending', 'up', 'down', 'above', 'below']) and not exchangeSpecificDefined and not allowEmpty:
5744
+ raise ArgumentsRequired(self.id + ' createOrder() : trigger orders require params["triggerDirection"] to be either "ascending" or "descending"')
5745
+ # if old format was provided, overwrite to new
5746
+ if triggerDirection == 'up' or triggerDirection == 'above':
5747
+ triggerDirection = 'ascending'
5748
+ elif triggerDirection == 'down' or triggerDirection == 'below':
5749
+ triggerDirection = 'descending'
5750
+ return [triggerDirection, params]
5751
+
5724
5752
  def handle_trigger_and_params(self, params):
5725
5753
  isTrigger = self.safe_bool_2(params, 'trigger', 'stop')
5726
5754
  if isTrigger:
ccxt/binance.py CHANGED
@@ -1599,7 +1599,7 @@ class binance(Exchange, ImplicitAPI):
1599
1599
  'triggerDirection': False,
1600
1600
  'stopLossPrice': True,
1601
1601
  'takeProfitPrice': True,
1602
- 'attachedStopLossTakeProfit': None, # not supported
1602
+ 'attachedStopLossTakeProfit': None,
1603
1603
  'timeInForce': {
1604
1604
  'IOC': True,
1605
1605
  'FOK': True,
@@ -1608,12 +1608,16 @@ class binance(Exchange, ImplicitAPI):
1608
1608
  },
1609
1609
  'hedged': True,
1610
1610
  'leverage': False,
1611
- 'marketBuyRequiresPrice': False,
1612
1611
  'marketBuyByCost': True,
1613
- # exchange-supported features
1614
- 'selfTradePrevention': True, # todo
1615
- 'trailing': True,
1616
- '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,
1617
1621
  },
1618
1622
  'createOrders': None,
1619
1623
  'fetchMyTrades': {
@@ -1654,7 +1658,7 @@ class binance(Exchange, ImplicitAPI):
1654
1658
  'limit': 1000,
1655
1659
  },
1656
1660
  },
1657
- 'default': {
1661
+ 'forDerivatives': {
1658
1662
  'sandbox': True,
1659
1663
  'createOrder': {
1660
1664
  'marginMode': False,
@@ -1726,18 +1730,18 @@ class binance(Exchange, ImplicitAPI):
1726
1730
  },
1727
1731
  'swap': {
1728
1732
  'linear': {
1729
- 'extends': 'default',
1733
+ 'extends': 'forDerivatives',
1730
1734
  },
1731
1735
  'inverse': {
1732
- 'extends': 'default',
1736
+ 'extends': 'forDerivatives',
1733
1737
  },
1734
1738
  },
1735
1739
  'future': {
1736
1740
  'linear': {
1737
- 'extends': 'default',
1741
+ 'extends': 'forDerivatives',
1738
1742
  },
1739
1743
  'inverse': {
1740
- 'extends': 'default',
1744
+ 'extends': 'forDerivatives',
1741
1745
  },
1742
1746
  },
1743
1747
  },
@@ -4401,12 +4405,11 @@ class binance(Exchange, ImplicitAPI):
4401
4405
  type = 'spot' if (timestamp is None) else 'swap'
4402
4406
  marketId = self.safe_string(entry, 'symbol')
4403
4407
  market = self.safe_market(marketId, market, None, type)
4404
- price = self.safe_number(entry, 'price')
4405
4408
  return {
4406
4409
  'symbol': market['symbol'],
4407
4410
  'timestamp': timestamp,
4408
4411
  'datetime': self.iso8601(timestamp),
4409
- 'price': price,
4412
+ 'price': self.safe_number_omit_zero(entry, 'price'),
4410
4413
  'side': None,
4411
4414
  'info': entry,
4412
4415
  }
@@ -6021,7 +6024,7 @@ class binance(Exchange, ImplicitAPI):
6021
6024
  """
6022
6025
  create a trade order
6023
6026
 
6024
- 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
6025
6028
  https://developers.binance.com/docs/binance-spot-api-docs/rest-api/public-api-endpoints#test-new-order-trade
6026
6029
  https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/New-Order
6027
6030
  https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/New-Order
@@ -6050,6 +6053,8 @@ class binance(Exchange, ImplicitAPI):
6050
6053
  :param float [params.stopLossPrice]: the price that a stop loss order is triggered at
6051
6054
  :param float [params.takeProfitPrice]: the price that a take profit order is triggered at
6052
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
6053
6058
  :param str [params.stopLossOrTakeProfit]: 'stopLoss' or 'takeProfit', required for spot trailing orders
6054
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
6055
6060
  :param bool [params.hedged]: *swap and portfolio margin only* True for hedged mode, False for one way mode, default is False
@@ -6343,7 +6348,7 @@ class binance(Exchange, ImplicitAPI):
6343
6348
  if stopPrice is not None:
6344
6349
  request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
6345
6350
  if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None) and (self.safe_string(request, 'timeInForce') is None):
6346
- 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
6347
6352
  if not isPortfolioMargin and market['contract'] and postOnly:
6348
6353
  request['timeInForce'] = 'GTX'
6349
6354
  # remove timeInForce from params because PO is only used by self.is_post_only and it's not a valid value for Binance
@@ -6355,7 +6360,17 @@ class binance(Exchange, ImplicitAPI):
6355
6360
  params = self.omit(params, 'reduceOnly')
6356
6361
  side = 'sell' if (side == 'buy') else 'buy'
6357
6362
  request['positionSide'] = 'LONG' if (side == 'buy') else 'SHORT'
6358
- 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'])
6359
6374
  return self.extend(request, requestParams)
6360
6375
 
6361
6376
  def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):