ccxt 4.4.48__py2.py3-none-any.whl → 4.4.50__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 +1 -1
- ccxt/abstract/binance.py +1 -0
- ccxt/abstract/binancecoinm.py +1 -0
- ccxt/abstract/binanceus.py +1 -0
- ccxt/abstract/binanceusdm.py +1 -0
- ccxt/alpaca.py +62 -1
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/alpaca.py +62 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +8 -4
- ccxt/async_support/bingx.py +73 -29
- ccxt/async_support/bitget.py +12 -10
- ccxt/async_support/blofin.py +1 -1
- ccxt/async_support/coinex.py +3 -3
- ccxt/async_support/coinsph.py +17 -8
- ccxt/async_support/deribit.py +82 -0
- ccxt/async_support/digifinex.py +125 -10
- ccxt/async_support/ellipx.py +61 -0
- ccxt/async_support/exmo.py +58 -0
- ccxt/async_support/hitbtc.py +99 -0
- ccxt/async_support/hollaex.py +85 -16
- ccxt/async_support/huobijp.py +73 -0
- ccxt/async_support/hyperliquid.py +22 -1
- ccxt/async_support/idex.py +71 -0
- ccxt/async_support/independentreserve.py +64 -0
- ccxt/async_support/indodax.py +61 -0
- ccxt/async_support/kucoin.py +47 -67
- ccxt/async_support/kuna.py +60 -1
- ccxt/async_support/latoken.py +64 -0
- ccxt/async_support/lbank.py +70 -0
- ccxt/async_support/luno.py +73 -0
- ccxt/async_support/lykke.py +64 -0
- ccxt/async_support/mercado.py +65 -0
- ccxt/async_support/mexc.py +4 -3
- ccxt/async_support/myokx.py +10 -0
- ccxt/async_support/ndax.py +71 -0
- ccxt/async_support/novadax.py +74 -0
- ccxt/async_support/oceanex.py +69 -0
- ccxt/async_support/okcoin.py +92 -7
- ccxt/async_support/onetrading.py +66 -0
- ccxt/async_support/oxfun.py +66 -0
- ccxt/async_support/p2b.py +63 -1
- ccxt/async_support/paradex.py +68 -0
- ccxt/async_support/paymium.py +42 -0
- ccxt/async_support/probit.py +68 -1
- ccxt/async_support/timex.py +67 -0
- ccxt/async_support/tokocrypto.py +81 -4
- ccxt/async_support/tradeogre.py +58 -1
- ccxt/async_support/whitebit.py +10 -4
- ccxt/base/exchange.py +62 -1
- ccxt/binance.py +8 -4
- ccxt/bingx.py +73 -29
- ccxt/bitget.py +12 -10
- ccxt/blofin.py +1 -1
- ccxt/coinex.py +3 -3
- ccxt/coinsph.py +17 -8
- ccxt/deribit.py +82 -0
- ccxt/digifinex.py +125 -10
- ccxt/ellipx.py +61 -0
- ccxt/exmo.py +58 -0
- ccxt/hitbtc.py +99 -0
- ccxt/hollaex.py +85 -16
- ccxt/huobijp.py +73 -0
- ccxt/hyperliquid.py +22 -1
- ccxt/idex.py +71 -0
- ccxt/independentreserve.py +64 -0
- ccxt/indodax.py +61 -0
- ccxt/kucoin.py +47 -67
- ccxt/kuna.py +60 -1
- ccxt/latoken.py +64 -0
- ccxt/lbank.py +70 -0
- ccxt/luno.py +73 -0
- ccxt/lykke.py +64 -0
- ccxt/mercado.py +65 -0
- ccxt/mexc.py +4 -3
- ccxt/myokx.py +10 -0
- ccxt/ndax.py +71 -0
- ccxt/novadax.py +74 -0
- ccxt/oceanex.py +69 -0
- ccxt/okcoin.py +92 -7
- ccxt/onetrading.py +66 -0
- ccxt/oxfun.py +66 -0
- ccxt/p2b.py +63 -1
- ccxt/paradex.py +68 -0
- ccxt/paymium.py +42 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitmart.py +5 -0
- ccxt/probit.py +68 -1
- ccxt/timex.py +67 -0
- ccxt/tokocrypto.py +81 -4
- ccxt/tradeogre.py +58 -1
- ccxt/whitebit.py +10 -4
- {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/METADATA +4 -4
- {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/RECORD +97 -97
- {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/WHEEL +0 -0
- {ccxt-4.4.48.dist-info → ccxt-4.4.50.dist-info}/top_level.txt +0 -0
ccxt/async_support/tokocrypto.py
CHANGED
@@ -619,6 +619,79 @@ class tokocrypto(Exchange, ImplicitAPI):
|
|
619
619
|
'MAX_POSITION': InvalidOrder, # {"code":-2010,"msg":"Filter failure: MAX_POSITION"}
|
620
620
|
},
|
621
621
|
},
|
622
|
+
'features': {
|
623
|
+
'spot': {
|
624
|
+
'sandbox': False,
|
625
|
+
'createOrder': {
|
626
|
+
'marginMode': False,
|
627
|
+
'triggerPrice': True,
|
628
|
+
'triggerDirection': False,
|
629
|
+
'triggerPriceType': None,
|
630
|
+
'stopLossPrice': False, # todo
|
631
|
+
'takeProfitPrice': False, # todo
|
632
|
+
'attachedStopLossTakeProfit': None,
|
633
|
+
'timeInForce': {
|
634
|
+
'IOC': True,
|
635
|
+
'FOK': True,
|
636
|
+
'PO': True,
|
637
|
+
'GTD': False,
|
638
|
+
},
|
639
|
+
'hedged': False,
|
640
|
+
'trailing': False,
|
641
|
+
'leverage': False,
|
642
|
+
'marketBuyByCost': True,
|
643
|
+
'marketBuyRequiresPrice': True,
|
644
|
+
'selfTradePrevention': True, # todo
|
645
|
+
'iceberg': True, # todo
|
646
|
+
},
|
647
|
+
'createOrders': None,
|
648
|
+
'fetchMyTrades': {
|
649
|
+
'marginMode': False,
|
650
|
+
'limit': 1000,
|
651
|
+
'daysBack': 100000, # todo
|
652
|
+
'untilDays': 100000, # todo
|
653
|
+
},
|
654
|
+
'fetchOrder': {
|
655
|
+
'marginMode': False,
|
656
|
+
'trigger': False,
|
657
|
+
'trailing': False,
|
658
|
+
},
|
659
|
+
'fetchOpenOrders': {
|
660
|
+
'marginMode': False,
|
661
|
+
'limit': 1000,
|
662
|
+
'trigger': False,
|
663
|
+
'trailing': False,
|
664
|
+
},
|
665
|
+
'fetchOrders': {
|
666
|
+
'marginMode': False,
|
667
|
+
'limit': 1000,
|
668
|
+
'daysBack': 100000,
|
669
|
+
'untilDays': 100000,
|
670
|
+
'trigger': False,
|
671
|
+
'trailing': False,
|
672
|
+
},
|
673
|
+
'fetchClosedOrders': {
|
674
|
+
'marginMode': False,
|
675
|
+
'limit': 1000,
|
676
|
+
'daysBack': 100000, # todo
|
677
|
+
'daysBackCanceled': 1, # todo
|
678
|
+
'untilDays': 100000, # todo
|
679
|
+
'trigger': False,
|
680
|
+
'trailing': False,
|
681
|
+
},
|
682
|
+
'fetchOHLCV': {
|
683
|
+
'limit': 1000,
|
684
|
+
},
|
685
|
+
},
|
686
|
+
'swap': {
|
687
|
+
'linear': None,
|
688
|
+
'inverse': None,
|
689
|
+
},
|
690
|
+
'future': {
|
691
|
+
'linear': None,
|
692
|
+
'inverse': None,
|
693
|
+
},
|
694
|
+
},
|
622
695
|
})
|
623
696
|
|
624
697
|
def nonce(self):
|
@@ -635,9 +708,14 @@ class tokocrypto(Exchange, ImplicitAPI):
|
|
635
708
|
"""
|
636
709
|
response = await self.publicGetOpenV1CommonTime(params)
|
637
710
|
#
|
711
|
+
# {
|
712
|
+
# "code": 0,
|
713
|
+
# "msg": "Success",
|
714
|
+
# "data": null,
|
715
|
+
# "timestamp": 1737378074159
|
716
|
+
# }
|
638
717
|
#
|
639
|
-
|
640
|
-
return self.safe_integer(response, 'serverTime')
|
718
|
+
return self.safe_integer(response, 'timestamp')
|
641
719
|
|
642
720
|
async def fetch_markets(self, params={}) -> List[Market]:
|
643
721
|
"""
|
@@ -1575,7 +1653,6 @@ class tokocrypto(Exchange, ImplicitAPI):
|
|
1575
1653
|
create a trade order
|
1576
1654
|
|
1577
1655
|
https://www.tokocrypto.com/apidocs/#new-order--signed
|
1578
|
-
https://www.tokocrypto.com/apidocs/#account-trade-list-signed
|
1579
1656
|
|
1580
1657
|
:param str symbol: unified symbol of the market to create an order in
|
1581
1658
|
:param str type: 'market' or 'limit'
|
@@ -1733,7 +1810,7 @@ class tokocrypto(Exchange, ImplicitAPI):
|
|
1733
1810
|
async def fetch_order(self, id: str, symbol: Str = None, params={}):
|
1734
1811
|
"""
|
1735
1812
|
|
1736
|
-
https://www.tokocrypto.com/apidocs/#
|
1813
|
+
https://www.tokocrypto.com/apidocs/#query-order-signed
|
1737
1814
|
|
1738
1815
|
fetches information on an order made by the user
|
1739
1816
|
:param str id: order id
|
ccxt/async_support/tradeogre.py
CHANGED
@@ -164,6 +164,57 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
164
164
|
},
|
165
165
|
'options': {
|
166
166
|
},
|
167
|
+
'features': {
|
168
|
+
'spot': {
|
169
|
+
'sandbox': False,
|
170
|
+
'createOrder': {
|
171
|
+
'marginMode': False,
|
172
|
+
'triggerPrice': False,
|
173
|
+
'triggerDirection': False,
|
174
|
+
'triggerPriceType': None,
|
175
|
+
'stopLossPrice': False,
|
176
|
+
'takeProfitPrice': False,
|
177
|
+
'attachedStopLossTakeProfit': None,
|
178
|
+
'timeInForce': {
|
179
|
+
'IOC': False,
|
180
|
+
'FOK': False,
|
181
|
+
'PO': False,
|
182
|
+
'GTD': False,
|
183
|
+
},
|
184
|
+
'hedged': False,
|
185
|
+
'trailing': False,
|
186
|
+
'leverage': False,
|
187
|
+
'marketBuyByCost': False,
|
188
|
+
'marketBuyRequiresPrice': False,
|
189
|
+
'selfTradePrevention': False,
|
190
|
+
'iceberg': False,
|
191
|
+
},
|
192
|
+
'createOrders': None,
|
193
|
+
'fetchMyTrades': None,
|
194
|
+
'fetchOrder': {
|
195
|
+
'marginMode': False,
|
196
|
+
'trigger': False,
|
197
|
+
'trailing': False,
|
198
|
+
},
|
199
|
+
'fetchOpenOrders': {
|
200
|
+
'marginMode': False,
|
201
|
+
'limit': None,
|
202
|
+
'trigger': False,
|
203
|
+
'trailing': False,
|
204
|
+
},
|
205
|
+
'fetchOrders': None,
|
206
|
+
'fetchClosedOrders': None,
|
207
|
+
'fetchOHLCV': None, # todo
|
208
|
+
},
|
209
|
+
'swap': {
|
210
|
+
'linear': None,
|
211
|
+
'inverse': None,
|
212
|
+
},
|
213
|
+
'future': {
|
214
|
+
'linear': None,
|
215
|
+
'inverse': None,
|
216
|
+
},
|
217
|
+
},
|
167
218
|
})
|
168
219
|
|
169
220
|
async def fetch_markets(self, params={}) -> List[Market]:
|
@@ -442,6 +493,9 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
442
493
|
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
443
494
|
"""
|
444
495
|
create a trade order
|
496
|
+
|
497
|
+
https://tradeogre.com/help/api#:~:text=u%20%27%7Bpublic%7D%3A%7Bprivate%7D%27-,Submit%20Buy%20Order
|
498
|
+
|
445
499
|
:param str symbol: unified symbol of the market to create an order in
|
446
500
|
:param str type: must be 'limit'
|
447
501
|
:param str side: 'buy' or 'sell'
|
@@ -499,6 +553,9 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
499
553
|
async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
500
554
|
"""
|
501
555
|
fetch all unfilled currently open orders
|
556
|
+
|
557
|
+
https://tradeogre.com/help/api#:~:text=%7B%22success%22%3Atrue%7D-,Get%20Orders,-Method%20(POST)
|
558
|
+
|
502
559
|
:param str symbol: unified market symbol of the market orders were made in
|
503
560
|
:param int [since]: the earliest time in ms to fetch orders for
|
504
561
|
:param int [limit]: the maximum number of order structures to retrieve
|
@@ -519,7 +576,7 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
519
576
|
"""
|
520
577
|
fetches information on an order made by the user
|
521
578
|
|
522
|
-
https://
|
579
|
+
https://tradeogre.com/help/api#:~:text=market%22%3A%22XMR%2DBTC%22%7D%5D-,Get%20Order,-Method%20(GET)
|
523
580
|
|
524
581
|
:param str id: order id
|
525
582
|
:param str symbol: unified symbol of the market the order was made in
|
ccxt/async_support/whitebit.py
CHANGED
@@ -272,6 +272,8 @@ class whitebit(Exchange, ImplicitAPI):
|
|
272
272
|
},
|
273
273
|
},
|
274
274
|
'options': {
|
275
|
+
'timeDifference': 0, # the difference between system clock and exchange clock
|
276
|
+
'adjustForTimeDifference': False, # controls the adjustment logic upon instantiation
|
275
277
|
'fiatCurrencies': ['EUR', 'USD', 'RUB', 'UAH'],
|
276
278
|
'fetchBalance': {
|
277
279
|
'account': 'spot',
|
@@ -328,6 +330,8 @@ class whitebit(Exchange, ImplicitAPI):
|
|
328
330
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
329
331
|
:returns dict[]: an array of objects representing market data
|
330
332
|
"""
|
333
|
+
if self.options['adjustForTimeDifference']:
|
334
|
+
await self.load_time_difference()
|
331
335
|
markets = await self.v4PublicGetMarkets()
|
332
336
|
#
|
333
337
|
# [
|
@@ -1227,7 +1231,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
1227
1231
|
response = await self.v4PublicGetTime(params)
|
1228
1232
|
#
|
1229
1233
|
# {
|
1230
|
-
# "time":
|
1234
|
+
# "time":1737380046
|
1231
1235
|
# }
|
1232
1236
|
#
|
1233
1237
|
return self.safe_integer(response, 'time')
|
@@ -2514,7 +2518,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
2514
2518
|
return self.in_array(currency, fiatCurrencies)
|
2515
2519
|
|
2516
2520
|
def nonce(self):
|
2517
|
-
return self.milliseconds()
|
2521
|
+
return self.milliseconds() - self.options['timeDifference']
|
2518
2522
|
|
2519
2523
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
2520
2524
|
query = self.omit(params, self.extract_params(path))
|
@@ -2527,10 +2531,12 @@ class whitebit(Exchange, ImplicitAPI):
|
|
2527
2531
|
url += '?' + self.urlencode(query)
|
2528
2532
|
if accessibility == 'private':
|
2529
2533
|
self.check_required_credentials()
|
2530
|
-
nonce =
|
2534
|
+
nonce = self.nonce()
|
2535
|
+
timestamp = self.parse_to_int(nonce / 1000)
|
2536
|
+
timestampString = str(timestamp)
|
2531
2537
|
secret = self.encode(self.secret)
|
2532
2538
|
request = '/' + 'api' + '/' + version + pathWithParams
|
2533
|
-
body = self.json(self.extend({'request': request, 'nonce':
|
2539
|
+
body = self.json(self.extend({'request': request, 'nonce': timestampString}, params))
|
2534
2540
|
payload = self.string_to_base64(body)
|
2535
2541
|
signature = self.hmac(self.encode(payload), secret, hashlib.sha512)
|
2536
2542
|
headers = {
|
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.4.
|
7
|
+
__version__ = '4.4.50'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -2876,6 +2876,67 @@ class Exchange(object):
|
|
2876
2876
|
}
|
2877
2877
|
|
2878
2878
|
def safe_currency_structure(self, currency: object):
|
2879
|
+
# derive data from networks: deposit, withdraw, active, fee, limits, precision
|
2880
|
+
networks = self.safe_dict(currency, 'networks', {})
|
2881
|
+
keys = list(networks.keys())
|
2882
|
+
length = len(keys)
|
2883
|
+
if length != 0:
|
2884
|
+
for i in range(0, length):
|
2885
|
+
network = networks[keys[i]]
|
2886
|
+
deposit = self.safe_bool(network, 'deposit')
|
2887
|
+
if currency['deposit'] is None or deposit:
|
2888
|
+
currency['deposit'] = deposit
|
2889
|
+
withdraw = self.safe_bool(network, 'withdraw')
|
2890
|
+
if currency['withdraw'] is None or withdraw:
|
2891
|
+
currency['withdraw'] = withdraw
|
2892
|
+
active = self.safe_bool(network, 'active')
|
2893
|
+
if currency['active'] is None or active:
|
2894
|
+
currency['active'] = active
|
2895
|
+
# find lowest fee(which is more desired)
|
2896
|
+
fee = self.safe_string(network, 'fee')
|
2897
|
+
feeMain = self.safe_string(currency, 'fee')
|
2898
|
+
if feeMain is None or Precise.string_lt(fee, feeMain):
|
2899
|
+
currency['fee'] = self.parse_number(fee)
|
2900
|
+
# find lowest precision(which is more desired)
|
2901
|
+
precision = self.safe_string(network, 'precision')
|
2902
|
+
precisionMain = self.safe_string(currency, 'precision')
|
2903
|
+
if precisionMain is None or Precise.string_lt(precision, precisionMain):
|
2904
|
+
currency['precision'] = self.parse_number(precision)
|
2905
|
+
# limits
|
2906
|
+
limits = self.safe_dict(network, 'limits')
|
2907
|
+
limitsMain = self.safe_dict(currency, 'limits')
|
2908
|
+
if limitsMain is None:
|
2909
|
+
currency['limits'] = {}
|
2910
|
+
# deposits
|
2911
|
+
limitsDeposit = self.safe_dict(limits, 'deposit')
|
2912
|
+
limitsDepositMain = self.safe_dict(limitsMain, 'deposit')
|
2913
|
+
if limitsDepositMain is None:
|
2914
|
+
currency['limits']['deposit'] = {}
|
2915
|
+
limitsDepositMin = self.safe_string(limitsDeposit, 'min')
|
2916
|
+
limitsDepositMax = self.safe_string(limitsDeposit, 'max')
|
2917
|
+
limitsDepositMinMain = self.safe_string(limitsDepositMain, 'min')
|
2918
|
+
limitsDepositMaxMain = self.safe_string(limitsDepositMain, 'max')
|
2919
|
+
# find min
|
2920
|
+
if limitsDepositMinMain is None or Precise.string_lt(limitsDepositMin, limitsDepositMinMain):
|
2921
|
+
currency['limits']['deposit']['min'] = self.parse_number(limitsDepositMin)
|
2922
|
+
# find max
|
2923
|
+
if limitsDepositMaxMain is None or Precise.string_gt(limitsDepositMax, limitsDepositMaxMain):
|
2924
|
+
currency['limits']['deposit']['max'] = self.parse_number(limitsDepositMax)
|
2925
|
+
# withdrawals
|
2926
|
+
limitsWithdraw = self.safe_dict(limits, 'withdraw')
|
2927
|
+
limitsWithdrawMain = self.safe_dict(limitsMain, 'withdraw')
|
2928
|
+
if limitsWithdrawMain is None:
|
2929
|
+
currency['limits']['withdraw'] = {}
|
2930
|
+
limitsWithdrawMin = self.safe_string(limitsWithdraw, 'min')
|
2931
|
+
limitsWithdrawMax = self.safe_string(limitsWithdraw, 'max')
|
2932
|
+
limitsWithdrawMinMain = self.safe_string(limitsWithdrawMain, 'min')
|
2933
|
+
limitsWithdrawMaxMain = self.safe_string(limitsWithdrawMain, 'max')
|
2934
|
+
# find min
|
2935
|
+
if limitsWithdrawMinMain is None or Precise.string_lt(limitsWithdrawMin, limitsWithdrawMinMain):
|
2936
|
+
currency['limits']['withdraw']['min'] = self.parse_number(limitsWithdrawMin)
|
2937
|
+
# find max
|
2938
|
+
if limitsWithdrawMaxMain is None or Precise.string_gt(limitsWithdrawMax, limitsWithdrawMaxMain):
|
2939
|
+
currency['limits']['withdraw']['max'] = self.parse_number(limitsWithdrawMax)
|
2879
2940
|
return self.extend({
|
2880
2941
|
'info': None,
|
2881
2942
|
'id': None,
|
ccxt/binance.py
CHANGED
@@ -502,6 +502,7 @@ class binance(Exchange, ImplicitAPI):
|
|
502
502
|
'portfolio/repay-futures-switch': 3, # Weight(IP): 30 => cost = 0.1 * 30 = 3
|
503
503
|
'portfolio/margin-asset-leverage': 5, # Weight(IP): 50 => cost = 0.1 * 50 = 5
|
504
504
|
'portfolio/balance': 2,
|
505
|
+
'portfolio/negative-balance-exchange-record': 2,
|
505
506
|
# staking
|
506
507
|
'staking/productList': 0.1,
|
507
508
|
'staking/position': 0.1,
|
@@ -5000,11 +5001,13 @@ class binance(Exchange, ImplicitAPI):
|
|
5000
5001
|
until = self.safe_integer(params, 'until')
|
5001
5002
|
if until is not None:
|
5002
5003
|
request['endTime'] = until
|
5003
|
-
if limit is not None:
|
5004
|
-
isFutureOrSwap = (market['swap'] or market['future'])
|
5005
|
-
request['limit'] = min(limit, 1000) if isFutureOrSwap else limit # default = 500, maximum = 1000
|
5006
5004
|
method = self.safe_string(self.options, 'fetchTradesMethod')
|
5007
5005
|
method = self.safe_string_2(params, 'fetchTradesMethod', 'method', method)
|
5006
|
+
if limit is not None:
|
5007
|
+
isFutureOrSwap = (market['swap'] or market['future'])
|
5008
|
+
isHistoricalEndpoint = (method is not None) and (method.find('GetHistoricalTrades') >= 0)
|
5009
|
+
maxLimitForContractHistorical = 500 if isHistoricalEndpoint else 1000
|
5010
|
+
request['limit'] = min(limit, maxLimitForContractHistorical) if isFutureOrSwap else limit # default = 500, maximum = 1000
|
5008
5011
|
params = self.omit(params, ['until', 'fetchTradesMethod'])
|
5009
5012
|
response = None
|
5010
5013
|
if market['option'] or method == 'eapiPublicGetTrades':
|
@@ -6836,6 +6839,7 @@ class binance(Exchange, ImplicitAPI):
|
|
6836
6839
|
:param str symbol: unified market symbol
|
6837
6840
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
6838
6841
|
:param str [params.trigger]: set to True if you would like to fetch portfolio margin account stop or conditional orders
|
6842
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch for a portfolio margin account
|
6839
6843
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
6840
6844
|
"""
|
6841
6845
|
if symbol is None:
|
@@ -10158,7 +10162,7 @@ class binance(Exchange, ImplicitAPI):
|
|
10158
10162
|
# }
|
10159
10163
|
#
|
10160
10164
|
marketId = self.safe_string(position, 'symbol')
|
10161
|
-
market = self.safe_market(marketId, market)
|
10165
|
+
market = self.safe_market(marketId, market, None, 'swap')
|
10162
10166
|
symbol = market['symbol']
|
10163
10167
|
side = self.safe_string_lower(position, 'side')
|
10164
10168
|
quantity = self.safe_string(position, 'quantity')
|
ccxt/bingx.py
CHANGED
@@ -829,8 +829,8 @@ class bingx(Exchange, ImplicitAPI):
|
|
829
829
|
# "symbols": [
|
830
830
|
# {
|
831
831
|
# "symbol": "GEAR-USDT",
|
832
|
-
# "minQty": 735,
|
833
|
-
# "maxQty": 2941177,
|
832
|
+
# "minQty": 735, # deprecated
|
833
|
+
# "maxQty": 2941177, # deprecated
|
834
834
|
# "minNotional": 5,
|
835
835
|
# "maxNotional": 20000,
|
836
836
|
# "status": 1,
|
@@ -948,6 +948,9 @@ class bingx(Exchange, ImplicitAPI):
|
|
948
948
|
isActive = True # spot active
|
949
949
|
isInverse = None if (spot) else checkIsInverse
|
950
950
|
isLinear = None if (spot) else checkIsLinear
|
951
|
+
minAmount = None
|
952
|
+
if not spot:
|
953
|
+
minAmount = self.safe_number_2(market, 'minQty', 'tradeMinQuantity')
|
951
954
|
timeOnline = self.safe_integer(market, 'timeOnline')
|
952
955
|
if timeOnline == 0:
|
953
956
|
timeOnline = None
|
@@ -988,8 +991,8 @@ class bingx(Exchange, ImplicitAPI):
|
|
988
991
|
'max': None,
|
989
992
|
},
|
990
993
|
'amount': {
|
991
|
-
'min':
|
992
|
-
'max':
|
994
|
+
'min': minAmount,
|
995
|
+
'max': None,
|
993
996
|
},
|
994
997
|
'price': {
|
995
998
|
'min': minTickSize,
|
@@ -1621,21 +1624,24 @@ class bingx(Exchange, ImplicitAPI):
|
|
1621
1624
|
# }
|
1622
1625
|
#
|
1623
1626
|
data = self.safe_list(response, 'data', [])
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1627
|
+
return self.parse_funding_rate_histories(data, market, since, limit)
|
1628
|
+
|
1629
|
+
def parse_funding_rate_history(self, contract, market: Market = None):
|
1630
|
+
#
|
1631
|
+
# {
|
1632
|
+
# "symbol": "BTC-USDT",
|
1633
|
+
# "fundingRate": "0.0001",
|
1634
|
+
# "fundingTime": 1585684800000
|
1635
|
+
# }
|
1636
|
+
#
|
1637
|
+
timestamp = self.safe_integer(contract, 'fundingTime')
|
1638
|
+
return {
|
1639
|
+
'info': contract,
|
1640
|
+
'symbol': self.safe_symbol(self.safe_string(contract, 'symbol'), market, '-', 'swap'),
|
1641
|
+
'fundingRate': self.safe_number(contract, 'fundingRate'),
|
1642
|
+
'timestamp': timestamp,
|
1643
|
+
'datetime': self.iso8601(timestamp),
|
1644
|
+
}
|
1639
1645
|
|
1640
1646
|
def fetch_open_interest(self, symbol: str, params={}):
|
1641
1647
|
"""
|
@@ -2274,12 +2280,13 @@ class bingx(Exchange, ImplicitAPI):
|
|
2274
2280
|
else:
|
2275
2281
|
linearSwapData = self.safe_dict(response, 'data', {})
|
2276
2282
|
linearSwapBalance = self.safe_dict(linearSwapData, 'balance')
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
+
if linearSwapBalance:
|
2284
|
+
currencyId = self.safe_string(linearSwapBalance, 'asset')
|
2285
|
+
code = self.safe_currency_code(currencyId)
|
2286
|
+
account = self.account()
|
2287
|
+
account['free'] = self.safe_string(linearSwapBalance, 'availableMargin')
|
2288
|
+
account['used'] = self.safe_string(linearSwapBalance, 'usedMargin')
|
2289
|
+
result[code] = account
|
2283
2290
|
return self.safe_balance(result)
|
2284
2291
|
|
2285
2292
|
def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
@@ -6160,6 +6167,37 @@ class bingx(Exchange, ImplicitAPI):
|
|
6160
6167
|
'tierBased': False,
|
6161
6168
|
}
|
6162
6169
|
|
6170
|
+
def custom_encode(self, params):
|
6171
|
+
sortedParams = self.keysort(params)
|
6172
|
+
keys = list(sortedParams.keys())
|
6173
|
+
adjustedValue = None
|
6174
|
+
result = None
|
6175
|
+
for i in range(0, len(keys)):
|
6176
|
+
key = keys[i]
|
6177
|
+
value = sortedParams[key]
|
6178
|
+
if isinstance(value, list):
|
6179
|
+
arrStr = None
|
6180
|
+
for j in range(0, len(value)):
|
6181
|
+
arrayElement = value[j]
|
6182
|
+
isString = (isinstance(arrayElement, str))
|
6183
|
+
if isString:
|
6184
|
+
if j > 0:
|
6185
|
+
arrStr += ',' + '"' + str(arrayElement) + '"'
|
6186
|
+
else:
|
6187
|
+
arrStr = '"' + str(arrayElement) + '"'
|
6188
|
+
else:
|
6189
|
+
if j > 0:
|
6190
|
+
arrStr += ',' + str(arrayElement)
|
6191
|
+
else:
|
6192
|
+
arrStr = str(arrayElement)
|
6193
|
+
adjustedValue = '[' + arrStr + ']'
|
6194
|
+
value = adjustedValue
|
6195
|
+
if i == 0:
|
6196
|
+
result = key + '=' + value
|
6197
|
+
else:
|
6198
|
+
result += '&' + key + '=' + value
|
6199
|
+
return result
|
6200
|
+
|
6163
6201
|
def sign(self, path, section='public', method='GET', params={}, headers=None, body=None):
|
6164
6202
|
type = section[0]
|
6165
6203
|
version = section[1]
|
@@ -6188,16 +6226,22 @@ class bingx(Exchange, ImplicitAPI):
|
|
6188
6226
|
elif access == 'private':
|
6189
6227
|
self.check_required_credentials()
|
6190
6228
|
isJsonContentType = (((type == 'subAccount') or (type == 'account/transfer')) and (method == 'POST'))
|
6191
|
-
parsedParams =
|
6192
|
-
|
6229
|
+
parsedParams = None
|
6230
|
+
encodeRequest = None
|
6231
|
+
if isJsonContentType:
|
6232
|
+
encodeRequest = self.custom_encode(params)
|
6233
|
+
else:
|
6234
|
+
parsedParams = self.parse_params(params)
|
6235
|
+
encodeRequest = self.rawencode(parsedParams)
|
6236
|
+
signature = self.hmac(self.encode(encodeRequest), self.encode(self.secret), hashlib.sha256)
|
6193
6237
|
headers = {
|
6194
6238
|
'X-BX-APIKEY': self.apiKey,
|
6195
6239
|
'X-SOURCE-KEY': self.safe_string(self.options, 'broker', 'CCXT'),
|
6196
6240
|
}
|
6197
6241
|
if isJsonContentType:
|
6198
6242
|
headers['Content-Type'] = 'application/json'
|
6199
|
-
|
6200
|
-
body = self.json(
|
6243
|
+
params['signature'] = signature
|
6244
|
+
body = self.json(params)
|
6201
6245
|
else:
|
6202
6246
|
query = self.urlencode(parsedParams)
|
6203
6247
|
url += '?' + query + '&' + 'signature=' + signature
|
ccxt/bitget.py
CHANGED
@@ -1402,18 +1402,18 @@ class bitget(Exchange, ImplicitAPI):
|
|
1402
1402
|
'1m': 30,
|
1403
1403
|
'3m': 30,
|
1404
1404
|
'5m': 30,
|
1405
|
-
'10m':
|
1405
|
+
'10m': 30,
|
1406
1406
|
'15m': 52,
|
1407
|
-
'30m':
|
1407
|
+
'30m': 62,
|
1408
1408
|
'1h': 83,
|
1409
1409
|
'2h': 120,
|
1410
1410
|
'4h': 240,
|
1411
1411
|
'6h': 360,
|
1412
1412
|
'12h': 360,
|
1413
|
-
'1d':
|
1414
|
-
'3d':
|
1415
|
-
'1w':
|
1416
|
-
'1M':
|
1413
|
+
'1d': 300,
|
1414
|
+
'3d': 300,
|
1415
|
+
'1w': 300,
|
1416
|
+
'1M': 300,
|
1417
1417
|
},
|
1418
1418
|
},
|
1419
1419
|
'fetchTrades': {
|
@@ -3463,6 +3463,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3463
3463
|
:param int [limit]: the maximum amount of candles to fetch
|
3464
3464
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
3465
3465
|
:param int [params.until]: timestamp in ms of the latest candle to fetch
|
3466
|
+
:param boolean [params.useHistoryEndpoint]: whether to force to use historical endpoint(it has max limit of 200)
|
3466
3467
|
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
3467
3468
|
:param str [params.price]: *swap only* "mark"(to fetch mark price candles) or "index"(to fetch index price candles)
|
3468
3469
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
@@ -3474,8 +3475,9 @@ class bitget(Exchange, ImplicitAPI):
|
|
3474
3475
|
paginate = False
|
3475
3476
|
paginate, params = self.handle_option_and_params(params, 'fetchOHLCV', 'paginate')
|
3476
3477
|
if paginate:
|
3477
|
-
return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params,
|
3478
|
+
return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimitForRecentEndpoint)
|
3478
3479
|
sandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
|
3480
|
+
useHistoryEndpoint = self.safe_bool(params, 'useHistoryEndpoint', False)
|
3479
3481
|
market = None
|
3480
3482
|
if sandboxMode:
|
3481
3483
|
sandboxSymbol = self.convert_symbol_for_sandbox(symbol)
|
@@ -3503,7 +3505,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3503
3505
|
ohlcOptions = self.safe_dict(self.options, 'fetchOHLCV', {})
|
3504
3506
|
retrievableDaysMap = self.safe_dict(ohlcOptions, 'maxDaysPerTimeframe', {})
|
3505
3507
|
maxRetrievableDaysForRecent = self.safe_integer(retrievableDaysMap, timeframe, 30) # default to safe minimum
|
3506
|
-
endpointTsBoundary = now - maxRetrievableDaysForRecent * msInDay
|
3508
|
+
endpointTsBoundary = now - (maxRetrievableDaysForRecent - 1) * msInDay
|
3507
3509
|
if limitDefined:
|
3508
3510
|
limit = min(limit, maxLimitForRecentEndpoint)
|
3509
3511
|
request['limit'] = limit
|
@@ -3534,7 +3536,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3534
3536
|
# make request
|
3535
3537
|
if market['spot']:
|
3536
3538
|
# checks if we need history endpoint
|
3537
|
-
if historicalEndpointNeeded:
|
3539
|
+
if historicalEndpointNeeded or useHistoryEndpoint:
|
3538
3540
|
response = self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
|
3539
3541
|
else:
|
3540
3542
|
response = self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
|
@@ -3558,7 +3560,7 @@ class bitget(Exchange, ImplicitAPI):
|
|
3558
3560
|
elif priceType == 'index':
|
3559
3561
|
response = self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
|
3560
3562
|
else:
|
3561
|
-
if historicalEndpointNeeded:
|
3563
|
+
if historicalEndpointNeeded or useHistoryEndpoint:
|
3562
3564
|
response = self.publicMixGetV2MixMarketHistoryCandles(extended)
|
3563
3565
|
else:
|
3564
3566
|
response = self.publicMixGetV2MixMarketCandles(extended)
|
ccxt/blofin.py
CHANGED
ccxt/coinex.py
CHANGED
@@ -480,7 +480,7 @@ class coinex(Exchange, ImplicitAPI):
|
|
480
480
|
'ERC20': 'ERC20',
|
481
481
|
'BRC20': 'BRC20',
|
482
482
|
'SOL': 'SOL',
|
483
|
-
'TON': '
|
483
|
+
'TON': 'TON',
|
484
484
|
'BSV': 'BSV',
|
485
485
|
'AVAXC': 'AVA_C',
|
486
486
|
'AVAXX': 'AVA',
|
@@ -4608,13 +4608,13 @@ class coinex(Exchange, ImplicitAPI):
|
|
4608
4608
|
self.check_address(address)
|
4609
4609
|
self.load_markets()
|
4610
4610
|
currency = self.currency(code)
|
4611
|
-
if tag:
|
4612
|
-
address = address + ':' + tag
|
4613
4611
|
request: dict = {
|
4614
4612
|
'ccy': currency['id'],
|
4615
4613
|
'to_address': address, # must be authorized, inter-user transfer by a registered mobile phone number or an email address is supported
|
4616
4614
|
'amount': self.number_to_string(amount), # the actual amount without fees, https://www.coinex.com/fees
|
4617
4615
|
}
|
4616
|
+
if tag is not None:
|
4617
|
+
request['memo'] = tag
|
4618
4618
|
networkCode = None
|
4619
4619
|
networkCode, params = self.handle_network_code_and_params(params)
|
4620
4620
|
if networkCode is not None:
|