ccxt 4.1.88__py2.py3-none-any.whl → 4.1.90__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.

Files changed (56) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/phemex.py +1 -0
  3. ccxt/async_support/__init__.py +1 -1
  4. ccxt/async_support/base/exchange.py +3 -3
  5. ccxt/async_support/bigone.py +8 -1
  6. ccxt/async_support/binance.py +1 -1
  7. ccxt/async_support/bitforex.py +2 -0
  8. ccxt/async_support/bitget.py +9 -4
  9. ccxt/async_support/bitmex.py +2 -0
  10. ccxt/async_support/blockchaincom.py +0 -37
  11. ccxt/async_support/bybit.py +23 -14
  12. ccxt/async_support/coinex.py +12 -0
  13. ccxt/async_support/coinlist.py +2 -0
  14. ccxt/async_support/coinsph.py +2 -0
  15. ccxt/async_support/cryptocom.py +2 -0
  16. ccxt/async_support/gate.py +258 -11
  17. ccxt/async_support/htx.py +223 -207
  18. ccxt/async_support/kuna.py +2 -0
  19. ccxt/async_support/mexc.py +2 -0
  20. ccxt/async_support/okcoin.py +56 -16
  21. ccxt/async_support/phemex.py +151 -28
  22. ccxt/async_support/poloniex.py +23 -2
  23. ccxt/async_support/tokocrypto.py +25 -12
  24. ccxt/async_support/wazirx.py +2 -0
  25. ccxt/async_support/whitebit.py +2 -0
  26. ccxt/async_support/woo.py +38 -12
  27. ccxt/base/exchange.py +3 -3
  28. ccxt/bigone.py +8 -1
  29. ccxt/binance.py +1 -1
  30. ccxt/bitforex.py +2 -0
  31. ccxt/bitget.py +9 -4
  32. ccxt/bitmex.py +2 -0
  33. ccxt/blockchaincom.py +0 -37
  34. ccxt/bybit.py +23 -14
  35. ccxt/coinex.py +12 -0
  36. ccxt/coinlist.py +2 -0
  37. ccxt/coinsph.py +2 -0
  38. ccxt/cryptocom.py +2 -0
  39. ccxt/gate.py +258 -11
  40. ccxt/htx.py +223 -207
  41. ccxt/kuna.py +2 -0
  42. ccxt/mexc.py +2 -0
  43. ccxt/okcoin.py +56 -16
  44. ccxt/phemex.py +151 -28
  45. ccxt/poloniex.py +23 -2
  46. ccxt/pro/__init__.py +1 -1
  47. ccxt/pro/binance.py +6 -6
  48. ccxt/pro/poloniex.py +15 -11
  49. ccxt/tokocrypto.py +25 -12
  50. ccxt/wazirx.py +2 -0
  51. ccxt/whitebit.py +2 -0
  52. ccxt/woo.py +38 -12
  53. {ccxt-4.1.88.dist-info → ccxt-4.1.90.dist-info}/METADATA +5 -5
  54. {ccxt-4.1.88.dist-info → ccxt-4.1.90.dist-info}/RECORD +56 -56
  55. {ccxt-4.1.88.dist-info → ccxt-4.1.90.dist-info}/WHEEL +0 -0
  56. {ccxt-4.1.88.dist-info → ccxt-4.1.90.dist-info}/top_level.txt +0 -0
ccxt/kuna.py CHANGED
@@ -101,6 +101,8 @@ class kuna(Exchange, ImplicitAPI):
101
101
  'fetchWithdrawal': True,
102
102
  'fetchWithdrawals': True,
103
103
  'reduceMargin': False,
104
+ 'repayCrossMargin': False,
105
+ 'repayIsolatedMargin': False,
104
106
  'setLeverage': False,
105
107
  'setMargin': False,
106
108
  'setMarginMode': False,
ccxt/mexc.py CHANGED
@@ -120,6 +120,8 @@ class mexc(Exchange, ImplicitAPI):
120
120
  'fetchWithdrawal': None,
121
121
  'fetchWithdrawals': True,
122
122
  'reduceMargin': True,
123
+ 'repayCrossMargin': False,
124
+ 'repayIsolatedMargin': False,
123
125
  'setLeverage': True,
124
126
  'setMarginMode': None,
125
127
  'setPositionMode': True,
ccxt/okcoin.py CHANGED
@@ -20,6 +20,7 @@ from ccxt.base.errors import InvalidAddress
20
20
  from ccxt.base.errors import InvalidOrder
21
21
  from ccxt.base.errors import OrderNotFound
22
22
  from ccxt.base.errors import CancelPending
23
+ from ccxt.base.errors import NotSupported
23
24
  from ccxt.base.errors import NetworkError
24
25
  from ccxt.base.errors import RateLimitExceeded
25
26
  from ccxt.base.errors import ExchangeNotAvailable
@@ -51,8 +52,17 @@ class okcoin(Exchange, ImplicitAPI):
51
52
  'future': True,
52
53
  'option': None,
53
54
  'cancelOrder': True,
55
+ 'createMarketBuyOrderWithCost': True,
56
+ 'createMarketOrderWithCost': False,
57
+ 'createMarketSellOrderWithCost': False,
54
58
  'createOrder': True,
55
59
  'fetchBalance': True,
60
+ 'fetchBorrowInterest': False,
61
+ 'fetchBorrowRate': False,
62
+ 'fetchBorrowRateHistories': False,
63
+ 'fetchBorrowRateHistory': False,
64
+ 'fetchBorrowRates': False,
65
+ 'fetchBorrowRatesPerSymbol': False,
56
66
  'fetchClosedOrders': True,
57
67
  'fetchCurrencies': True, # see below
58
68
  'fetchDepositAddress': True,
@@ -74,6 +84,10 @@ class okcoin(Exchange, ImplicitAPI):
74
84
  'fetchTrades': True,
75
85
  'fetchTransactions': None,
76
86
  'fetchWithdrawals': True,
87
+ 'reduceMargin': False,
88
+ 'repayCrossMargin': False,
89
+ 'repayIsolatedMargin': False,
90
+ 'setMargin': False,
77
91
  'transfer': True,
78
92
  'withdraw': True,
79
93
  },
@@ -1227,6 +1241,23 @@ class okcoin(Exchange, ImplicitAPI):
1227
1241
  result[code] = account
1228
1242
  return self.safe_balance(result)
1229
1243
 
1244
+ def create_market_buy_order_with_cost(self, symbol: str, cost, params={}):
1245
+ """
1246
+ create a market buy order by providing the symbol and cost
1247
+ :see: https://www.okcoin.com/docs-v5/en/#rest-api-trade-place-order
1248
+ :param str symbol: unified symbol of the market to create an order in
1249
+ :param float cost: how much you want to trade in units of the quote currency
1250
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1251
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1252
+ """
1253
+ self.load_markets()
1254
+ market = self.market(symbol)
1255
+ if not market['spot']:
1256
+ raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
1257
+ params['createMarketBuyOrderRequiresPrice'] = False
1258
+ params['tgtCcy'] = 'quote_ccy'
1259
+ return self.create_order(symbol, 'market', 'buy', cost, None, params)
1260
+
1230
1261
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount, price=None, params={}):
1231
1262
  """
1232
1263
  :see: https://www.okcoin.com/docs-v5/en/#rest-api-trade-place-order
@@ -1251,6 +1282,7 @@ class okcoin(Exchange, ImplicitAPI):
1251
1282
  :param float [params.stopLoss.triggerPrice]: stop loss trigger price
1252
1283
  :param float [params.stopLoss.price]: used for stop loss limit orders, not used for stop loss market price orders
1253
1284
  :param str [params.stopLoss.type]: 'market' or 'limit' used to specify the stop loss price type
1285
+ :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
1254
1286
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1255
1287
  """
1256
1288
  self.load_markets()
@@ -1293,7 +1325,7 @@ class okcoin(Exchange, ImplicitAPI):
1293
1325
  'ordType': type,
1294
1326
  # 'ordType': type, # privatePostTradeOrder: market, limit, post_only, fok, ioc, optimal_limit_ioc
1295
1327
  # 'ordType': type, # privatePostTradeOrderAlgo: conditional, oco, trigger, move_order_stop, iceberg, twap
1296
- 'sz': self.amount_to_precision(symbol, amount),
1328
+ # 'sz': self.amount_to_precision(symbol, amount),
1297
1329
  # 'px': self.price_to_precision(symbol, price), # limit orders only
1298
1330
  # 'reduceOnly': False,
1299
1331
  #
@@ -1351,27 +1383,35 @@ class okcoin(Exchange, ImplicitAPI):
1351
1383
  request['tgtCcy'] = tgtCcy
1352
1384
  if isMarketOrder or marketIOC:
1353
1385
  request['ordType'] = 'market'
1354
- if (side == 'buy'):
1386
+ if side == 'buy':
1355
1387
  # spot market buy: "sz" can refer either to base currency units or to quote currency units
1356
1388
  # see documentation: https://www.okx.com/docs-v5/en/#rest-api-trade-place-order
1357
1389
  if tgtCcy == 'quote_ccy':
1358
1390
  # quote_ccy: sz refers to units of quote currency
1359
- notional = self.safe_number_2(params, 'cost', 'sz')
1360
- createMarketBuyOrderRequiresPrice = self.safe_value(self.options, 'createMarketBuyOrderRequiresPrice', True)
1361
- if createMarketBuyOrderRequiresPrice:
1362
- if price is not None:
1363
- if notional is None:
1364
- amountString = self.number_to_string(amount)
1365
- priceString = self.number_to_string(price)
1366
- quoteAmount = Precise.string_mul(amountString, priceString)
1367
- notional = self.parse_number(quoteAmount)
1368
- elif notional is None:
1369
- raise InvalidOrder(self.id + " createOrder() requires the price argument with market buy orders to calculate total order cost(amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = False and supply the total cost value in the 'amount' argument or in the 'cost' unified extra parameter or in exchange-specific 'sz' extra parameter(the exchange-specific behaviour)")
1370
- else:
1371
- notional = amount if (notional is None) else notional
1372
- request['sz'] = self.cost_to_precision(symbol, notional)
1391
+ quoteAmount = None
1392
+ createMarketBuyOrderRequiresPrice = True
1393
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
1394
+ cost = self.safe_number_2(params, 'cost', 'sz')
1373
1395
  params = self.omit(params, ['cost', 'sz'])
1396
+ if cost is not None:
1397
+ quoteAmount = self.cost_to_precision(symbol, cost)
1398
+ elif createMarketBuyOrderRequiresPrice:
1399
+ if price is None:
1400
+ raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
1401
+ else:
1402
+ amountString = self.number_to_string(amount)
1403
+ priceString = self.number_to_string(price)
1404
+ costRequest = Precise.string_mul(amountString, priceString)
1405
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
1406
+ else:
1407
+ quoteAmount = self.cost_to_precision(symbol, amount)
1408
+ request['sz'] = quoteAmount
1409
+ else:
1410
+ request['sz'] = self.amount_to_precision(symbol, amount)
1411
+ else:
1412
+ request['sz'] = self.amount_to_precision(symbol, amount)
1374
1413
  else:
1414
+ request['sz'] = self.amount_to_precision(symbol, amount)
1375
1415
  if (not trigger) and (not conditional):
1376
1416
  request['px'] = self.price_to_precision(symbol, price)
1377
1417
  if postOnly:
ccxt/phemex.py CHANGED
@@ -100,7 +100,7 @@ class phemex(Exchange, ImplicitAPI):
100
100
  'setMarginMode': True,
101
101
  'setPositionMode': True,
102
102
  'transfer': True,
103
- 'withdraw': None,
103
+ 'withdraw': True,
104
104
  },
105
105
  'urls': {
106
106
  'logo': 'https://user-images.githubusercontent.com/1294454/85225056-221eb600-b3d7-11ea-930d-564d2690e3f6.jpg',
@@ -174,6 +174,7 @@ class phemex(Exchange, ImplicitAPI):
174
174
  },
175
175
  'v2': {
176
176
  'get': {
177
+ 'public/products': 5,
177
178
  'md/v2/orderbook': 5, # ?symbol=<symbol>&id=<id>
178
179
  'md/v2/trade': 5, # ?symbol=<symbol>&id=<id>
179
180
  'md/v2/ticker/24hr': 5, # ?symbol=<symbol>&id=<id>
@@ -238,6 +239,7 @@ class phemex(Exchange, ImplicitAPI):
238
239
  'assets/spots/sub-accounts/transfer': 5, # ?currency=<currency>&start=<start>&end=<end>&limit=<limit>&offset=<offset>
239
240
  'assets/futures/sub-accounts/transfer': 5, # ?currency=<currency>&start=<start>&end=<end>&limit=<limit>&offset=<offset>
240
241
  'assets/quote': 5, # ?fromCurrency=<currency>&toCurrency=<currency>&amountEv=<amount>
242
+ # deposit/withdraw
241
243
  },
242
244
  'post': {
243
245
  # spot
@@ -481,6 +483,16 @@ class phemex(Exchange, ImplicitAPI):
481
483
  'spot': 'spot',
482
484
  'swap': 'future',
483
485
  },
486
+ 'stableCoins': [
487
+ 'BUSD',
488
+ 'FEI',
489
+ 'TUSD',
490
+ 'USD',
491
+ 'USDC',
492
+ 'USDD',
493
+ 'USDP',
494
+ 'USDT',
495
+ ],
484
496
  'transfer': {
485
497
  'fillResponseFromRequest': True,
486
498
  },
@@ -499,6 +511,8 @@ class phemex(Exchange, ImplicitAPI):
499
511
  #
500
512
  # {
501
513
  # "symbol":"BTCUSD",
514
+ # "code":"1",
515
+ # "type":"Perpetual",
502
516
  # "displaySymbol":"BTC / USD",
503
517
  # "indexSymbol":".BTC",
504
518
  # "markSymbol":".MBTC",
@@ -516,9 +530,10 @@ class phemex(Exchange, ImplicitAPI):
516
530
  # "minPriceEp":5000,
517
531
  # "maxPriceEp":10000000000,
518
532
  # "maxOrderQty":1000000,
519
- # "type":"Perpetual",
520
533
  # "status":"Listed",
521
534
  # "tipOrderQty":1000000,
535
+ # "listTime":"1574650800000",
536
+ # "majorSymbol":true,
522
537
  # "steps":"50",
523
538
  # "riskLimits":[
524
539
  # {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
@@ -572,7 +587,7 @@ class phemex(Exchange, ImplicitAPI):
572
587
  else:
573
588
  # "1.0"
574
589
  contractSize = self.parse_number(contractSizeString)
575
- return {
590
+ return self.safe_market_structure({
576
591
  'id': id,
577
592
  'symbol': base + '/' + quote + ':' + settle,
578
593
  'base': base,
@@ -625,24 +640,26 @@ class phemex(Exchange, ImplicitAPI):
625
640
  },
626
641
  'created': None,
627
642
  'info': market,
628
- }
643
+ })
629
644
 
630
645
  def parse_spot_market(self, market):
631
646
  #
632
647
  # {
633
648
  # "symbol":"sBTCUSDT",
634
649
  # "code":1001,
650
+ # "type":"Spot",
635
651
  # "displaySymbol":"BTC / USDT",
636
652
  # "quoteCurrency":"USDT",
637
653
  # "priceScale":8,
638
654
  # "ratioScale":8,
639
655
  # "pricePrecision":2,
640
- # "type":"Spot",
641
656
  # "baseCurrency":"BTC",
642
657
  # "baseTickSize":"0.000001 BTC",
643
658
  # "baseTickSizeEv":100,
644
659
  # "quoteTickSize":"0.01 USDT",
645
660
  # "quoteTickSizeEv":1000000,
661
+ # "baseQtyPrecision":6,
662
+ # "quoteQtyPrecision":2,
646
663
  # "minOrderValue":"10 USDT",
647
664
  # "minOrderValueEv":1000000000,
648
665
  # "maxBaseOrderSize":"1000 BTC",
@@ -653,13 +670,13 @@ class phemex(Exchange, ImplicitAPI):
653
670
  # "defaultTakerFeeEr":100000,
654
671
  # "defaultMakerFee":"0.001",
655
672
  # "defaultMakerFeeEr":100000,
656
- # "baseQtyPrecision":6,
657
- # "quoteQtyPrecision":2,
673
+ # "description":"BTCUSDT is a BTC/USDT spot trading pair. Minimum order value is 1 USDT",
658
674
  # "status":"Listed",
659
675
  # "tipOrderQty":2,
660
- # "description":"BTCUSDT is a BTC/USDT spot trading pair. Minimum order value is 1 USDT",
676
+ # "listTime":1589338800000,
677
+ # "buyPriceUpperLimitPct":110,
678
+ # "sellPriceLowerLimitPct":90,
661
679
  # "leverage":5
662
- # "valueScale":8,
663
680
  # },
664
681
  #
665
682
  type = self.safe_string_lower(market, 'type')
@@ -671,7 +688,7 @@ class phemex(Exchange, ImplicitAPI):
671
688
  status = self.safe_string(market, 'status')
672
689
  precisionAmount = self.parse_safe_number(self.safe_string(market, 'baseTickSize'))
673
690
  precisionPrice = self.parse_safe_number(self.safe_string(market, 'quoteTickSize'))
674
- return {
691
+ return self.safe_market_structure({
675
692
  'id': id,
676
693
  'symbol': base + '/' + quote,
677
694
  'base': base,
@@ -724,7 +741,7 @@ class phemex(Exchange, ImplicitAPI):
724
741
  },
725
742
  'created': None,
726
743
  'info': market,
727
- }
744
+ })
728
745
 
729
746
  def fetch_markets(self, params={}):
730
747
  """
@@ -732,21 +749,22 @@ class phemex(Exchange, ImplicitAPI):
732
749
  :param dict [params]: extra parameters specific to the exchange API endpoint
733
750
  :returns dict[]: an array of objects representing market data
734
751
  """
735
- v2Products = self.publicGetCfgV2Products(params)
752
+ v2Products = self.v2GetPublicProducts(params)
736
753
  #
737
754
  # {
738
755
  # "code":0,
739
- # "msg":"OK",
756
+ # "msg":"",
740
757
  # "data":{
741
- # "ratioScale":8,
742
758
  # "currencies":[
743
- # {"code":1,"currency":"BTC","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"Bitcoin"},
744
- # {"code":2,"currency":"USD","valueScale":4,"minValueEv":1,"maxValueEv":500000000000000,"name":"USD"},
745
- # {"code":3,"currency":"USDT","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"TetherUS"},
759
+ # {"currency":"BTC","name":"Bitcoin","code":1,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"BTC","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":8},
760
+ # {"currency":"USD","name":"USD","code":2,"valueScale":4,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USD","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":2},
761
+ # {"currency":"USDT","name":"TetherUS","code":3,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USDT","inAssetsDisplay":1,"perpetual":2,"stableCoin":1,"assetsPrecision":8},
746
762
  # ],
747
763
  # "products":[
748
764
  # {
749
765
  # "symbol":"BTCUSD",
766
+ # "code":1,
767
+ # "type":"Perpetual"
750
768
  # "displaySymbol":"BTC / USD",
751
769
  # "indexSymbol":".BTC",
752
770
  # "markSymbol":".MBTC",
@@ -764,22 +782,31 @@ class phemex(Exchange, ImplicitAPI):
764
782
  # "minPriceEp":5000,
765
783
  # "maxPriceEp":10000000000,
766
784
  # "maxOrderQty":1000000,
767
- # "type":"Perpetual"
785
+ # "description":"BTC/USD perpetual contracts are priced on the .BTC Index. Each contract is worth 1 USD. Funding fees are paid and received every 8 hours at UTC time: 00:00, 08:00 and 16:00.",
786
+ # "status":"Listed",
787
+ # "tipOrderQty":1000000,
788
+ # "listTime":1574650800000,
789
+ # "majorSymbol":true,
790
+ # "defaultLeverage":"-10",
791
+ # "fundingInterval":28800,
792
+ # "maxLeverage":100
768
793
  # },
769
794
  # {
770
795
  # "symbol":"sBTCUSDT",
771
796
  # "code":1001,
797
+ # "type":"Spot",
772
798
  # "displaySymbol":"BTC / USDT",
773
799
  # "quoteCurrency":"USDT",
774
800
  # "priceScale":8,
775
801
  # "ratioScale":8,
776
802
  # "pricePrecision":2,
777
- # "type":"Spot",
778
803
  # "baseCurrency":"BTC",
779
804
  # "baseTickSize":"0.000001 BTC",
780
805
  # "baseTickSizeEv":100,
781
806
  # "quoteTickSize":"0.01 USDT",
782
807
  # "quoteTickSizeEv":1000000,
808
+ # "baseQtyPrecision":6,
809
+ # "quoteQtyPrecision":2,
783
810
  # "minOrderValue":"10 USDT",
784
811
  # "minOrderValueEv":1000000000,
785
812
  # "maxBaseOrderSize":"1000 BTC",
@@ -790,14 +817,51 @@ class phemex(Exchange, ImplicitAPI):
790
817
  # "defaultTakerFeeEr":100000,
791
818
  # "defaultMakerFee":"0.001",
792
819
  # "defaultMakerFeeEr":100000,
793
- # "baseQtyPrecision":6,
794
- # "quoteQtyPrecision":2,
820
+ # "description":"BTCUSDT is a BTC/USDT spot trading pair. Minimum order value is 1 USDT",
795
821
  # "status":"Listed",
796
822
  # "tipOrderQty":2,
797
- # "description":"BTCUSDT is a BTC/USDT spot trading pair. Minimum order value is 1 USDT",
823
+ # "listTime":1589338800000,
824
+ # "buyPriceUpperLimitPct":110,
825
+ # "sellPriceLowerLimitPct":90,
798
826
  # "leverage":5
799
827
  # },
800
828
  # ],
829
+ # "perpProductsV2":[
830
+ # {
831
+ # "symbol":"BTCUSDT",
832
+ # "code":41541,
833
+ # "type":"PerpetualV2",
834
+ # "displaySymbol":"BTC / USDT",
835
+ # "indexSymbol":".BTCUSDT",
836
+ # "markSymbol":".MBTCUSDT",
837
+ # "fundingRateSymbol":".BTCUSDTFR",
838
+ # "fundingRate8hSymbol":".BTCUSDTFR8H",
839
+ # "contractUnderlyingAssets":"BTC",
840
+ # "settleCurrency":"USDT",
841
+ # "quoteCurrency":"USDT",
842
+ # "tickSize":"0.1",
843
+ # "priceScale":0,
844
+ # "ratioScale":0,
845
+ # "pricePrecision":1,
846
+ # "baseCurrency":"BTC",
847
+ # "description":"BTC/USDT perpetual contracts are priced on the .BTCUSDT Index. Each contract is worth 1 BTC. Funding fees are paid and received every 8 hours at UTC time: 00:00, 08:00 and 16:00.",
848
+ # "status":"Listed",
849
+ # "tipOrderQty":0,
850
+ # "listTime":1668225600000,
851
+ # "majorSymbol":true,
852
+ # "defaultLeverage":"-10",
853
+ # "fundingInterval":28800,
854
+ # "maxLeverage":100,
855
+ # "maxOrderQtyRq":"1000",
856
+ # "maxPriceRp":"2000000000",
857
+ # "minOrderValueRv":"1",
858
+ # "minPriceRp":"1000.0",
859
+ # "qtyPrecision":3,
860
+ # "qtyStepSize":"0.001",
861
+ # "tipOrderQtyRq":"200",
862
+ # "maxOpenPosLeverage":100.0
863
+ # },
864
+ # ],
801
865
  # "riskLimits":[
802
866
  # {
803
867
  # "symbol":"BTCUSD",
@@ -813,7 +877,25 @@ class phemex(Exchange, ImplicitAPI):
813
877
  # {"initialMargin":"1.0%","initialMarginEr":1000000,"options":[1,2,3,5,10,25,50,100]},
814
878
  # {"initialMargin":"1.5%","initialMarginEr":1500000,"options":[1,2,3,5,10,25,50,66]},
815
879
  # {"initialMargin":"2.0%","initialMarginEr":2000000,"options":[1,2,3,5,10,25,33,50]},
816
- # ]
880
+ # ],
881
+ # "riskLimitsV2":[
882
+ # {
883
+ # "symbol":"BTCUSDT",
884
+ # "steps":"2000K",
885
+ # "riskLimits":[
886
+ # {"limit":2000000,"initialMarginRr":"0.01","maintenanceMarginRr":"0.005"},,
887
+ # {"limit":4000000,"initialMarginRr":"0.015","maintenanceMarginRr":"0.0075"},
888
+ # {"limit":6000000,"initialMarginRr":"0.02","maintenanceMarginRr":"0.01"},
889
+ # ]
890
+ # },
891
+ # ],
892
+ # "leveragesV2":[
893
+ # {"options":[1.0,2.0,3.0,5.0,10.0,25.0,50.0,100.0],"initialMarginRr":"0.01"},
894
+ # {"options":[1.0,2.0,3.0,5.0,10.0,25.0,50.0,66.67],"initialMarginRr":"0.015"},
895
+ # {"options":[1.0,2.0,3.0,5.0,10.0,25.0,33.0,50.0],"initialMarginRr":"0.02"},
896
+ # ],
897
+ # "ratioScale":8,
898
+ # "md5Checksum":"5c6604814d3c1bafbe602c3d11a7e8bf",
817
899
  # }
818
900
  # }
819
901
  #
@@ -856,7 +938,11 @@ class phemex(Exchange, ImplicitAPI):
856
938
  #
857
939
  v2ProductsData = self.safe_value(v2Products, 'data', {})
858
940
  products = self.safe_value(v2ProductsData, 'products', [])
941
+ perpetualProductsV2 = self.safe_value(v2ProductsData, 'perpProductsV2', [])
942
+ products = self.array_concat(products, perpetualProductsV2)
859
943
  riskLimits = self.safe_value(v2ProductsData, 'riskLimits', [])
944
+ riskLimitsV2 = self.safe_value(v2ProductsData, 'riskLimitsV2', [])
945
+ riskLimits = self.array_concat(riskLimits, riskLimitsV2)
860
946
  currencies = self.safe_value(v2ProductsData, 'currencies', [])
861
947
  riskLimitsById = self.index_by(riskLimits, 'symbol')
862
948
  v1ProductsById = self.index_by(v1ProductsData, 'symbol')
@@ -887,7 +973,7 @@ class phemex(Exchange, ImplicitAPI):
887
973
  :param dict [params]: extra parameters specific to the exchange API endpoint
888
974
  :returns dict: an associative dictionary of currencies
889
975
  """
890
- response = self.publicGetCfgV2Products(params)
976
+ response = self.v2GetPublicProducts(params)
891
977
  #
892
978
  # {
893
979
  # "code":0,
@@ -895,9 +981,9 @@ class phemex(Exchange, ImplicitAPI):
895
981
  # "data":{
896
982
  # ...,
897
983
  # "currencies":[
898
- # {"currency":"BTC","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"Bitcoin"},
899
- # {"currency":"USD","valueScale":4,"minValueEv":1,"maxValueEv":500000000000000,"name":"USD"},
900
- # {"currency":"USDT","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"TetherUS"},
984
+ # {"currency":"BTC","name":"Bitcoin","code":1,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"BTC","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":8},
985
+ # {"currency":"USD","name":"USD","code":2,"valueScale":4,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USD","inAssetsDisplay":1,"perpetual":0,"stableCoin":0,"assetsPrecision":2},
986
+ # {"currency":"USDT","name":"TetherUS","code":3,"valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"needAddrTag":0,"status":"Listed","displayCurrency":"USDT","inAssetsDisplay":1,"perpetual":2,"stableCoin":1,"assetsPrecision":8},
901
987
  # ],
902
988
  # ...
903
989
  # }
@@ -910,6 +996,7 @@ class phemex(Exchange, ImplicitAPI):
910
996
  id = self.safe_string(currency, 'currency')
911
997
  name = self.safe_string(currency, 'name')
912
998
  code = self.safe_currency_code(id)
999
+ status = self.safe_string(currency, 'status')
913
1000
  valueScaleString = self.safe_string(currency, 'valueScale')
914
1001
  valueScale = int(valueScaleString)
915
1002
  minValueEv = self.safe_string(currency, 'minValueEv')
@@ -927,7 +1014,7 @@ class phemex(Exchange, ImplicitAPI):
927
1014
  'info': currency,
928
1015
  'code': code,
929
1016
  'name': name,
930
- 'active': None,
1017
+ 'active': status == 'Listed',
931
1018
  'deposit': None,
932
1019
  'withdraw': None,
933
1020
  'fee': None,
@@ -4151,6 +4238,42 @@ class phemex(Exchange, ImplicitAPI):
4151
4238
  sorted = self.sort_by(result, 'timestamp')
4152
4239
  return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
4153
4240
 
4241
+ def withdraw(self, code: str, amount, address, tag=None, params={}):
4242
+ """
4243
+ make a withdrawal
4244
+ :see: https://phemex-docs.github.io/#create-withdraw-request
4245
+ :param str code: unified currency code
4246
+ :param float amount: the amount to withdraw
4247
+ :param str address: the address to withdraw to
4248
+ :param str tag:
4249
+ :param dict [params]: extra parameters specific to the phemex api endpoint
4250
+ :param str [params.network]: unified network code
4251
+ :returns dict: a `transaction structure <https://github.com/ccxt/ccxt/wiki/Manual#transaction-structure>`
4252
+ """
4253
+ tag, params = self.handle_withdraw_tag_and_params(tag, params)
4254
+ self.load_markets()
4255
+ self.check_address(address)
4256
+ currency = self.currency(code)
4257
+ networkCode = None
4258
+ networkCode, params = self.handle_network_code_and_params(params)
4259
+ networkId = self.network_code_to_id(networkCode)
4260
+ stableCoins = self.safe_value(self.options, 'stableCoins')
4261
+ if networkId is None:
4262
+ if not (self.in_array(code, stableCoins)):
4263
+ networkId = currency['id']
4264
+ else:
4265
+ raise ArgumentsRequired(self.id + ' withdraw() requires an extra argument params["network"]')
4266
+ request = {
4267
+ 'currency': currency['id'],
4268
+ 'address': address,
4269
+ 'amount': amount,
4270
+ 'chainName': networkId.upper(),
4271
+ }
4272
+ if tag is not None:
4273
+ request['tag'] = tag
4274
+ response = self.privatePostPhemexWithdrawWalletsApiCreateWithdraw(self.extend(request, params))
4275
+ return self.parse_transaction(response, currency)
4276
+
4154
4277
  def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
4155
4278
  if response is None:
4156
4279
  return None # fallback to default error handler
ccxt/poloniex.py CHANGED
@@ -47,6 +47,9 @@ class poloniex(Exchange, ImplicitAPI):
47
47
  'cancelAllOrders': True,
48
48
  'cancelOrder': True,
49
49
  'createDepositAddress': True,
50
+ 'createMarketBuyOrderWithCost': True,
51
+ 'createMarketOrderWithCost': False,
52
+ 'createMarketSellOrderWithCost': False,
50
53
  'createOrder': True,
51
54
  'editOrder': True,
52
55
  'fetchBalance': True,
@@ -240,6 +243,7 @@ class poloniex(Exchange, ImplicitAPI):
240
243
  'UST': 'USTC',
241
244
  },
242
245
  'options': {
246
+ 'createMarketBuyOrderRequiresPrice': True,
243
247
  'networks': {
244
248
  'BEP20': 'BSC',
245
249
  'ERC20': 'ETH',
@@ -1219,6 +1223,7 @@ class poloniex(Exchange, ImplicitAPI):
1219
1223
  :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1220
1224
  :param dict [params]: extra parameters specific to the exchange API endpoint
1221
1225
  :param float [params.triggerPrice]: *spot only* The price at which a trigger order is triggered at
1226
+ :param float [params.cost]: *spot market buy only* the quote quantity that can be used alternative for the amount
1222
1227
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1223
1228
  """
1224
1229
  self.load_markets()
@@ -1251,7 +1256,6 @@ class poloniex(Exchange, ImplicitAPI):
1251
1256
  return self.parse_order(response, market)
1252
1257
 
1253
1258
  def order_request(self, symbol, type, side, amount, request, price=None, params={}):
1254
- market = self.market(symbol)
1255
1259
  upperCaseType = type.upper()
1256
1260
  isMarket = upperCaseType == 'MARKET'
1257
1261
  isPostOnly = self.is_post_only(isMarket, upperCaseType == 'LIMIT_MAKER', params)
@@ -1265,7 +1269,24 @@ class poloniex(Exchange, ImplicitAPI):
1265
1269
  request['type'] = upperCaseType
1266
1270
  if isMarket:
1267
1271
  if side == 'buy':
1268
- request['amount'] = self.currency_to_precision(market['quote'], amount)
1272
+ quoteAmount = None
1273
+ createMarketBuyOrderRequiresPrice = True
1274
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
1275
+ cost = self.safe_number(params, 'cost')
1276
+ params = self.omit(params, 'cost')
1277
+ if cost is not None:
1278
+ quoteAmount = self.cost_to_precision(symbol, cost)
1279
+ elif createMarketBuyOrderRequiresPrice:
1280
+ if price is None:
1281
+ raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend(quote quantity) in the amount argument')
1282
+ else:
1283
+ amountString = self.number_to_string(amount)
1284
+ priceString = self.number_to_string(price)
1285
+ costRequest = Precise.string_mul(amountString, priceString)
1286
+ quoteAmount = self.cost_to_precision(symbol, costRequest)
1287
+ else:
1288
+ quoteAmount = self.cost_to_precision(symbol, amount)
1289
+ request['amount'] = quoteAmount
1269
1290
  else:
1270
1291
  request['quantity'] = self.amount_to_precision(symbol, amount)
1271
1292
  else:
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.1.88'
7
+ __version__ = '4.1.90'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/binance.py CHANGED
@@ -444,7 +444,7 @@ class binance(ccxt.async_support.binance):
444
444
  subscribe = {
445
445
  'id': requestId,
446
446
  }
447
- trades = await self.watch(url, subParams, self.extend(request, query), subParams, subscribe)
447
+ trades = await self.watch_multiple(url, subParams, self.extend(request, query), subParams, subscribe)
448
448
  if self.newUpdates:
449
449
  first = self.safe_value(trades, 0)
450
450
  tradeSymbol = self.safe_string(first, 'symbol')
@@ -1802,10 +1802,10 @@ class binance(ccxt.async_support.binance):
1802
1802
  self.set_balance_cache(client, type)
1803
1803
  self.set_positions_cache(client, type)
1804
1804
  message = None
1805
- newOrder = await self.watch(url, messageHash, message, type)
1805
+ orders = await self.watch(url, messageHash, message, type)
1806
1806
  if self.newUpdates:
1807
- return newOrder
1808
- return self.filter_by_symbol_since_limit(self.orders, symbol, since, limit, True)
1807
+ limit = orders.getLimit(symbol, limit)
1808
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
1809
1809
 
1810
1810
  def parse_ws_order(self, order, market=None):
1811
1811
  #
@@ -2405,8 +2405,8 @@ class binance(ccxt.async_support.binance):
2405
2405
  cachedOrders.append(parsed)
2406
2406
  messageHash = 'orders'
2407
2407
  symbolSpecificMessageHash = 'orders:' + symbol
2408
- client.resolve(parsed, messageHash)
2409
- client.resolve(parsed, symbolSpecificMessageHash)
2408
+ client.resolve(cachedOrders, messageHash)
2409
+ client.resolve(cachedOrders, symbolSpecificMessageHash)
2410
2410
 
2411
2411
  def handle_acount_update(self, client, message):
2412
2412
  self.handle_balance(client, message)