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
@@ -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,
@@ -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,
@@ -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
+ async 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
+ await 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 await self.create_order(symbol, 'market', 'buy', cost, None, params)
1260
+
1230
1261
  async 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
  await 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:
@@ -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
  async 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 = await self.publicGetCfgV2Products(params)
752
+ v2Products = await 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 = await self.publicGetCfgV2Products(params)
976
+ response = await 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
+ async 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
+ await 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 = await 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
@@ -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
  await 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:
@@ -59,6 +59,9 @@ class tokocrypto(Exchange, ImplicitAPI):
59
59
  'cancelOrder': True,
60
60
  'cancelOrders': None,
61
61
  'createDepositAddress': False,
62
+ 'createMarketBuyOrderWithCost': True,
63
+ 'createMarketOrderWithCost': False,
64
+ 'createMarketSellOrderWithCost': False,
62
65
  'createOrder': True,
63
66
  'createReduceOnlyOrder': None,
64
67
  'createStopLimitOrder': True,
@@ -126,6 +129,8 @@ class tokocrypto(Exchange, ImplicitAPI):
126
129
  'fetchWithdrawals': True,
127
130
  'fetchWithdrawalWhitelist': False,
128
131
  'reduceMargin': False,
132
+ 'repayCrossMargin': False,
133
+ 'repayIsolatedMargin': False,
129
134
  'setLeverage': False,
130
135
  'setMargin': False,
131
136
  'setMarginMode': False,
@@ -1544,6 +1549,7 @@ class tokocrypto(Exchange, ImplicitAPI):
1544
1549
  :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1545
1550
  :param dict [params]: extra parameters specific to the exchange API endpoint
1546
1551
  :param float [params.triggerPrice]: the price at which a trigger order would be triggered
1552
+ :param float [params.cost]: for spot market buy orders, the quote quantity that can be used alternative for the amount
1547
1553
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1548
1554
  """
1549
1555
  await self.load_markets()
@@ -1610,18 +1616,25 @@ class tokocrypto(Exchange, ImplicitAPI):
1610
1616
  # LIMIT_MAKER quantity, price
1611
1617
  #
1612
1618
  if uppercaseType == 'MARKET':
1613
- quoteOrderQtyInner = self.safe_value_2(params, 'quoteOrderQty', 'cost')
1614
- if self.options['createMarketBuyOrderRequiresPrice'] and (side == 'buy') and (price is None) and (quoteOrderQtyInner is None):
1615
- raise InvalidOrder(self.id + ' createOrder() requires price argument for market buy orders on spot markets to calculate the total amount to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option to False and pass in the cost to spend into the amount parameter')
1616
- precision = market['precision']['price']
1617
- if quoteOrderQtyInner is not None:
1618
- request['quoteOrderQty'] = self.decimal_to_precision(quoteOrderQtyInner, TRUNCATE, precision, self.precisionMode)
1619
- params = self.omit(params, ['quoteOrderQty', 'cost'])
1620
- elif price is not None:
1621
- amountString = self.number_to_string(amount)
1622
- priceString = self.number_to_string(price)
1623
- quoteOrderQty = Precise.string_mul(amountString, priceString)
1624
- request['quoteOrderQty'] = self.decimal_to_precision(quoteOrderQty, TRUNCATE, precision, self.precisionMode)
1619
+ if side == 'buy':
1620
+ precision = market['precision']['price']
1621
+ quoteAmount = None
1622
+ createMarketBuyOrderRequiresPrice = True
1623
+ createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice', True)
1624
+ cost = self.safe_number_2(params, 'cost', 'quoteOrderQty')
1625
+ params = self.omit(params, ['cost', 'quoteOrderQty'])
1626
+ if cost is not None:
1627
+ quoteAmount = cost
1628
+ elif createMarketBuyOrderRequiresPrice:
1629
+ if price is None:
1630
+ 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')
1631
+ else:
1632
+ amountString = self.number_to_string(amount)
1633
+ priceString = self.number_to_string(price)
1634
+ quoteAmount = Precise.string_mul(amountString, priceString)
1635
+ else:
1636
+ quoteAmount = amount
1637
+ request['quoteOrderQty'] = self.decimal_to_precision(quoteAmount, TRUNCATE, precision, self.precisionMode)
1625
1638
  else:
1626
1639
  quantityIsRequired = True
1627
1640
  elif uppercaseType == 'LIMIT':