ccxt 4.3.79__py2.py3-none-any.whl → 4.3.81__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.
ccxt/__init__.py CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.3.79'
25
+ __version__ = '4.3.81'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.79'
7
+ __version__ = '4.3.81'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # -----------------------------------------------------------------------------
4
4
 
5
- __version__ = '4.3.79'
5
+ __version__ = '4.3.81'
6
6
 
7
7
  # -----------------------------------------------------------------------------
8
8
 
@@ -75,7 +75,7 @@ class binance(Exchange, ImplicitAPI):
75
75
  'createMarketSellOrderWithCost': True,
76
76
  'createOrder': True,
77
77
  'createOrders': True,
78
- 'createOrderWithTakeProfitAndStopLoss': True,
78
+ 'createOrderWithTakeProfitAndStopLoss': False,
79
79
  'createPostOnlyOrder': True,
80
80
  'createReduceOnlyOrder': True,
81
81
  'createStopLimitOrder': True,
@@ -2364,8 +2364,6 @@ class bitmart(Exchange, ImplicitAPI):
2364
2364
  :see: https://developer-pro.bitmart.com/en/spot/#place-margin-order
2365
2365
  :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2366
2366
  :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2367
- :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2368
- :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2369
2367
  :see: https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2370
2368
  :param str symbol: unified symbol of the market to create an order in
2371
2369
  :param str type: 'market', 'limit' or 'trailing' for swap markets only
@@ -2496,6 +2494,7 @@ class bitmart(Exchange, ImplicitAPI):
2496
2494
  create a trade order
2497
2495
  :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2498
2496
  :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2497
+ :see: https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2499
2498
  :param str symbol: unified symbol of the market to create an order in
2500
2499
  :param str type: 'market', 'limit' or 'trailing'
2501
2500
  :param str side: 'buy' or 'sell'
@@ -2549,7 +2548,8 @@ class bitmart(Exchange, ImplicitAPI):
2549
2548
  request['activation_price'] = self.price_to_precision(symbol, trailingTriggerPrice)
2550
2549
  request['activation_price_type'] = self.safe_integer(params, 'activation_price_type', 1)
2551
2550
  if isTriggerOrder:
2552
- request['executive_price'] = self.price_to_precision(symbol, price)
2551
+ if isLimitOrder or price is not None:
2552
+ request['executive_price'] = self.price_to_precision(symbol, price)
2553
2553
  request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
2554
2554
  request['price_type'] = self.safe_integer(params, 'price_type', 1)
2555
2555
  if side == 'buy':
@@ -1210,6 +1210,18 @@ class bybit(Exchange, ImplicitAPI):
1210
1210
  optionType = self.safe_string(optionParts, 3)
1211
1211
  datetime = self.convert_expire_date(expiry)
1212
1212
  timestamp = self.parse8601(datetime)
1213
+ amountPrecision = None
1214
+ pricePrecision = None
1215
+ # hard coded amount and price precisions from fetchOptionMarkets
1216
+ if base == 'BTC':
1217
+ amountPrecision = self.parse_number('0.01')
1218
+ pricePrecision = self.parse_number('5')
1219
+ elif base == 'ETH':
1220
+ amountPrecision = self.parse_number('0.1')
1221
+ pricePrecision = self.parse_number('0.1')
1222
+ elif base == 'SOL':
1223
+ amountPrecision = self.parse_number('1')
1224
+ pricePrecision = self.parse_number('0.01')
1213
1225
  return {
1214
1226
  'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
1215
1227
  'symbol': base + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
@@ -1229,14 +1241,14 @@ class bybit(Exchange, ImplicitAPI):
1229
1241
  'option': True,
1230
1242
  'margin': False,
1231
1243
  'contract': True,
1232
- 'contractSize': None,
1244
+ 'contractSize': self.parse_number('1'),
1233
1245
  'expiry': timestamp,
1234
1246
  'expiryDatetime': datetime,
1235
1247
  'optionType': 'call' if (optionType == 'C') else 'put',
1236
1248
  'strike': self.parse_number(strike),
1237
1249
  'precision': {
1238
- 'amount': None,
1239
- 'price': None,
1250
+ 'amount': amountPrecision,
1251
+ 'price': pricePrecision,
1240
1252
  },
1241
1253
  'limits': {
1242
1254
  'amount': {
@@ -1271,6 +1283,30 @@ class bybit(Exchange, ImplicitAPI):
1271
1283
  return [type, params]
1272
1284
  return [subType, params]
1273
1285
 
1286
+ def get_amount(self, symbol: str, amount: float):
1287
+ # some markets like options might not have the precision available
1288
+ # and we shouldn't crash in those cases
1289
+ market = self.market(symbol)
1290
+ emptyPrecisionAmount = (market['precision']['amount'] is None)
1291
+ amountString = self.number_to_string(amount)
1292
+ if not emptyPrecisionAmount and (amountString != '0'):
1293
+ return self.amount_to_precision(symbol, amount)
1294
+ return amountString
1295
+
1296
+ def get_price(self, symbol: str, price: str):
1297
+ market = self.market(symbol)
1298
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1299
+ if not emptyPrecisionPrice:
1300
+ return self.price_to_precision(symbol, price)
1301
+ return price
1302
+
1303
+ def get_cost(self, symbol: str, cost: str):
1304
+ market = self.market(symbol)
1305
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1306
+ if not emptyPrecisionPrice:
1307
+ return self.cost_to_precision(symbol, cost)
1308
+ return cost
1309
+
1274
1310
  async def fetch_time(self, params={}):
1275
1311
  """
1276
1312
  fetches the current integer timestamp in milliseconds from the exchange server
@@ -1848,7 +1884,7 @@ class bybit(Exchange, ImplicitAPI):
1848
1884
  'inverse': None,
1849
1885
  'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
1850
1886
  'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
1851
- 'contractSize': self.safe_number(lotSizeFilter, 'minOrderQty'),
1887
+ 'contractSize': self.parse_number('1'),
1852
1888
  'expiry': expiry,
1853
1889
  'expiryDatetime': self.iso8601(expiry),
1854
1890
  'strike': self.parse_number(strike),
@@ -3474,24 +3510,26 @@ class bybit(Exchange, ImplicitAPI):
3474
3510
  isLimit = lowerCaseType == 'limit'
3475
3511
  isBuy = side == 'buy'
3476
3512
  isAlternativeEndpoint = defaultMethod == 'privatePostV5PositionTradingStop'
3513
+ amountString = self.get_amount(symbol, amount)
3514
+ priceString = self.get_price(symbol, self.number_to_string(price)) if (price is not None) else None
3477
3515
  if isTrailingAmountOrder or isAlternativeEndpoint:
3478
3516
  if isStopLoss or isTakeProfit or isTriggerOrder or market['spot']:
3479
3517
  raise InvalidOrder(self.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders')
3480
3518
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3481
3519
  if isStopLossTriggerOrder:
3482
- request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
3520
+ request['stopLoss'] = self.get_price(symbol, stopLossTriggerPrice)
3483
3521
  if isLimit:
3484
3522
  request['tpslMode'] = 'Partial'
3485
3523
  request['slOrderType'] = 'Limit'
3486
- request['slLimitPrice'] = self.price_to_precision(symbol, price)
3487
- request['slSize'] = self.amount_to_precision(symbol, amount)
3524
+ request['slLimitPrice'] = priceString
3525
+ request['slSize'] = amountString
3488
3526
  elif isTakeProfitTriggerOrder:
3489
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
3527
+ request['takeProfit'] = self.get_price(symbol, takeProfitTriggerPrice)
3490
3528
  if isLimit:
3491
3529
  request['tpslMode'] = 'Partial'
3492
3530
  request['tpOrderType'] = 'Limit'
3493
- request['tpLimitPrice'] = self.price_to_precision(symbol, price)
3494
- request['tpSize'] = self.amount_to_precision(symbol, amount)
3531
+ request['tpLimitPrice'] = priceString
3532
+ request['tpSize'] = amountString
3495
3533
  else:
3496
3534
  request['side'] = self.capitalize(side)
3497
3535
  request['orderType'] = self.capitalize(lowerCaseType)
@@ -3519,7 +3557,7 @@ class bybit(Exchange, ImplicitAPI):
3519
3557
  # mandatory field for options
3520
3558
  request['orderLinkId'] = self.uuid16()
3521
3559
  if isLimit:
3522
- request['price'] = self.price_to_precision(symbol, price)
3560
+ request['price'] = priceString
3523
3561
  if market['spot']:
3524
3562
  request['category'] = 'spot'
3525
3563
  elif market['linear']:
@@ -3540,14 +3578,12 @@ class bybit(Exchange, ImplicitAPI):
3540
3578
  if cost is not None:
3541
3579
  orderCost = cost
3542
3580
  else:
3543
- amountString = self.number_to_string(amount)
3544
- priceString = self.number_to_string(price)
3545
3581
  quoteAmount = Precise.string_mul(amountString, priceString)
3546
3582
  orderCost = quoteAmount
3547
- request['qty'] = self.cost_to_precision(symbol, orderCost)
3583
+ request['qty'] = self.get_cost(symbol, orderCost)
3548
3584
  else:
3549
3585
  request['marketUnit'] = 'baseCoin'
3550
- request['qty'] = self.amount_to_precision(symbol, amount)
3586
+ request['qty'] = amountString
3551
3587
  elif market['spot'] and (type == 'market') and (side == 'buy'):
3552
3588
  # classic accounts
3553
3589
  # for market buy it requires the amount of quote currency to spend
@@ -3557,22 +3593,17 @@ class bybit(Exchange, ImplicitAPI):
3557
3593
  if (price is None) and (cost is None):
3558
3594
  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 in the amount argument')
3559
3595
  else:
3560
- amountString = self.number_to_string(amount)
3561
- priceString = self.number_to_string(price)
3562
3596
  quoteAmount = Precise.string_mul(amountString, priceString)
3563
3597
  costRequest = cost if (cost is not None) else quoteAmount
3564
- request['qty'] = self.cost_to_precision(symbol, costRequest)
3598
+ request['qty'] = self.get_cost(symbol, costRequest)
3565
3599
  else:
3566
- request['qty'] = self.cost_to_precision(symbol, amount)
3600
+ request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
3567
3601
  else:
3568
3602
  if not isTrailingAmountOrder and not isAlternativeEndpoint:
3569
- if market['option']:
3570
- request['qty'] = self.number_to_string(amount)
3571
- else:
3572
- request['qty'] = self.amount_to_precision(symbol, amount)
3603
+ request['qty'] = amountString
3573
3604
  if isTrailingAmountOrder:
3574
3605
  if trailingTriggerPrice is not None:
3575
- request['activePrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
3606
+ request['activePrice'] = self.get_price(symbol, trailingTriggerPrice)
3576
3607
  request['trailingStop'] = trailingAmount
3577
3608
  elif isTriggerOrder and not isAlternativeEndpoint:
3578
3609
  triggerDirection = self.safe_string(params, 'triggerDirection')
@@ -3585,32 +3616,32 @@ class bybit(Exchange, ImplicitAPI):
3585
3616
  raise ArgumentsRequired(self.id + ' stop/trigger orders require a triggerDirection parameter, either "above" or "below" to determine the direction of the trigger.')
3586
3617
  isAsending = ((triggerDirection == 'above') or (triggerDirection == '1'))
3587
3618
  request['triggerDirection'] = 1 if isAsending else 2
3588
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3619
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3589
3620
  elif (isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not isAlternativeEndpoint:
3590
3621
  if isBuy:
3591
3622
  request['triggerDirection'] = 1 if isStopLossTriggerOrder else 2
3592
3623
  else:
3593
3624
  request['triggerDirection'] = 2 if isStopLossTriggerOrder else 1
3594
3625
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3595
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3626
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3596
3627
  request['reduceOnly'] = True
3597
3628
  if (isStopLoss or isTakeProfit) and not isAlternativeEndpoint:
3598
3629
  if isStopLoss:
3599
3630
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3600
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3631
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3601
3632
  slLimitPrice = self.safe_value(stopLoss, 'price')
3602
3633
  if slLimitPrice is not None:
3603
3634
  request['tpslMode'] = 'Partial'
3604
3635
  request['slOrderType'] = 'Limit'
3605
- request['slLimitPrice'] = self.price_to_precision(symbol, slLimitPrice)
3636
+ request['slLimitPrice'] = self.get_price(symbol, slLimitPrice)
3606
3637
  if isTakeProfit:
3607
3638
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3608
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3639
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3609
3640
  tpLimitPrice = self.safe_value(takeProfit, 'price')
3610
3641
  if tpLimitPrice is not None:
3611
3642
  request['tpslMode'] = 'Partial'
3612
3643
  request['tpOrderType'] = 'Limit'
3613
- request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
3644
+ request['tpLimitPrice'] = self.get_price(symbol, tpLimitPrice)
3614
3645
  params = self.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice'])
3615
3646
  return self.extend(request, params)
3616
3647
 
@@ -3710,7 +3741,7 @@ class bybit(Exchange, ImplicitAPI):
3710
3741
  'side': self.capitalize(side),
3711
3742
  'orderType': self.capitalize(lowerCaseType), # limit or market
3712
3743
  'timeInForce': 'GoodTillCancel', # ImmediateOrCancel, FillOrKill, PostOnly
3713
- 'orderQty': self.amount_to_precision(symbol, amount),
3744
+ 'orderQty': self.get_amount(symbol, amount),
3714
3745
  # 'takeProfit': 123.45, # take profit price, only take effect upon opening the position
3715
3746
  # 'stopLoss': 123.45, # stop loss price, only take effect upon opening the position
3716
3747
  # 'reduceOnly': False, # reduce only, required for linear orders
@@ -3728,7 +3759,7 @@ class bybit(Exchange, ImplicitAPI):
3728
3759
  isMarket = lowerCaseType == 'market'
3729
3760
  isLimit = lowerCaseType == 'limit'
3730
3761
  if isLimit is not None:
3731
- request['orderPrice'] = self.price_to_precision(symbol, price)
3762
+ request['orderPrice'] = self.get_price(symbol, self.number_to_string(price))
3732
3763
  exchangeSpecificParam = self.safe_string(params, 'time_in_force')
3733
3764
  timeInForce = self.safe_string_lower(params, 'timeInForce')
3734
3765
  postOnly = self.is_post_only(isMarket, exchangeSpecificParam == 'PostOnly', params)
@@ -3755,17 +3786,17 @@ class bybit(Exchange, ImplicitAPI):
3755
3786
  request['orderFilter'] = 'StopOrder'
3756
3787
  request['trigger_by'] = 'LastPrice'
3757
3788
  stopPx = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3758
- preciseStopPrice = self.price_to_precision(symbol, stopPx)
3789
+ preciseStopPrice = self.get_price(symbol, stopPx)
3759
3790
  request['triggerPrice'] = preciseStopPrice
3760
3791
  delta = self.number_to_string(market['precision']['price'])
3761
3792
  request['basePrice'] = Precise.string_sub(preciseStopPrice, delta) if isStopLossTriggerOrder else Precise.string_add(preciseStopPrice, delta)
3762
3793
  elif isStopLoss or isTakeProfit:
3763
3794
  if isStopLoss:
3764
3795
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3765
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3796
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3766
3797
  if isTakeProfit:
3767
3798
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3768
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3799
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3769
3800
  else:
3770
3801
  request['orderFilter'] = 'Order'
3771
3802
  clientOrderId = self.safe_string(params, 'clientOrderId')
@@ -3816,9 +3847,9 @@ class bybit(Exchange, ImplicitAPI):
3816
3847
  'orderId': id,
3817
3848
  }
3818
3849
  if amount is not None:
3819
- request['orderQty'] = self.amount_to_precision(symbol, amount)
3850
+ request['orderQty'] = self.get_amount(symbol, amount)
3820
3851
  if price is not None:
3821
- request['orderPrice'] = self.price_to_precision(symbol, price)
3852
+ request['orderPrice'] = self.get_price(symbol, price)
3822
3853
  response = None
3823
3854
  if market['option']:
3824
3855
  response = await self.privatePostOptionUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
@@ -3833,11 +3864,11 @@ class bybit(Exchange, ImplicitAPI):
3833
3864
  if isStopOrder:
3834
3865
  request['orderFilter'] = 'StopOrder' if isStop else 'Order'
3835
3866
  if triggerPrice is not None:
3836
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3867
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3837
3868
  if stopLossPrice is not None:
3838
- request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
3869
+ request['stopLoss'] = self.get_price(symbol, stopLossPrice)
3839
3870
  if takeProfitPrice is not None:
3840
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
3871
+ request['takeProfit'] = self.get_price(symbol, takeProfitPrice)
3841
3872
  params = self.omit(params, ['stop', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
3842
3873
  response = await self.privatePostPerpetualUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
3843
3874
  #
@@ -3880,11 +3911,9 @@ class bybit(Exchange, ImplicitAPI):
3880
3911
  elif market['option']:
3881
3912
  request['category'] = 'option'
3882
3913
  if amount is not None:
3883
- request['qty'] = self.amount_to_precision(symbol, amount)
3914
+ request['qty'] = self.get_amount(symbol, amount)
3884
3915
  if price is not None:
3885
- request['price'] = self.price_to_precision(symbol, price)
3886
- if amount is not None:
3887
- request['qty'] = self.amount_to_precision(symbol, amount)
3916
+ request['price'] = self.get_price(symbol, self.number_to_string(price))
3888
3917
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
3889
3918
  stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
3890
3919
  takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
@@ -3897,20 +3926,20 @@ class bybit(Exchange, ImplicitAPI):
3897
3926
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3898
3927
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3899
3928
  if triggerPrice is not None:
3900
- triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.price_to_precision(symbol, triggerPrice)
3929
+ triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.get_price(symbol, triggerPrice)
3901
3930
  request['triggerPrice'] = triggerPriceRequest
3902
3931
  triggerBy = self.safe_string(params, 'triggerBy', 'LastPrice')
3903
3932
  request['triggerBy'] = triggerBy
3904
3933
  if isStopLoss or isTakeProfit:
3905
3934
  if isStopLoss:
3906
3935
  slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3907
- stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.price_to_precision(symbol, slTriggerPrice)
3936
+ stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.get_price(symbol, slTriggerPrice)
3908
3937
  request['stopLoss'] = stopLossRequest
3909
3938
  slTriggerBy = self.safe_string(params, 'slTriggerBy', 'LastPrice')
3910
3939
  request['slTriggerBy'] = slTriggerBy
3911
3940
  if isTakeProfit:
3912
3941
  tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3913
- takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.price_to_precision(symbol, tpTriggerPrice)
3942
+ takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.get_price(symbol, tpTriggerPrice)
3914
3943
  request['takeProfit'] = takeProfitRequest
3915
3944
  tpTriggerBy = self.safe_string(params, 'tpTriggerBy', 'LastPrice')
3916
3945
  request['tpTriggerBy'] = tpTriggerBy
@@ -3946,9 +3975,9 @@ class bybit(Exchange, ImplicitAPI):
3946
3975
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3947
3976
  """
3948
3977
  await self.load_markets()
3978
+ market = self.market(symbol)
3949
3979
  if symbol is None:
3950
3980
  raise ArgumentsRequired(self.id + ' editOrder() requires a symbol argument')
3951
- market = self.market(symbol)
3952
3981
  enableUnifiedMargin, enableUnifiedAccount = await self.is_unified_enabled()
3953
3982
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
3954
3983
  isUsdcSettled = market['settle'] == 'USDC'
@@ -5466,10 +5495,12 @@ class bybit(Exchange, ImplicitAPI):
5466
5495
  """
5467
5496
  fetch the history of changes, actions done by the user or operations that altered balance of the user
5468
5497
  :see: https://bybit-exchange.github.io/docs/v5/account/transaction-log
5498
+ :see: https://bybit-exchange.github.io/docs/v5/account/contract-transaction-log
5469
5499
  :param str code: unified currency code, default is None
5470
5500
  :param int [since]: timestamp in ms of the earliest ledger entry, default is None
5471
5501
  :param int [limit]: max number of ledger entrys to return, default is None
5472
5502
  :param dict [params]: extra parameters specific to the exchange API endpoint
5503
+ :param str [params.subType]: if inverse will use v5/account/contract-transaction-log
5473
5504
  :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
5474
5505
  """
5475
5506
  await self.load_markets()
@@ -5507,9 +5538,14 @@ class bybit(Exchange, ImplicitAPI):
5507
5538
  request[currencyKey] = currency['id']
5508
5539
  if limit is not None:
5509
5540
  request['limit'] = limit
5541
+ subType = None
5542
+ subType, params = self.handle_sub_type_and_params('fetchLedger', None, params)
5510
5543
  response = None
5511
5544
  if enableUnified[1]:
5512
- response = await self.privateGetV5AccountTransactionLog(self.extend(request, params))
5545
+ if subType == 'inverse':
5546
+ response = await self.privateGetV5AccountContractTransactionLog(self.extend(request, params))
5547
+ else:
5548
+ response = await self.privateGetV5AccountTransactionLog(self.extend(request, params))
5513
5549
  else:
5514
5550
  response = await self.privateGetV2PrivateWalletFundRecords(self.extend(request, params))
5515
5551
  #
@@ -1088,8 +1088,9 @@ class poloniex(Exchange, ImplicitAPI):
1088
1088
  market = self.safe_market(marketId, market, '_')
1089
1089
  symbol = market['symbol']
1090
1090
  resultingTrades = self.safe_value(order, 'resultingTrades')
1091
- if not isinstance(resultingTrades, list):
1092
- resultingTrades = self.safe_value(resultingTrades, self.safe_string(market, 'id', marketId))
1091
+ if resultingTrades is not None:
1092
+ if not isinstance(resultingTrades, list):
1093
+ resultingTrades = self.safe_value(resultingTrades, self.safe_string(market, 'id', marketId))
1093
1094
  price = self.safe_string_2(order, 'price', 'rate')
1094
1095
  amount = self.safe_string(order, 'quantity')
1095
1096
  filled = self.safe_string(order, 'filledQuantity')
@@ -249,6 +249,7 @@ class yobit(Exchange, ImplicitAPI):
249
249
  'XIN': 'XINCoin',
250
250
  'XMT': 'SummitCoin',
251
251
  'XRA': 'Ratecoin',
252
+ 'BCHN': 'BSV',
252
253
  },
253
254
  'options': {
254
255
  'maxUrlLength': 2048,
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.79'
7
+ __version__ = '4.3.81'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -1472,14 +1472,6 @@ class Exchange(object):
1472
1472
  return error
1473
1473
  return result
1474
1474
 
1475
- def check_address(self, address):
1476
- """Checks an address is not the same character repeated or an empty sequence"""
1477
- if address is None:
1478
- raise InvalidAddress(self.id + ' address is None')
1479
- if all(letter == address[0] for letter in address) or len(address) < self.minFundingAddressLength or ' ' in address:
1480
- raise InvalidAddress(self.id + ' address is invalid or has less than ' + str(self.minFundingAddressLength) + ' characters: "' + str(address) + '"')
1481
- return address
1482
-
1483
1475
  def precision_from_string(self, str):
1484
1476
  # support string formats like '1e-4'
1485
1477
  if 'e' in str or 'E' in str:
@@ -2236,44 +2228,38 @@ class Exchange(object):
2236
2228
  httpsProxy = None
2237
2229
  socksProxy = None
2238
2230
  # httpProxy
2239
- if self.value_is_defined(self.httpProxy):
2231
+ isHttpProxyDefined = self.value_is_defined(self.httpProxy)
2232
+ isHttp_proxy_defined = self.value_is_defined(self.http_proxy)
2233
+ if isHttpProxyDefined or isHttp_proxy_defined:
2240
2234
  usedProxies.append('httpProxy')
2241
- httpProxy = self.httpProxy
2242
- if self.value_is_defined(self.http_proxy):
2243
- usedProxies.append('http_proxy')
2244
- httpProxy = self.http_proxy
2245
- if self.httpProxyCallback is not None:
2235
+ httpProxy = self.httpProxy if isHttpProxyDefined else self.http_proxy
2236
+ ishttpProxyCallbackDefined = self.value_is_defined(self.httpProxyCallback)
2237
+ ishttp_proxy_callback_defined = self.value_is_defined(self.http_proxy_callback)
2238
+ if ishttpProxyCallbackDefined or ishttp_proxy_callback_defined:
2246
2239
  usedProxies.append('httpProxyCallback')
2247
- httpProxy = self.httpProxyCallback(url, method, headers, body)
2248
- if self.http_proxy_callback is not None:
2249
- usedProxies.append('http_proxy_callback')
2250
- httpProxy = self.http_proxy_callback(url, method, headers, body)
2240
+ httpProxy = self.httpProxyCallback(url, method, headers, body) if ishttpProxyCallbackDefined else self.http_proxy_callback(url, method, headers, body)
2251
2241
  # httpsProxy
2252
- if self.value_is_defined(self.httpsProxy):
2242
+ isHttpsProxyDefined = self.value_is_defined(self.httpsProxy)
2243
+ isHttps_proxy_defined = self.value_is_defined(self.https_proxy)
2244
+ if isHttpsProxyDefined or isHttps_proxy_defined:
2253
2245
  usedProxies.append('httpsProxy')
2254
- httpsProxy = self.httpsProxy
2255
- if self.value_is_defined(self.https_proxy):
2256
- usedProxies.append('https_proxy')
2257
- httpsProxy = self.https_proxy
2258
- if self.httpsProxyCallback is not None:
2246
+ httpsProxy = self.httpsProxy if isHttpsProxyDefined else self.https_proxy
2247
+ ishttpsProxyCallbackDefined = self.value_is_defined(self.httpsProxyCallback)
2248
+ ishttps_proxy_callback_defined = self.value_is_defined(self.https_proxy_callback)
2249
+ if ishttpsProxyCallbackDefined or ishttps_proxy_callback_defined:
2259
2250
  usedProxies.append('httpsProxyCallback')
2260
- httpsProxy = self.httpsProxyCallback(url, method, headers, body)
2261
- if self.https_proxy_callback is not None:
2262
- usedProxies.append('https_proxy_callback')
2263
- httpsProxy = self.https_proxy_callback(url, method, headers, body)
2251
+ httpsProxy = self.httpsProxyCallback(url, method, headers, body) if ishttpsProxyCallbackDefined else self.https_proxy_callback(url, method, headers, body)
2264
2252
  # socksProxy
2265
- if self.value_is_defined(self.socksProxy):
2253
+ isSocksProxyDefined = self.value_is_defined(self.socksProxy)
2254
+ isSocks_proxy_defined = self.value_is_defined(self.socks_proxy)
2255
+ if isSocksProxyDefined or isSocks_proxy_defined:
2266
2256
  usedProxies.append('socksProxy')
2267
- socksProxy = self.socksProxy
2268
- if self.value_is_defined(self.socks_proxy):
2269
- usedProxies.append('socks_proxy')
2270
- socksProxy = self.socks_proxy
2271
- if self.socksProxyCallback is not None:
2257
+ socksProxy = self.socksProxy if isSocksProxyDefined else self.socks_proxy
2258
+ issocksProxyCallbackDefined = self.value_is_defined(self.socksProxyCallback)
2259
+ issocks_proxy_callback_defined = self.value_is_defined(self.socks_proxy_callback)
2260
+ if issocksProxyCallbackDefined or issocks_proxy_callback_defined:
2272
2261
  usedProxies.append('socksProxyCallback')
2273
- socksProxy = self.socksProxyCallback(url, method, headers, body)
2274
- if self.socks_proxy_callback is not None:
2275
- usedProxies.append('socks_proxy_callback')
2276
- socksProxy = self.socks_proxy_callback(url, method, headers, body)
2262
+ socksProxy = self.socksProxyCallback(url, method, headers, body) if issocksProxyCallbackDefined else self.socks_proxy_callback(url, method, headers, body)
2277
2263
  # check
2278
2264
  length = len(usedProxies)
2279
2265
  if length > 1:
@@ -2318,6 +2304,16 @@ class Exchange(object):
2318
2304
  if proxyAgentSet and proxyUrlSet:
2319
2305
  raise InvalidProxySettings(self.id + ' you have multiple conflicting proxy settings, please use only one from : proxyUrl, httpProxy, httpsProxy, socksProxy')
2320
2306
 
2307
+ def check_address(self, address: Str = None):
2308
+ if address is None:
2309
+ raise InvalidAddress(self.id + ' address is None')
2310
+ # check the address is not the same letter like 'aaaaa' nor too short nor has a space
2311
+ uniqChars = (self.unique(self.string_to_chars_array(address)))
2312
+ length = len(uniqChars) # py transpiler trick
2313
+ if length == 1 or len(address) < self.minFundingAddressLength or address.find(' ') > -1:
2314
+ raise InvalidAddress(self.id + ' address is invalid or has less than ' + str(self.minFundingAddressLength) + ' characters: "' + str(address) + '"')
2315
+ return address
2316
+
2321
2317
  def find_message_hashes(self, client, element: str):
2322
2318
  result = []
2323
2319
  messageHashes = list(client.futures.keys())
@@ -4000,7 +3996,9 @@ class Exchange(object):
4000
3996
  ]
4001
3997
 
4002
3998
  def get_list_from_object_values(self, objects, key: IndexType):
4003
- newArray = self.to_array(objects)
3999
+ newArray = objects
4000
+ if not isinstance(objects, list):
4001
+ newArray = self.to_array(objects)
4004
4002
  results = []
4005
4003
  for i in range(0, len(newArray)):
4006
4004
  results.append(newArray[i][key])
ccxt/binance.py CHANGED
@@ -74,7 +74,7 @@ class binance(Exchange, ImplicitAPI):
74
74
  'createMarketSellOrderWithCost': True,
75
75
  'createOrder': True,
76
76
  'createOrders': True,
77
- 'createOrderWithTakeProfitAndStopLoss': True,
77
+ 'createOrderWithTakeProfitAndStopLoss': False,
78
78
  'createPostOnlyOrder': True,
79
79
  'createReduceOnlyOrder': True,
80
80
  'createStopLimitOrder': True,
ccxt/bitmart.py CHANGED
@@ -2364,8 +2364,6 @@ class bitmart(Exchange, ImplicitAPI):
2364
2364
  :see: https://developer-pro.bitmart.com/en/spot/#place-margin-order
2365
2365
  :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2366
2366
  :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2367
- :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2368
- :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2369
2367
  :see: https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2370
2368
  :param str symbol: unified symbol of the market to create an order in
2371
2369
  :param str type: 'market', 'limit' or 'trailing' for swap markets only
@@ -2496,6 +2494,7 @@ class bitmart(Exchange, ImplicitAPI):
2496
2494
  create a trade order
2497
2495
  :see: https://developer-pro.bitmart.com/en/futures/#submit-order-signed
2498
2496
  :see: https://developer-pro.bitmart.com/en/futures/#submit-plan-order-signed
2497
+ :see: https://developer-pro.bitmart.com/en/futuresv2/#submit-plan-order-signed
2499
2498
  :param str symbol: unified symbol of the market to create an order in
2500
2499
  :param str type: 'market', 'limit' or 'trailing'
2501
2500
  :param str side: 'buy' or 'sell'
@@ -2549,7 +2548,8 @@ class bitmart(Exchange, ImplicitAPI):
2549
2548
  request['activation_price'] = self.price_to_precision(symbol, trailingTriggerPrice)
2550
2549
  request['activation_price_type'] = self.safe_integer(params, 'activation_price_type', 1)
2551
2550
  if isTriggerOrder:
2552
- request['executive_price'] = self.price_to_precision(symbol, price)
2551
+ if isLimitOrder or price is not None:
2552
+ request['executive_price'] = self.price_to_precision(symbol, price)
2553
2553
  request['trigger_price'] = self.price_to_precision(symbol, triggerPrice)
2554
2554
  request['price_type'] = self.safe_integer(params, 'price_type', 1)
2555
2555
  if side == 'buy':
ccxt/bybit.py CHANGED
@@ -1209,6 +1209,18 @@ class bybit(Exchange, ImplicitAPI):
1209
1209
  optionType = self.safe_string(optionParts, 3)
1210
1210
  datetime = self.convert_expire_date(expiry)
1211
1211
  timestamp = self.parse8601(datetime)
1212
+ amountPrecision = None
1213
+ pricePrecision = None
1214
+ # hard coded amount and price precisions from fetchOptionMarkets
1215
+ if base == 'BTC':
1216
+ amountPrecision = self.parse_number('0.01')
1217
+ pricePrecision = self.parse_number('5')
1218
+ elif base == 'ETH':
1219
+ amountPrecision = self.parse_number('0.1')
1220
+ pricePrecision = self.parse_number('0.1')
1221
+ elif base == 'SOL':
1222
+ amountPrecision = self.parse_number('1')
1223
+ pricePrecision = self.parse_number('0.01')
1212
1224
  return {
1213
1225
  'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
1214
1226
  'symbol': base + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
@@ -1228,14 +1240,14 @@ class bybit(Exchange, ImplicitAPI):
1228
1240
  'option': True,
1229
1241
  'margin': False,
1230
1242
  'contract': True,
1231
- 'contractSize': None,
1243
+ 'contractSize': self.parse_number('1'),
1232
1244
  'expiry': timestamp,
1233
1245
  'expiryDatetime': datetime,
1234
1246
  'optionType': 'call' if (optionType == 'C') else 'put',
1235
1247
  'strike': self.parse_number(strike),
1236
1248
  'precision': {
1237
- 'amount': None,
1238
- 'price': None,
1249
+ 'amount': amountPrecision,
1250
+ 'price': pricePrecision,
1239
1251
  },
1240
1252
  'limits': {
1241
1253
  'amount': {
@@ -1270,6 +1282,30 @@ class bybit(Exchange, ImplicitAPI):
1270
1282
  return [type, params]
1271
1283
  return [subType, params]
1272
1284
 
1285
+ def get_amount(self, symbol: str, amount: float):
1286
+ # some markets like options might not have the precision available
1287
+ # and we shouldn't crash in those cases
1288
+ market = self.market(symbol)
1289
+ emptyPrecisionAmount = (market['precision']['amount'] is None)
1290
+ amountString = self.number_to_string(amount)
1291
+ if not emptyPrecisionAmount and (amountString != '0'):
1292
+ return self.amount_to_precision(symbol, amount)
1293
+ return amountString
1294
+
1295
+ def get_price(self, symbol: str, price: str):
1296
+ market = self.market(symbol)
1297
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1298
+ if not emptyPrecisionPrice:
1299
+ return self.price_to_precision(symbol, price)
1300
+ return price
1301
+
1302
+ def get_cost(self, symbol: str, cost: str):
1303
+ market = self.market(symbol)
1304
+ emptyPrecisionPrice = (market['precision']['price'] is None)
1305
+ if not emptyPrecisionPrice:
1306
+ return self.cost_to_precision(symbol, cost)
1307
+ return cost
1308
+
1273
1309
  def fetch_time(self, params={}):
1274
1310
  """
1275
1311
  fetches the current integer timestamp in milliseconds from the exchange server
@@ -1847,7 +1883,7 @@ class bybit(Exchange, ImplicitAPI):
1847
1883
  'inverse': None,
1848
1884
  'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
1849
1885
  'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
1850
- 'contractSize': self.safe_number(lotSizeFilter, 'minOrderQty'),
1886
+ 'contractSize': self.parse_number('1'),
1851
1887
  'expiry': expiry,
1852
1888
  'expiryDatetime': self.iso8601(expiry),
1853
1889
  'strike': self.parse_number(strike),
@@ -3473,24 +3509,26 @@ class bybit(Exchange, ImplicitAPI):
3473
3509
  isLimit = lowerCaseType == 'limit'
3474
3510
  isBuy = side == 'buy'
3475
3511
  isAlternativeEndpoint = defaultMethod == 'privatePostV5PositionTradingStop'
3512
+ amountString = self.get_amount(symbol, amount)
3513
+ priceString = self.get_price(symbol, self.number_to_string(price)) if (price is not None) else None
3476
3514
  if isTrailingAmountOrder or isAlternativeEndpoint:
3477
3515
  if isStopLoss or isTakeProfit or isTriggerOrder or market['spot']:
3478
3516
  raise InvalidOrder(self.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders')
3479
3517
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3480
3518
  if isStopLossTriggerOrder:
3481
- request['stopLoss'] = self.price_to_precision(symbol, stopLossTriggerPrice)
3519
+ request['stopLoss'] = self.get_price(symbol, stopLossTriggerPrice)
3482
3520
  if isLimit:
3483
3521
  request['tpslMode'] = 'Partial'
3484
3522
  request['slOrderType'] = 'Limit'
3485
- request['slLimitPrice'] = self.price_to_precision(symbol, price)
3486
- request['slSize'] = self.amount_to_precision(symbol, amount)
3523
+ request['slLimitPrice'] = priceString
3524
+ request['slSize'] = amountString
3487
3525
  elif isTakeProfitTriggerOrder:
3488
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitTriggerPrice)
3526
+ request['takeProfit'] = self.get_price(symbol, takeProfitTriggerPrice)
3489
3527
  if isLimit:
3490
3528
  request['tpslMode'] = 'Partial'
3491
3529
  request['tpOrderType'] = 'Limit'
3492
- request['tpLimitPrice'] = self.price_to_precision(symbol, price)
3493
- request['tpSize'] = self.amount_to_precision(symbol, amount)
3530
+ request['tpLimitPrice'] = priceString
3531
+ request['tpSize'] = amountString
3494
3532
  else:
3495
3533
  request['side'] = self.capitalize(side)
3496
3534
  request['orderType'] = self.capitalize(lowerCaseType)
@@ -3518,7 +3556,7 @@ class bybit(Exchange, ImplicitAPI):
3518
3556
  # mandatory field for options
3519
3557
  request['orderLinkId'] = self.uuid16()
3520
3558
  if isLimit:
3521
- request['price'] = self.price_to_precision(symbol, price)
3559
+ request['price'] = priceString
3522
3560
  if market['spot']:
3523
3561
  request['category'] = 'spot'
3524
3562
  elif market['linear']:
@@ -3539,14 +3577,12 @@ class bybit(Exchange, ImplicitAPI):
3539
3577
  if cost is not None:
3540
3578
  orderCost = cost
3541
3579
  else:
3542
- amountString = self.number_to_string(amount)
3543
- priceString = self.number_to_string(price)
3544
3580
  quoteAmount = Precise.string_mul(amountString, priceString)
3545
3581
  orderCost = quoteAmount
3546
- request['qty'] = self.cost_to_precision(symbol, orderCost)
3582
+ request['qty'] = self.get_cost(symbol, orderCost)
3547
3583
  else:
3548
3584
  request['marketUnit'] = 'baseCoin'
3549
- request['qty'] = self.amount_to_precision(symbol, amount)
3585
+ request['qty'] = amountString
3550
3586
  elif market['spot'] and (type == 'market') and (side == 'buy'):
3551
3587
  # classic accounts
3552
3588
  # for market buy it requires the amount of quote currency to spend
@@ -3556,22 +3592,17 @@ class bybit(Exchange, ImplicitAPI):
3556
3592
  if (price is None) and (cost is None):
3557
3593
  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 in the amount argument')
3558
3594
  else:
3559
- amountString = self.number_to_string(amount)
3560
- priceString = self.number_to_string(price)
3561
3595
  quoteAmount = Precise.string_mul(amountString, priceString)
3562
3596
  costRequest = cost if (cost is not None) else quoteAmount
3563
- request['qty'] = self.cost_to_precision(symbol, costRequest)
3597
+ request['qty'] = self.get_cost(symbol, costRequest)
3564
3598
  else:
3565
- request['qty'] = self.cost_to_precision(symbol, amount)
3599
+ request['qty'] = self.get_cost(symbol, self.number_to_string(amount))
3566
3600
  else:
3567
3601
  if not isTrailingAmountOrder and not isAlternativeEndpoint:
3568
- if market['option']:
3569
- request['qty'] = self.number_to_string(amount)
3570
- else:
3571
- request['qty'] = self.amount_to_precision(symbol, amount)
3602
+ request['qty'] = amountString
3572
3603
  if isTrailingAmountOrder:
3573
3604
  if trailingTriggerPrice is not None:
3574
- request['activePrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
3605
+ request['activePrice'] = self.get_price(symbol, trailingTriggerPrice)
3575
3606
  request['trailingStop'] = trailingAmount
3576
3607
  elif isTriggerOrder and not isAlternativeEndpoint:
3577
3608
  triggerDirection = self.safe_string(params, 'triggerDirection')
@@ -3584,32 +3615,32 @@ class bybit(Exchange, ImplicitAPI):
3584
3615
  raise ArgumentsRequired(self.id + ' stop/trigger orders require a triggerDirection parameter, either "above" or "below" to determine the direction of the trigger.')
3585
3616
  isAsending = ((triggerDirection == 'above') or (triggerDirection == '1'))
3586
3617
  request['triggerDirection'] = 1 if isAsending else 2
3587
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3618
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3588
3619
  elif (isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not isAlternativeEndpoint:
3589
3620
  if isBuy:
3590
3621
  request['triggerDirection'] = 1 if isStopLossTriggerOrder else 2
3591
3622
  else:
3592
3623
  request['triggerDirection'] = 2 if isStopLossTriggerOrder else 1
3593
3624
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3594
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3625
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3595
3626
  request['reduceOnly'] = True
3596
3627
  if (isStopLoss or isTakeProfit) and not isAlternativeEndpoint:
3597
3628
  if isStopLoss:
3598
3629
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3599
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3630
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3600
3631
  slLimitPrice = self.safe_value(stopLoss, 'price')
3601
3632
  if slLimitPrice is not None:
3602
3633
  request['tpslMode'] = 'Partial'
3603
3634
  request['slOrderType'] = 'Limit'
3604
- request['slLimitPrice'] = self.price_to_precision(symbol, slLimitPrice)
3635
+ request['slLimitPrice'] = self.get_price(symbol, slLimitPrice)
3605
3636
  if isTakeProfit:
3606
3637
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3607
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3638
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3608
3639
  tpLimitPrice = self.safe_value(takeProfit, 'price')
3609
3640
  if tpLimitPrice is not None:
3610
3641
  request['tpslMode'] = 'Partial'
3611
3642
  request['tpOrderType'] = 'Limit'
3612
- request['tpLimitPrice'] = self.price_to_precision(symbol, tpLimitPrice)
3643
+ request['tpLimitPrice'] = self.get_price(symbol, tpLimitPrice)
3613
3644
  params = self.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice'])
3614
3645
  return self.extend(request, params)
3615
3646
 
@@ -3709,7 +3740,7 @@ class bybit(Exchange, ImplicitAPI):
3709
3740
  'side': self.capitalize(side),
3710
3741
  'orderType': self.capitalize(lowerCaseType), # limit or market
3711
3742
  'timeInForce': 'GoodTillCancel', # ImmediateOrCancel, FillOrKill, PostOnly
3712
- 'orderQty': self.amount_to_precision(symbol, amount),
3743
+ 'orderQty': self.get_amount(symbol, amount),
3713
3744
  # 'takeProfit': 123.45, # take profit price, only take effect upon opening the position
3714
3745
  # 'stopLoss': 123.45, # stop loss price, only take effect upon opening the position
3715
3746
  # 'reduceOnly': False, # reduce only, required for linear orders
@@ -3727,7 +3758,7 @@ class bybit(Exchange, ImplicitAPI):
3727
3758
  isMarket = lowerCaseType == 'market'
3728
3759
  isLimit = lowerCaseType == 'limit'
3729
3760
  if isLimit is not None:
3730
- request['orderPrice'] = self.price_to_precision(symbol, price)
3761
+ request['orderPrice'] = self.get_price(symbol, self.number_to_string(price))
3731
3762
  exchangeSpecificParam = self.safe_string(params, 'time_in_force')
3732
3763
  timeInForce = self.safe_string_lower(params, 'timeInForce')
3733
3764
  postOnly = self.is_post_only(isMarket, exchangeSpecificParam == 'PostOnly', params)
@@ -3754,17 +3785,17 @@ class bybit(Exchange, ImplicitAPI):
3754
3785
  request['orderFilter'] = 'StopOrder'
3755
3786
  request['trigger_by'] = 'LastPrice'
3756
3787
  stopPx = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3757
- preciseStopPrice = self.price_to_precision(symbol, stopPx)
3788
+ preciseStopPrice = self.get_price(symbol, stopPx)
3758
3789
  request['triggerPrice'] = preciseStopPrice
3759
3790
  delta = self.number_to_string(market['precision']['price'])
3760
3791
  request['basePrice'] = Precise.string_sub(preciseStopPrice, delta) if isStopLossTriggerOrder else Precise.string_add(preciseStopPrice, delta)
3761
3792
  elif isStopLoss or isTakeProfit:
3762
3793
  if isStopLoss:
3763
3794
  slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3764
- request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
3795
+ request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
3765
3796
  if isTakeProfit:
3766
3797
  tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3767
- request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
3798
+ request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
3768
3799
  else:
3769
3800
  request['orderFilter'] = 'Order'
3770
3801
  clientOrderId = self.safe_string(params, 'clientOrderId')
@@ -3815,9 +3846,9 @@ class bybit(Exchange, ImplicitAPI):
3815
3846
  'orderId': id,
3816
3847
  }
3817
3848
  if amount is not None:
3818
- request['orderQty'] = self.amount_to_precision(symbol, amount)
3849
+ request['orderQty'] = self.get_amount(symbol, amount)
3819
3850
  if price is not None:
3820
- request['orderPrice'] = self.price_to_precision(symbol, price)
3851
+ request['orderPrice'] = self.get_price(symbol, price)
3821
3852
  response = None
3822
3853
  if market['option']:
3823
3854
  response = self.privatePostOptionUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
@@ -3832,11 +3863,11 @@ class bybit(Exchange, ImplicitAPI):
3832
3863
  if isStopOrder:
3833
3864
  request['orderFilter'] = 'StopOrder' if isStop else 'Order'
3834
3865
  if triggerPrice is not None:
3835
- request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
3866
+ request['triggerPrice'] = self.get_price(symbol, triggerPrice)
3836
3867
  if stopLossPrice is not None:
3837
- request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
3868
+ request['stopLoss'] = self.get_price(symbol, stopLossPrice)
3838
3869
  if takeProfitPrice is not None:
3839
- request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
3870
+ request['takeProfit'] = self.get_price(symbol, takeProfitPrice)
3840
3871
  params = self.omit(params, ['stop', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
3841
3872
  response = self.privatePostPerpetualUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
3842
3873
  #
@@ -3879,11 +3910,9 @@ class bybit(Exchange, ImplicitAPI):
3879
3910
  elif market['option']:
3880
3911
  request['category'] = 'option'
3881
3912
  if amount is not None:
3882
- request['qty'] = self.amount_to_precision(symbol, amount)
3913
+ request['qty'] = self.get_amount(symbol, amount)
3883
3914
  if price is not None:
3884
- request['price'] = self.price_to_precision(symbol, price)
3885
- if amount is not None:
3886
- request['qty'] = self.amount_to_precision(symbol, amount)
3915
+ request['price'] = self.get_price(symbol, self.number_to_string(price))
3887
3916
  triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
3888
3917
  stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
3889
3918
  takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
@@ -3896,20 +3925,20 @@ class bybit(Exchange, ImplicitAPI):
3896
3925
  if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
3897
3926
  triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
3898
3927
  if triggerPrice is not None:
3899
- triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.price_to_precision(symbol, triggerPrice)
3928
+ triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.get_price(symbol, triggerPrice)
3900
3929
  request['triggerPrice'] = triggerPriceRequest
3901
3930
  triggerBy = self.safe_string(params, 'triggerBy', 'LastPrice')
3902
3931
  request['triggerBy'] = triggerBy
3903
3932
  if isStopLoss or isTakeProfit:
3904
3933
  if isStopLoss:
3905
3934
  slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
3906
- stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.price_to_precision(symbol, slTriggerPrice)
3935
+ stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.get_price(symbol, slTriggerPrice)
3907
3936
  request['stopLoss'] = stopLossRequest
3908
3937
  slTriggerBy = self.safe_string(params, 'slTriggerBy', 'LastPrice')
3909
3938
  request['slTriggerBy'] = slTriggerBy
3910
3939
  if isTakeProfit:
3911
3940
  tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
3912
- takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.price_to_precision(symbol, tpTriggerPrice)
3941
+ takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.get_price(symbol, tpTriggerPrice)
3913
3942
  request['takeProfit'] = takeProfitRequest
3914
3943
  tpTriggerBy = self.safe_string(params, 'tpTriggerBy', 'LastPrice')
3915
3944
  request['tpTriggerBy'] = tpTriggerBy
@@ -3945,9 +3974,9 @@ class bybit(Exchange, ImplicitAPI):
3945
3974
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
3946
3975
  """
3947
3976
  self.load_markets()
3977
+ market = self.market(symbol)
3948
3978
  if symbol is None:
3949
3979
  raise ArgumentsRequired(self.id + ' editOrder() requires a symbol argument')
3950
- market = self.market(symbol)
3951
3980
  enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
3952
3981
  isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
3953
3982
  isUsdcSettled = market['settle'] == 'USDC'
@@ -5465,10 +5494,12 @@ class bybit(Exchange, ImplicitAPI):
5465
5494
  """
5466
5495
  fetch the history of changes, actions done by the user or operations that altered balance of the user
5467
5496
  :see: https://bybit-exchange.github.io/docs/v5/account/transaction-log
5497
+ :see: https://bybit-exchange.github.io/docs/v5/account/contract-transaction-log
5468
5498
  :param str code: unified currency code, default is None
5469
5499
  :param int [since]: timestamp in ms of the earliest ledger entry, default is None
5470
5500
  :param int [limit]: max number of ledger entrys to return, default is None
5471
5501
  :param dict [params]: extra parameters specific to the exchange API endpoint
5502
+ :param str [params.subType]: if inverse will use v5/account/contract-transaction-log
5472
5503
  :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger-structure>`
5473
5504
  """
5474
5505
  self.load_markets()
@@ -5506,9 +5537,14 @@ class bybit(Exchange, ImplicitAPI):
5506
5537
  request[currencyKey] = currency['id']
5507
5538
  if limit is not None:
5508
5539
  request['limit'] = limit
5540
+ subType = None
5541
+ subType, params = self.handle_sub_type_and_params('fetchLedger', None, params)
5509
5542
  response = None
5510
5543
  if enableUnified[1]:
5511
- response = self.privateGetV5AccountTransactionLog(self.extend(request, params))
5544
+ if subType == 'inverse':
5545
+ response = self.privateGetV5AccountContractTransactionLog(self.extend(request, params))
5546
+ else:
5547
+ response = self.privateGetV5AccountTransactionLog(self.extend(request, params))
5512
5548
  else:
5513
5549
  response = self.privateGetV2PrivateWalletFundRecords(self.extend(request, params))
5514
5550
  #
ccxt/poloniex.py CHANGED
@@ -1088,8 +1088,9 @@ class poloniex(Exchange, ImplicitAPI):
1088
1088
  market = self.safe_market(marketId, market, '_')
1089
1089
  symbol = market['symbol']
1090
1090
  resultingTrades = self.safe_value(order, 'resultingTrades')
1091
- if not isinstance(resultingTrades, list):
1092
- resultingTrades = self.safe_value(resultingTrades, self.safe_string(market, 'id', marketId))
1091
+ if resultingTrades is not None:
1092
+ if not isinstance(resultingTrades, list):
1093
+ resultingTrades = self.safe_value(resultingTrades, self.safe_string(market, 'id', marketId))
1093
1094
  price = self.safe_string_2(order, 'price', 'rate')
1094
1095
  amount = self.safe_string(order, 'quantity')
1095
1096
  filled = self.safe_string(order, 'filledQuantity')
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.79'
7
+ __version__ = '4.3.81'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/yobit.py CHANGED
@@ -248,6 +248,7 @@ class yobit(Exchange, ImplicitAPI):
248
248
  'XIN': 'XINCoin',
249
249
  'XMT': 'SummitCoin',
250
250
  'XRA': 'Ratecoin',
251
+ 'BCHN': 'BSV',
251
252
  },
252
253
  'options': {
253
254
  'maxUrlLength': 2048,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.3.79
3
+ Version: 4.3.81
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -270,13 +270,13 @@ console.log(version, Object.keys(exchanges));
270
270
 
271
271
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
272
272
 
273
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.79/dist/ccxt.browser.min.js
274
- * unpkg: https://unpkg.com/ccxt@4.3.79/dist/ccxt.browser.min.js
273
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.81/dist/ccxt.browser.min.js
274
+ * unpkg: https://unpkg.com/ccxt@4.3.81/dist/ccxt.browser.min.js
275
275
 
276
276
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
277
277
 
278
278
  ```HTML
279
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.79/dist/ccxt.browser.min.js"></script>
279
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.81/dist/ccxt.browser.min.js"></script>
280
280
  ```
281
281
 
282
282
  Creates a global `ccxt` object:
@@ -1,10 +1,10 @@
1
- ccxt/__init__.py,sha256=tAJaZfxn1AB_n0GrlbIE4sk7durLH-yY3LPYxsri9X4,16417
1
+ ccxt/__init__.py,sha256=oX0SQ2U9Ze2mY1h-d0RSJ9fMZ18zj60A-Jq2YbjWtrU,16417
2
2
  ccxt/ace.py,sha256=Gee4ymA83iAuBFm3J8NaTb7qmu9buV2trA676KCtSVg,42383
3
3
  ccxt/alpaca.py,sha256=HQuhQZSFGRlT-BaCUSEZmxpzYp6tll2zn63qn3gTmoU,47470
4
4
  ccxt/ascendex.py,sha256=4aEwibO_me6khr66z8JFqDBxe2gtFOWIFBE7ulBEJPs,151933
5
5
  ccxt/bequant.py,sha256=RBiAmaTbL35DgiV3Hl6uchLUd78V0z1T9riTlNsrpdc,1174
6
6
  ccxt/bigone.py,sha256=PBciIENMufQQ6cxukdze5hhQ5vFOqBtMHDfTwT4nUuY,93086
7
- ccxt/binance.py,sha256=GBzISXiK4cPK1menx5c4jMJG1TSvTvRC2qC9JB3NtcE,640181
7
+ ccxt/binance.py,sha256=bzrq8F5iCWbC1JnDkcmw63hJ3Toq4Mpv5V6bxMZGlC0,640182
8
8
  ccxt/binancecoinm.py,sha256=arFnEh8mErSyi23eVPWE4iwoT7PWQyxGGVJCKCy6UJY,1702
9
9
  ccxt/binanceus.py,sha256=hdcT4OnadcdFFFjF3GtM0nWv90jqojqwdVS3xWGuW40,9163
10
10
  ccxt/binanceusdm.py,sha256=bAPcJj5HLxoCdPolriM8sJpoTBwbV78vBTbKRmWhNP4,2632
@@ -19,7 +19,7 @@ ccxt/bitfinex2.py,sha256=m1PXKkM7tDf-ud-dmyqqYMF942IO3U0Du7AS3iVx-GU,160641
19
19
  ccxt/bitflyer.py,sha256=biQ8-J_HSb9_S6HE1LBDd6BGpIZSMxK5JyTZ3Xg1SdI,41683
20
20
  ccxt/bitget.py,sha256=ZQvtdW3pnv-LVHG3a1UwR72b-K8Fq-BZ-tu_haz-v60,424620
21
21
  ccxt/bithumb.py,sha256=8oTnFWi8Ai9fnm5FPXvNmaUAVJEOqYi-18VC23cWmXY,47935
22
- ccxt/bitmart.py,sha256=ZSy0ua1ymOfwrMLkWNrn6elI1c8RhMtTvKfENm_0VwA,211961
22
+ ccxt/bitmart.py,sha256=U-QuxcYA6rMGGuD6RiTo1Mx-39uWX1at4uCNkdJFaV0,211937
23
23
  ccxt/bitmex.py,sha256=oOFatIOxvXIPOdOeeVau-IdryOeYpdCtTPGxX05HA9A,126861
24
24
  ccxt/bitopro.py,sha256=0m104rrKQXuXa3dThHGgqq0leIIcdN_nQTR3a9YJLLM,69322
25
25
  ccxt/bitpanda.py,sha256=aiwPkx9lKbVzt4ggoYdq_mIbMGtg5ZtGl2yRHO5xyz8,471
@@ -35,7 +35,7 @@ ccxt/btcalpha.py,sha256=UcCCDZ_7EM-Q2tHU1IQPEA2DErFsLhrSfX-Oy-Q2uL4,36715
35
35
  ccxt/btcbox.py,sha256=9-P15L-OiZRzz0ZOtgO3bf73kuHro9u3NYf3QjeYv4k,27744
36
36
  ccxt/btcmarkets.py,sha256=0gMC0vvmuDJwcnllHMUZsQRV6QWA1-Cbq1N1F9rIUW8,52697
37
37
  ccxt/btcturk.py,sha256=bQ8sJq5iEj9oq2R17uDadPWKcnIQG8id5UmdlpHfFy8,36992
38
- ccxt/bybit.py,sha256=hAAoPAcxo6xBUygcQOjre7Z0EHyC3XlMB99K8WYgot4,417341
38
+ ccxt/bybit.py,sha256=0f9LMR-RZ1SCXdQRk9jovoPd9Q7dcsLJPs5GqSZhU_U,418689
39
39
  ccxt/cex.py,sha256=YQtARIBP7cY3y-AqRarEH_mVh7_ftt18jLebhpL3hxQ,70084
40
40
  ccxt/coinbase.py,sha256=3L5CDWhg4MQlDkdZnuJxxOjmsWEh-gnqcV4R6nCq7rg,217483
41
41
  ccxt/coinbaseadvanced.py,sha256=d5g6nRx-NCcCwZDdtp8FsI2D-pRjSvnAP9ISSKY_nCQ,538
@@ -91,7 +91,7 @@ ccxt/p2b.py,sha256=V_P8GTdb6SkeaVptVtc-LbjwUKUinfYFtO4nzmKG0N0,54333
91
91
  ccxt/paradex.py,sha256=-o0MAEgItYeo-juKgh2D-lnQIsjRKWMCupyMVPldsG8,85602
92
92
  ccxt/paymium.py,sha256=Xz-H66MQWQcQ1KJbciSMeremCD9kl2up_-IQUvBt22Y,24419
93
93
  ccxt/phemex.py,sha256=Xi0Cb6Zfe2_tZ0GZ_Iam_m2NEJ7fIDjHpOYc1vJ-VQk,223106
94
- ccxt/poloniex.py,sha256=Pqmr-FAeN5phqDZi1eIIGfc43Djey8cTHI0FCNTG-yw,102253
94
+ ccxt/poloniex.py,sha256=vaLhyTpZpzBvrrM6dCA_TVypLwLICXotixqiM27q-MA,102301
95
95
  ccxt/poloniexfutures.py,sha256=E0S38NKWPCKRM8RV-TJVxhhOj0vjF-9qR3cbtgmsIdk,78551
96
96
  ccxt/probit.py,sha256=MFA0bFG-xEx3ZDQIWebUKaP83mCjYKVcztk3e61Zx8Y,76165
97
97
  ccxt/timex.py,sha256=Un10iGNwAHPifpQftyXdUwoqS-10ho6ZIesz2Ts_Iqg,72068
@@ -105,7 +105,7 @@ ccxt/whitebit.py,sha256=fkM0Clt74bSiOJ_L-CehR2Gkn3v3kZksCQT0JCCG5rs,119340
105
105
  ccxt/woo.py,sha256=VSW2iQ6t9SCB5GYlRClLfUD468HNW2SOhM6uEo3A_e4,153142
106
106
  ccxt/woofipro.py,sha256=-qGU-7u764-744FvsmqVTvWXsuGxjlNCgJfAj_Yq6PA,115464
107
107
  ccxt/xt.py,sha256=a9f_Oq5KyDdytyCqW15jjXXdHGumbZwCqutt8cbfsPo,202616
108
- ccxt/yobit.py,sha256=q1oj-wf0VwNw3U7kC5AOyHRSxWVZO6s8xGscBJiSLhI,54553
108
+ ccxt/yobit.py,sha256=NeQpnOTzkjRKj5gVfI-riru5cNltagRH-DSfEEfByLw,54584
109
109
  ccxt/zaif.py,sha256=LgeOsvAo4ShQW1s-RidgUYK4DnRU-Dk0eJG0Ca6M_9U,28862
110
110
  ccxt/zonda.py,sha256=KZfv46H6YsVpTQLSt4BvMiGFQr0WRLmbUpeODVv21O0,81419
111
111
  ccxt/abstract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -218,13 +218,13 @@ ccxt/abstract/xt.py,sha256=JkWvsic3L2O968BCr9H5Wd5NIbRE9aTT2A-9WbAtl0c,27146
218
218
  ccxt/abstract/yobit.py,sha256=8ycfCO8ORFly9hc0Aa47sZyX4_ZKPXS9h9yJzI-uQ7Q,1339
219
219
  ccxt/abstract/zaif.py,sha256=m15WHdl3gYy0GOXNZ8NEH8eE7sVh8c0T_ITNuU8vXeU,3935
220
220
  ccxt/abstract/zonda.py,sha256=X-hCW0SdX3YKZWixDyW-O2211M58Rno8kKJ6quY7rw4,7183
221
- ccxt/async_support/__init__.py,sha256=rLl-FPXAop9p_ugze4JhDc4O25cLlgsAEoF1ctZdOi4,16230
221
+ ccxt/async_support/__init__.py,sha256=QynwkYy707CJqolFuuc7f_mx91VTyZ7s_c0Or9ve-Hc,16230
222
222
  ccxt/async_support/ace.py,sha256=zBmLUKH691a2BH1sPzlJPg-uO7lD6Ys92Rv8WSzNtoo,42607
223
223
  ccxt/async_support/alpaca.py,sha256=495vDvdF1IWlsh9QhUnMtkMuINdD0EzeFGlUVqCf8TE,47682
224
224
  ccxt/async_support/ascendex.py,sha256=LK259BdUqU0_STGRH6DmTgaR-7lXqFpZHFVACf2um5c,152721
225
225
  ccxt/async_support/bequant.py,sha256=1hTwHovo1bW1XTIc8ZKjvJ-Xg6LfmpGdzT7TepykaVM,1188
226
226
  ccxt/async_support/bigone.py,sha256=PZcs9u6FI6uAyJKiiNGIGDA-uainz4aKEOrC1Q6KIk4,93540
227
- ccxt/async_support/binance.py,sha256=327Da-aSBFpqO5cvhQR7CqKaSxbC_F8MnwDoYo_RLCQ,642903
227
+ ccxt/async_support/binance.py,sha256=nYDNOInWD94OIpVhzb_JOmjh2zDYaBaPIi_YUJXxq7Q,642904
228
228
  ccxt/async_support/binancecoinm.py,sha256=yeE73xG5UXD_X3VPul6DMGnV_mgJfWYskpas1BUDdCU,1740
229
229
  ccxt/async_support/binanceus.py,sha256=c-K3Tk7LaRJjmYdCx8vBOqsx01uXrtvt0PC2ekBiD0g,9177
230
230
  ccxt/async_support/binanceusdm.py,sha256=8ugRkx7vyYmn67wdkEEf2f-DFMGAoC4t09usKlPVNyw,2670
@@ -239,7 +239,7 @@ ccxt/async_support/bitfinex2.py,sha256=vTO61ELmw5d8A7xvmINff17pCWpoiIrVnc_RJzVic
239
239
  ccxt/async_support/bitflyer.py,sha256=hIrGMxaM78V1i-gHN2FRFAhI2aaLR21mPAoIE33fW70,41991
240
240
  ccxt/async_support/bitget.py,sha256=JloBQJwLONpLsNjzTxfabc-poDryi3xqwl66UNYi8DU,426244
241
241
  ccxt/async_support/bithumb.py,sha256=Q0Cx_cRKZRfdpBAhQyINm63Qw3M6BRYQRiF0UqYzfis,48214
242
- ccxt/async_support/bitmart.py,sha256=sNb0CAnVrxrlO2Htg4DCYJ12ti1eRjqtLczEj-fKM_g,212917
242
+ ccxt/async_support/bitmart.py,sha256=zIkhlHwCfAXP7Uli6PKZaZmsJV-CI8qFsKXqYo1XUxY,212893
243
243
  ccxt/async_support/bitmex.py,sha256=qSKH_dXDtpY5BUrLUbESI3a3WQhBFrc1ucv1N5GDuIU,127439
244
244
  ccxt/async_support/bitopro.py,sha256=HHESL0hiE0Rc0GRhFeIKnTs-eBzHEtOqqECANTSp0e0,69726
245
245
  ccxt/async_support/bitpanda.py,sha256=2k3URBWrpnh2xHa7JiYenI7_4MW5UeOPGzetlmRkR4U,485
@@ -255,7 +255,7 @@ ccxt/async_support/btcalpha.py,sha256=DgzrJ6cczUCDZr-QLUxMpazeudEFdQ_OzXiQiJM4Hb
255
255
  ccxt/async_support/btcbox.py,sha256=FGIj8il6VZL56_dDYsAMwp4DpdKNt_vbMXV6VZ2boCI,27968
256
256
  ccxt/async_support/btcmarkets.py,sha256=x1-s5uVioHyvNJoBxhxP8eUUslTDwQnZMU0FWfu1Fd4,53047
257
257
  ccxt/async_support/btcturk.py,sha256=P3bg0XG0sAi-8ge9ZFzQqZHsoGOGfxBjkhIDo4VPSK4,37210
258
- ccxt/async_support/bybit.py,sha256=hb6SpCChGiPdASz9BRXMXpoh5CfYe3tJ0-DW0jqyjDc,419211
258
+ ccxt/async_support/bybit.py,sha256=ALkt2mzwRFL3jE1BjW4LZonhwWsBjLF18HPB9VIeDRI,420565
259
259
  ccxt/async_support/cex.py,sha256=5KZ9qt4WsUAkH2rkHn7zW7SwlB9FumruLELdKF4LFoE,70434
260
260
  ccxt/async_support/coinbase.py,sha256=Ch_hFo2zj0qp4kuDUnebGD16pUeKs6h3HJxs5Fdpkco,218637
261
261
  ccxt/async_support/coinbaseadvanced.py,sha256=Kupwnuxiu_qTjwCNV2asacoDUNFQvcaHNAznUJPhdQs,552
@@ -311,7 +311,7 @@ ccxt/async_support/p2b.py,sha256=aU_69L8hyfZEQ_yFJb6UoR_l0EbaeCTRgNvdDtk4QPs,545
311
311
  ccxt/async_support/paradex.py,sha256=iN1obpvPvLikj30KiE4I7BGlBVBRLHpHifEH8vn8JdY,86210
312
312
  ccxt/async_support/paymium.py,sha256=GIAgyOjR11o1pfq8om4Pwr68jMkLoEwEz7sB8lIDMI0,24607
313
313
  ccxt/async_support/phemex.py,sha256=Xfa8kxrN6mEr6BGLNDnquGhMq0sk42qJ7P5Ckmb-0BE,223924
314
- ccxt/async_support/poloniex.py,sha256=m5zaJRKARuSmk05lKbaSlPOlcj4s9KsA5BX4aEmil8I,102801
314
+ ccxt/async_support/poloniex.py,sha256=hYmiGQfwKyYcaPp1Q1Qa4gPP0TaqJrG2367y-q0WxXE,102849
315
315
  ccxt/async_support/poloniexfutures.py,sha256=iXEtcjHZBTEhgwkp8xbIqxObZf-OhfUr2yVwq5WlsMg,78937
316
316
  ccxt/async_support/probit.py,sha256=8XCtYbAIIQNjfdLfMVwjaJ9vM_7QWnEQ86yYZYPlS8M,76557
317
317
  ccxt/async_support/timex.py,sha256=vRHjqc-6uMgZTY-sFTBApU_QBnrUri8gaHPNw_Na3Jo,72430
@@ -325,11 +325,11 @@ ccxt/async_support/whitebit.py,sha256=haF5nFYGuJzkplHBIyLLDJ6N3ThIDPpgjeI3S-TYs9
325
325
  ccxt/async_support/woo.py,sha256=uaNh3timNm6_DNhiOn5l4Za4wagj4AhlxkDh4Fbhxfk,154110
326
326
  ccxt/async_support/woofipro.py,sha256=wLOSXkKdEqpw4q-9uzM67wFdhWDp0Li1wb8nPHmBwT4,116144
327
327
  ccxt/async_support/xt.py,sha256=_U-r4Gp0oBCOE6Ngo98Sn_Q6tr_81CUDDSliF0FMezE,203770
328
- ccxt/async_support/yobit.py,sha256=JuH_yClCl_cd5L-BMTt3MPAvIF61Wpqc3W7H-fno6Hs,54881
328
+ ccxt/async_support/yobit.py,sha256=GQhvYrsGHQrVdTrNHQxx9isEGqUABexlllzao9HL3f8,54912
329
329
  ccxt/async_support/zaif.py,sha256=-ZTr8M2JaIRCL90VrbCDXBMAsZwbiwsFChSQ2rWODuQ,29044
330
330
  ccxt/async_support/zonda.py,sha256=jncr6Wg12S72CTpu6mCKCse1pm1f8oefVQurQSrFvP0,81733
331
331
  ccxt/async_support/base/__init__.py,sha256=aVYSsFi--b4InRs9zDN_wtCpj8odosAB726JdUHavrk,67
332
- ccxt/async_support/base/exchange.py,sha256=iY0eUbebQbq2ihd4RfgRLzwB7umyHXGL4gt9H53Jq1k,110799
332
+ ccxt/async_support/base/exchange.py,sha256=c95NbqMjGCTRAr31pdj438saYwJD9MsUZqH-Ko49PoA,110799
333
333
  ccxt/async_support/base/throttler.py,sha256=tvDVcdRUVYi8fZRlEcnqtgzcgB_KMUMRs5Pu8tuU-tU,1847
334
334
  ccxt/async_support/base/ws/__init__.py,sha256=uockzpLuwntKGZbs5EOWFe-Zg-k6Cj7GhNJLc_RX0so,1791
335
335
  ccxt/async_support/base/ws/aiohttp_client.py,sha256=5IEiT0elWI9a7Vr-KV0jgmlbpLJWBzIlrLaCkTKGaqY,5752
@@ -343,10 +343,10 @@ ccxt/async_support/base/ws/order_book_side.py,sha256=GhnGUt78pJ-AYL_Dq9produGjmB
343
343
  ccxt/base/__init__.py,sha256=eTx1OE3HJjspFUQjGm6LBhaQiMKJnXjkdP-JUXknyQ0,1320
344
344
  ccxt/base/decimal_to_precision.py,sha256=fgWRBzRTtsf3r2INyS4f7WHlzgjB5YM1ekiwqD21aac,6634
345
345
  ccxt/base/errors.py,sha256=tosnf1tDaBn4YMCbWVNWyDYzqft-ImVtyjqJb6q83Y4,4369
346
- ccxt/base/exchange.py,sha256=uZzip0WRIl6DATaZW2EqdjMZMfOdvSTx-_mZMBCmLRg,295244
346
+ ccxt/base/exchange.py,sha256=ahEDjXHHBtn78_S5B1razurc-8AcS9bQTBysVHBhOCI,295904
347
347
  ccxt/base/precise.py,sha256=koce64Yrp6vFbGijJtUt-QQ6XhJgeGTCksZ871FPp_A,8886
348
348
  ccxt/base/types.py,sha256=TaP_RElKjGEZWuzyp4o4u2YhREyTG3rUeVT6gDffY9A,9613
349
- ccxt/pro/__init__.py,sha256=PFwYT1Nu4nc3PxY3q0CF_fiLxXDMG2a6VuV72sdk1w8,7608
349
+ ccxt/pro/__init__.py,sha256=yBtRJJWZ4Ji03DLCU4G4sFPTVe4xLt4_He0yUqqhTdM,7608
350
350
  ccxt/pro/alpaca.py,sha256=xh1yg1Ok-Zh_Mfx-MBjNrfJDs6MUU0exFfEj3GuQPC4,27631
351
351
  ccxt/pro/ascendex.py,sha256=181FIeztchLqGmgecRJEN8F8xEM45D5aMKhC-5nuNfU,35467
352
352
  ccxt/pro/bequant.py,sha256=33OEUWBi4D9-2w8CmkwN3aF1qS-AlLqX3pxrWwNbXPY,1552
@@ -648,8 +648,8 @@ ccxt/test/tests_async.py,sha256=NShOLO2-HzYsh07U7aiUGssiv-AZ_p88h-NuQub9OKU,8468
648
648
  ccxt/test/tests_helpers.py,sha256=xhOILoZ_x3RSfQjtKt6AQlkp9DkOtpTQe8GAUUZoM6s,10069
649
649
  ccxt/test/tests_init.py,sha256=eVwwUHujX9t4rjgo4TqEeg7DDhR1Hb_e2SJN8NVGyl0,998
650
650
  ccxt/test/tests_sync.py,sha256=6Arr2TcJpNg9eEpH_JQeBbLzaMPlb94J1P11HGlbpPg,83761
651
- ccxt-4.3.79.dist-info/LICENSE.txt,sha256=EIb9221AhMHV7xF1_55STFdKTFsnJVJYkRpY2Lnvo5w,1068
652
- ccxt-4.3.79.dist-info/METADATA,sha256=i9YlqcIIvRbr7EZrgP7yfB7Ah9rd2cgW2Zg2J02WFd0,116642
653
- ccxt-4.3.79.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
654
- ccxt-4.3.79.dist-info/top_level.txt,sha256=CkQDuCTDKNcImPV60t36G6MdYfxsAPNiSaEwifVoVMo,5
655
- ccxt-4.3.79.dist-info/RECORD,,
651
+ ccxt-4.3.81.dist-info/LICENSE.txt,sha256=EIb9221AhMHV7xF1_55STFdKTFsnJVJYkRpY2Lnvo5w,1068
652
+ ccxt-4.3.81.dist-info/METADATA,sha256=gQiQeuBWzcSMq7fHSGHmhk87kJToVPIL3K0WCUp27GU,116642
653
+ ccxt-4.3.81.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
654
+ ccxt-4.3.81.dist-info/top_level.txt,sha256=CkQDuCTDKNcImPV60t36G6MdYfxsAPNiSaEwifVoVMo,5
655
+ ccxt-4.3.81.dist-info/RECORD,,
File without changes