ccxt 4.4.80__py2.py3-none-any.whl → 4.4.85__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 -5
- ccxt/abstract/blofin.py +8 -0
- ccxt/abstract/btcbox.py +1 -0
- ccxt/apex.py +21 -30
- ccxt/ascendex.py +1 -1
- ccxt/async_support/__init__.py +1 -5
- ccxt/async_support/apex.py +21 -30
- ccxt/async_support/ascendex.py +1 -1
- ccxt/async_support/base/exchange.py +26 -3
- ccxt/async_support/base/ws/cache.py +6 -1
- ccxt/async_support/bigone.py +17 -14
- ccxt/async_support/bingx.py +13 -32
- ccxt/async_support/bitfinex.py +61 -48
- ccxt/async_support/bitget.py +7 -4
- ccxt/async_support/bitrue.py +14 -32
- ccxt/async_support/bitso.py +33 -0
- ccxt/async_support/bitstamp.py +33 -0
- ccxt/async_support/blofin.py +145 -14
- ccxt/async_support/btcbox.py +25 -5
- ccxt/async_support/bybit.py +20 -39
- ccxt/async_support/cex.py +2 -4
- ccxt/async_support/coinbase.py +56 -42
- ccxt/async_support/coinbaseexchange.py +141 -32
- ccxt/async_support/coincatch.py +14 -67
- ccxt/async_support/coinex.py +28 -29
- ccxt/async_support/coinlist.py +17 -16
- ccxt/async_support/coinmetro.py +20 -11
- ccxt/async_support/coinone.py +8 -10
- ccxt/async_support/coinsph.py +124 -2
- ccxt/async_support/cryptocom.py +109 -2
- ccxt/async_support/cryptomus.py +42 -80
- ccxt/async_support/delta.py +75 -36
- ccxt/async_support/derive.py +46 -10
- ccxt/async_support/ellipx.py +175 -77
- ccxt/async_support/gate.py +1 -1
- ccxt/async_support/gemini.py +3 -4
- ccxt/async_support/hitbtc.py +56 -65
- ccxt/async_support/htx.py +2 -2
- ccxt/async_support/hyperliquid.py +15 -2
- ccxt/async_support/kraken.py +27 -23
- ccxt/async_support/kucoinfutures.py +5 -0
- ccxt/async_support/lbank.py +1 -1
- ccxt/async_support/okx.py +1 -2
- ccxt/async_support/oxfun.py +21 -1
- ccxt/async_support/paradex.py +120 -4
- ccxt/base/errors.py +6 -0
- ccxt/base/exchange.py +40 -3
- ccxt/base/types.py +3 -0
- ccxt/bigone.py +17 -14
- ccxt/bingx.py +13 -32
- ccxt/bitfinex.py +61 -48
- ccxt/bitget.py +7 -4
- ccxt/bitrue.py +14 -32
- ccxt/bitso.py +33 -0
- ccxt/bitstamp.py +33 -0
- ccxt/blofin.py +145 -14
- ccxt/btcbox.py +24 -5
- ccxt/bybit.py +20 -39
- ccxt/cex.py +2 -4
- ccxt/coinbase.py +56 -42
- ccxt/coinbaseexchange.py +141 -32
- ccxt/coincatch.py +14 -67
- ccxt/coinex.py +28 -29
- ccxt/coinlist.py +17 -16
- ccxt/coinmetro.py +20 -11
- ccxt/coinone.py +8 -10
- ccxt/coinsph.py +124 -2
- ccxt/cryptocom.py +109 -2
- ccxt/cryptomus.py +42 -80
- ccxt/delta.py +75 -36
- ccxt/derive.py +46 -10
- ccxt/ellipx.py +175 -77
- ccxt/gate.py +1 -1
- ccxt/gemini.py +3 -4
- ccxt/hitbtc.py +56 -65
- ccxt/htx.py +2 -2
- ccxt/hyperliquid.py +15 -2
- ccxt/kraken.py +27 -23
- ccxt/kucoinfutures.py +5 -0
- ccxt/lbank.py +1 -1
- ccxt/okx.py +1 -2
- ccxt/oxfun.py +21 -1
- ccxt/paradex.py +120 -4
- ccxt/pro/__init__.py +69 -3
- ccxt/pro/binance.py +31 -33
- ccxt/pro/bithumb.py +5 -3
- ccxt/pro/coinbase.py +1 -1
- ccxt/pro/hyperliquid.py +10 -2
- ccxt/pro/kraken.py +249 -79
- ccxt/pro/mexc.py +252 -7
- ccxt/pro/poloniex.py +6 -2
- {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/METADATA +7 -11
- {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/RECORD +96 -104
- ccxt/abstract/bl3p.py +0 -19
- ccxt/abstract/idex.py +0 -26
- ccxt/async_support/base/ws/fast_client.py +0 -97
- ccxt/async_support/bl3p.py +0 -543
- ccxt/async_support/idex.py +0 -1889
- ccxt/bl3p.py +0 -543
- ccxt/idex.py +0 -1889
- ccxt/pro/idex.py +0 -687
- {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/WHEEL +0 -0
- {ccxt-4.4.80.dist-info → ccxt-4.4.85.dist-info}/top_level.txt +0 -0
ccxt/blofin.py
CHANGED
@@ -57,6 +57,7 @@ class blofin(Exchange, ImplicitAPI):
|
|
57
57
|
'createStopMarketOrder': False,
|
58
58
|
'createStopOrder': False,
|
59
59
|
'createTakeProfitOrder': True,
|
60
|
+
'createTriggerOrder': True,
|
60
61
|
'editOrder': False,
|
61
62
|
'fetchAccounts': False,
|
62
63
|
'fetchBalance': True,
|
@@ -110,6 +111,7 @@ class blofin(Exchange, ImplicitAPI):
|
|
110
111
|
'fetchOrders': False,
|
111
112
|
'fetchOrderTrades': True,
|
112
113
|
'fetchPosition': True,
|
114
|
+
'fetchPositionMode': True,
|
113
115
|
'fetchPositions': True,
|
114
116
|
'fetchPositionsForSymbol': False,
|
115
117
|
'fetchPositionsRisk': False,
|
@@ -137,8 +139,8 @@ class blofin(Exchange, ImplicitAPI):
|
|
137
139
|
'repayCrossMargin': False,
|
138
140
|
'setLeverage': True,
|
139
141
|
'setMargin': False,
|
140
|
-
'setMarginMode':
|
141
|
-
'setPositionMode':
|
142
|
+
'setMarginMode': True,
|
143
|
+
'setPositionMode': True,
|
142
144
|
'signIn': False,
|
143
145
|
'transfer': True,
|
144
146
|
'withdraw': False,
|
@@ -201,10 +203,14 @@ class blofin(Exchange, ImplicitAPI):
|
|
201
203
|
'account/positions': 1,
|
202
204
|
'account/leverage-info': 1,
|
203
205
|
'account/margin-mode': 1,
|
206
|
+
'account/position-mode': 1,
|
204
207
|
'account/batch-leverage-info': 1,
|
205
208
|
'trade/orders-tpsl-pending': 1,
|
209
|
+
'trade/orders-algo-pending': 1,
|
206
210
|
'trade/orders-history': 1,
|
207
211
|
'trade/orders-tpsl-history': 1,
|
212
|
+
'trade/orders-algo-history': 1, # todo new
|
213
|
+
'trade/order/price-range': 1,
|
208
214
|
'user/query-apikey': 1,
|
209
215
|
'affiliate/basic': 1,
|
210
216
|
'copytrading/instruments': 1,
|
@@ -221,8 +227,12 @@ class blofin(Exchange, ImplicitAPI):
|
|
221
227
|
'copytrading/trade/pending-tpsl-by-order': 1,
|
222
228
|
},
|
223
229
|
'post': {
|
230
|
+
'account/set-margin-mode': 1,
|
231
|
+
'account/set-position-mode': 1,
|
224
232
|
'trade/order': 1,
|
233
|
+
'trade/order-algo': 1,
|
225
234
|
'trade/cancel-order': 1,
|
235
|
+
'trade/cancel-algo': 1,
|
226
236
|
'account/set-leverage': 1,
|
227
237
|
'trade/batch-orders': 1,
|
228
238
|
'trade/order-tpsl': 1,
|
@@ -1135,7 +1145,11 @@ class blofin(Exchange, ImplicitAPI):
|
|
1135
1145
|
marginMode = None
|
1136
1146
|
marginMode, params = self.handle_margin_mode_and_params('createOrder', params, 'cross')
|
1137
1147
|
request['marginMode'] = marginMode
|
1148
|
+
triggerPrice = self.safe_string(params, 'triggerPrice')
|
1138
1149
|
timeInForce = self.safe_string(params, 'timeInForce', 'GTC')
|
1150
|
+
isHedged = self.safe_bool(params, 'hedged', False)
|
1151
|
+
if isHedged:
|
1152
|
+
request['positionSide'] = 'long' if (side == 'buy') else 'short'
|
1139
1153
|
isMarketOrder = type == 'market'
|
1140
1154
|
params = self.omit(params, ['timeInForce'])
|
1141
1155
|
ioc = (timeInForce == 'IOC') or (type == 'ioc')
|
@@ -1143,14 +1157,15 @@ class blofin(Exchange, ImplicitAPI):
|
|
1143
1157
|
if isMarketOrder or marketIOC:
|
1144
1158
|
request['orderType'] = 'market'
|
1145
1159
|
else:
|
1146
|
-
|
1160
|
+
key = 'orderPrice' if (triggerPrice is not None) else 'price'
|
1161
|
+
request[key] = self.price_to_precision(symbol, price)
|
1147
1162
|
postOnly = False
|
1148
1163
|
postOnly, params = self.handle_post_only(isMarketOrder, type == 'post_only', params)
|
1149
1164
|
if postOnly:
|
1150
1165
|
request['type'] = 'post_only'
|
1151
1166
|
stopLoss = self.safe_dict(params, 'stopLoss')
|
1152
1167
|
takeProfit = self.safe_dict(params, 'takeProfit')
|
1153
|
-
params = self.omit(params, ['stopLoss', 'takeProfit'])
|
1168
|
+
params = self.omit(params, ['stopLoss', 'takeProfit', 'hedged'])
|
1154
1169
|
isStopLoss = stopLoss is not None
|
1155
1170
|
isTakeProfit = takeProfit is not None
|
1156
1171
|
if isStopLoss or isTakeProfit:
|
@@ -1164,6 +1179,11 @@ class blofin(Exchange, ImplicitAPI):
|
|
1164
1179
|
request['tpTriggerPrice'] = self.price_to_precision(symbol, tpTriggerPrice)
|
1165
1180
|
tpPrice = self.safe_string(takeProfit, 'price', '-1')
|
1166
1181
|
request['tpOrderPrice'] = self.price_to_precision(symbol, tpPrice)
|
1182
|
+
elif triggerPrice is not None:
|
1183
|
+
request['orderType'] = 'trigger'
|
1184
|
+
request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
|
1185
|
+
if isMarketOrder:
|
1186
|
+
request['orderPrice'] = '-1'
|
1167
1187
|
return self.extend(request, params)
|
1168
1188
|
|
1169
1189
|
def parse_order_status(self, status: Str):
|
@@ -1213,7 +1233,7 @@ class blofin(Exchange, ImplicitAPI):
|
|
1213
1233
|
# "instType": "SWAP", # only in WS
|
1214
1234
|
# }
|
1215
1235
|
#
|
1216
|
-
id = self.
|
1236
|
+
id = self.safe_string_n(order, ['tpslId', 'orderId', 'algoId'])
|
1217
1237
|
timestamp = self.safe_integer(order, 'createTime')
|
1218
1238
|
lastUpdateTimestamp = self.safe_integer(order, 'updateTime')
|
1219
1239
|
lastTradeTimestamp = self.safe_integer(order, 'fillTime')
|
@@ -1307,12 +1327,14 @@ class blofin(Exchange, ImplicitAPI):
|
|
1307
1327
|
:param float amount: how much of currency you want to trade in units of base currency
|
1308
1328
|
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1309
1329
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1330
|
+
:param str [params.triggerPrice]: the trigger price for a trigger order
|
1310
1331
|
:param bool [params.reduceOnly]: a mark to reduce the position size for margin, swap and future orders
|
1311
1332
|
:param bool [params.postOnly]: True to place a post only order
|
1312
1333
|
:param str [params.marginMode]: 'cross' or 'isolated', default is 'cross'
|
1313
1334
|
:param float [params.stopLossPrice]: stop loss trigger price(will use privatePostTradeOrderTpsl)
|
1314
1335
|
:param float [params.takeProfitPrice]: take profit trigger price(will use privatePostTradeOrderTpsl)
|
1315
1336
|
:param str [params.positionSide]: *stopLossPrice/takeProfitPrice orders only* 'long' or 'short' or 'net' default is 'net'
|
1337
|
+
:param boolean [params.hedged]: if True, the positionSide will be set to long/short instead of net, default is False
|
1316
1338
|
:param str [params.clientOrderId]: a unique id for the order
|
1317
1339
|
:param dict [params.takeProfit]: *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
|
1318
1340
|
:param float [params.takeProfit.triggerPrice]: take profit trigger price
|
@@ -1330,14 +1352,25 @@ class blofin(Exchange, ImplicitAPI):
|
|
1330
1352
|
method, params = self.handle_option_and_params(params, 'createOrder', 'method', 'privatePostTradeOrder')
|
1331
1353
|
isStopLossPriceDefined = self.safe_string(params, 'stopLossPrice') is not None
|
1332
1354
|
isTakeProfitPriceDefined = self.safe_string(params, 'takeProfitPrice') is not None
|
1355
|
+
isTriggerOrder = self.safe_string(params, 'triggerPrice') is not None
|
1333
1356
|
isType2Order = (isStopLossPriceDefined or isTakeProfitPriceDefined)
|
1334
1357
|
response = None
|
1358
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly')
|
1359
|
+
if reduceOnly is not None:
|
1360
|
+
params['reduceOnly'] = 'true' if reduceOnly else 'false'
|
1335
1361
|
if tpsl or (method == 'privatePostTradeOrderTpsl') or isType2Order:
|
1336
1362
|
tpslRequest = self.create_tpsl_order_request(symbol, type, side, amount, price, params)
|
1337
1363
|
response = self.privatePostTradeOrderTpsl(tpslRequest)
|
1364
|
+
elif isTriggerOrder or (method == 'privatePostTradeOrderAlgo'):
|
1365
|
+
triggerRequest = self.create_order_request(symbol, type, side, amount, price, params)
|
1366
|
+
response = self.privatePostTradeOrderAlgo(triggerRequest)
|
1338
1367
|
else:
|
1339
1368
|
request = self.create_order_request(symbol, type, side, amount, price, params)
|
1340
1369
|
response = self.privatePostTradeOrder(request)
|
1370
|
+
if isTriggerOrder or (method == 'privatePostTradeOrderAlgo'):
|
1371
|
+
dataDict = self.safe_dict(response, 'data', {})
|
1372
|
+
triggerOrder = self.parse_order(dataDict, market)
|
1373
|
+
return triggerOrder
|
1341
1374
|
data = self.safe_list(response, 'data', [])
|
1342
1375
|
first = self.safe_dict(data, 0)
|
1343
1376
|
order = self.parse_order(first, market)
|
@@ -1387,7 +1420,8 @@ class blofin(Exchange, ImplicitAPI):
|
|
1387
1420
|
:param str id: order id
|
1388
1421
|
:param str symbol: unified symbol of the market the order was made in
|
1389
1422
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1390
|
-
:param boolean [params.trigger]: True if cancelling a trigger/conditional
|
1423
|
+
:param boolean [params.trigger]: True if cancelling a trigger/conditional
|
1424
|
+
:param boolean [params.tpsl]: True if cancelling a tpsl order
|
1391
1425
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1392
1426
|
"""
|
1393
1427
|
if symbol is None:
|
@@ -1397,20 +1431,27 @@ class blofin(Exchange, ImplicitAPI):
|
|
1397
1431
|
request: dict = {
|
1398
1432
|
'instId': market['id'],
|
1399
1433
|
}
|
1400
|
-
isTrigger = self.safe_bool_n(params, ['
|
1434
|
+
isTrigger = self.safe_bool_n(params, ['trigger'], False)
|
1435
|
+
isTpsl = self.safe_bool_2(params, 'tpsl', 'TPSL', False)
|
1401
1436
|
clientOrderId = self.safe_string(params, 'clientOrderId')
|
1402
1437
|
if clientOrderId is not None:
|
1403
1438
|
request['clientOrderId'] = clientOrderId
|
1404
1439
|
else:
|
1405
|
-
if not isTrigger:
|
1440
|
+
if not isTrigger and not isTpsl:
|
1406
1441
|
request['orderId'] = str(id)
|
1407
|
-
|
1442
|
+
elif isTpsl:
|
1408
1443
|
request['tpslId'] = str(id)
|
1444
|
+
elif isTrigger:
|
1445
|
+
request['algoId'] = str(id)
|
1409
1446
|
query = self.omit(params, ['orderId', 'clientOrderId', 'stop', 'trigger', 'tpsl'])
|
1410
|
-
if
|
1447
|
+
if isTpsl:
|
1411
1448
|
tpslResponse = self.cancel_orders([id], symbol, params)
|
1412
1449
|
first = self.safe_dict(tpslResponse, 0)
|
1413
1450
|
return first
|
1451
|
+
elif isTrigger:
|
1452
|
+
triggerResponse = self.privatePostTradeCancelAlgo(self.extend(request, query))
|
1453
|
+
triggerData = self.safe_dict(triggerResponse, 'data')
|
1454
|
+
return self.parse_order(triggerData, market)
|
1414
1455
|
response = self.privatePostTradeCancelOrder(self.extend(request, query))
|
1415
1456
|
data = self.safe_list(response, 'data', [])
|
1416
1457
|
order = self.safe_dict(data, 0)
|
@@ -1449,6 +1490,7 @@ class blofin(Exchange, ImplicitAPI):
|
|
1449
1490
|
|
1450
1491
|
https://blofin.com/docs#get-active-orders
|
1451
1492
|
https://blofin.com/docs#get-active-tpsl-orders
|
1493
|
+
https://docs.blofin.com/index.html#get-active-algo-orders
|
1452
1494
|
|
1453
1495
|
:param str symbol: unified market symbol
|
1454
1496
|
:param int [since]: the earliest time in ms to fetch open orders for
|
@@ -1471,13 +1513,17 @@ class blofin(Exchange, ImplicitAPI):
|
|
1471
1513
|
request['instId'] = market['id']
|
1472
1514
|
if limit is not None:
|
1473
1515
|
request['limit'] = limit # default 100, max 100
|
1474
|
-
isTrigger = self.safe_bool_n(params, ['stop', 'trigger'
|
1516
|
+
isTrigger = self.safe_bool_n(params, ['stop', 'trigger'], False)
|
1517
|
+
isTpSl = self.safe_bool_2(params, 'tpsl', 'TPSL', False)
|
1475
1518
|
method: Str = None
|
1476
1519
|
method, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'method', 'privateGetTradeOrdersPending')
|
1477
1520
|
query = self.omit(params, ['method', 'stop', 'trigger', 'tpsl', 'TPSL'])
|
1478
1521
|
response = None
|
1479
|
-
if
|
1522
|
+
if isTpSl or (method == 'privateGetTradeOrdersTpslPending'):
|
1480
1523
|
response = self.privateGetTradeOrdersTpslPending(self.extend(request, query))
|
1524
|
+
elif isTrigger or (method == 'privateGetTradeOrdersAlgoPending'):
|
1525
|
+
request['orderType'] = 'trigger'
|
1526
|
+
response = self.privateGetTradeOrdersAlgoPending(self.extend(request, query))
|
1481
1527
|
else:
|
1482
1528
|
response = self.privateGetTradeOrdersPending(self.extend(request, query))
|
1483
1529
|
data = self.safe_list(response, 'data', [])
|
@@ -2118,6 +2164,7 @@ class blofin(Exchange, ImplicitAPI):
|
|
2118
2164
|
:param str symbol: unified market symbol
|
2119
2165
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2120
2166
|
:param str [params.marginMode]: 'cross' or 'isolated'
|
2167
|
+
:param str [params.positionSide]: 'long' or 'short' - required for hedged mode in isolated margin
|
2121
2168
|
:returns dict: response from the exchange
|
2122
2169
|
"""
|
2123
2170
|
if symbol is None:
|
@@ -2239,13 +2286,97 @@ class blofin(Exchange, ImplicitAPI):
|
|
2239
2286
|
data = self.safe_dict(response, 'data', {})
|
2240
2287
|
return self.parse_margin_mode(data, market)
|
2241
2288
|
|
2242
|
-
def parse_margin_mode(self, marginMode: dict, market=None) -> MarginMode:
|
2289
|
+
def parse_margin_mode(self, marginMode: dict, market: Market = None) -> MarginMode:
|
2243
2290
|
return {
|
2244
2291
|
'info': marginMode,
|
2245
|
-
'symbol': market
|
2292
|
+
'symbol': self.safe_string(market, 'symbol'),
|
2246
2293
|
'marginMode': self.safe_string(marginMode, 'marginMode'),
|
2247
2294
|
}
|
2248
2295
|
|
2296
|
+
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
2297
|
+
"""
|
2298
|
+
set margin mode to 'cross' or 'isolated'
|
2299
|
+
|
2300
|
+
https://docs.blofin.com/index.html#set-margin-mode
|
2301
|
+
|
2302
|
+
:param str marginMode: 'cross' or 'isolated'
|
2303
|
+
:param str [symbol]: unified market symbol(not used in blofin setMarginMode)
|
2304
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2305
|
+
:returns dict: response from the exchange
|
2306
|
+
"""
|
2307
|
+
self.check_required_argument('setMarginMode', marginMode, 'marginMode', ['cross', 'isolated'])
|
2308
|
+
self.load_markets()
|
2309
|
+
market = None
|
2310
|
+
if symbol is not None:
|
2311
|
+
market = self.market(symbol)
|
2312
|
+
request: dict = {
|
2313
|
+
'marginMode': marginMode,
|
2314
|
+
}
|
2315
|
+
response = self.privatePostAccountSetMarginMode(self.extend(request, params))
|
2316
|
+
#
|
2317
|
+
# {
|
2318
|
+
# "code": "0",
|
2319
|
+
# "msg": "success",
|
2320
|
+
# "data": {
|
2321
|
+
# "marginMode": "isolated"
|
2322
|
+
# }
|
2323
|
+
# }
|
2324
|
+
#
|
2325
|
+
data = self.safe_dict(response, 'data', {})
|
2326
|
+
return self.parse_margin_mode(data, market)
|
2327
|
+
|
2328
|
+
def fetch_position_mode(self, symbol: Str = None, params={}):
|
2329
|
+
"""
|
2330
|
+
fetchs the position mode, hedged or one way
|
2331
|
+
|
2332
|
+
https://docs.blofin.com/index.html#get-position-mode
|
2333
|
+
|
2334
|
+
:param str [symbol]: unified symbol of the market to fetch the position mode for(not used in blofin fetchPositionMode)
|
2335
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2336
|
+
:returns dict: an object detailing whether the market is in hedged or one-way mode
|
2337
|
+
"""
|
2338
|
+
response = self.privateGetAccountPositionMode(params)
|
2339
|
+
data = self.safe_dict(response, 'data', {})
|
2340
|
+
positionMode = self.safe_string(data, 'positionMode')
|
2341
|
+
#
|
2342
|
+
# {
|
2343
|
+
# "code": "0",
|
2344
|
+
# "msg": "success",
|
2345
|
+
# "data": {
|
2346
|
+
# "positionMode": "long_short_mode"
|
2347
|
+
# }
|
2348
|
+
# }
|
2349
|
+
#
|
2350
|
+
return {
|
2351
|
+
'info': data,
|
2352
|
+
'hedged': positionMode == 'long_short_mode',
|
2353
|
+
}
|
2354
|
+
|
2355
|
+
def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
|
2356
|
+
"""
|
2357
|
+
set hedged to True or False for a market
|
2358
|
+
|
2359
|
+
https://docs.blofin.com/index.html#set-position-mode
|
2360
|
+
|
2361
|
+
:param bool hedged: set to True to use hedged mode, False for one-way mode
|
2362
|
+
:param str [symbol]: not used by blofin setPositionMode()
|
2363
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2364
|
+
:returns dict: response from the exchange
|
2365
|
+
"""
|
2366
|
+
request: dict = {
|
2367
|
+
'positionMode': 'long_short_mode' if hedged else 'net_mode',
|
2368
|
+
}
|
2369
|
+
#
|
2370
|
+
# {
|
2371
|
+
# "code": "0",
|
2372
|
+
# "msg": "success",
|
2373
|
+
# "data": {
|
2374
|
+
# "positionMode": "net_mode"
|
2375
|
+
# }
|
2376
|
+
# }
|
2377
|
+
#
|
2378
|
+
return self.privatePostAccountSetPositionMode(self.extend(request, params))
|
2379
|
+
|
2249
2380
|
def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
2250
2381
|
if response is None:
|
2251
2382
|
return None # fallback to default error handler
|
ccxt/btcbox.py
CHANGED
@@ -115,6 +115,18 @@ class btcbox(Exchange, ImplicitAPI):
|
|
115
115
|
'wallet',
|
116
116
|
],
|
117
117
|
},
|
118
|
+
'webApi': {
|
119
|
+
'get': [
|
120
|
+
'ajax/coin/coinInfo',
|
121
|
+
],
|
122
|
+
},
|
123
|
+
},
|
124
|
+
'options': {
|
125
|
+
'fetchMarkets': {
|
126
|
+
'webApiEnable': True, # fetches from WEB
|
127
|
+
'webApiRetries': 3,
|
128
|
+
},
|
129
|
+
'amountPrecision': '0.0001', # exchange has only few pairs and all of them
|
118
130
|
},
|
119
131
|
'features': {
|
120
132
|
'spot': {
|
@@ -198,9 +210,12 @@ class btcbox(Exchange, ImplicitAPI):
|
|
198
210
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
199
211
|
:returns dict[]: an array of objects representing market data
|
200
212
|
"""
|
201
|
-
|
213
|
+
promise1 = self.publicGetTickers()
|
214
|
+
promise2 = self.fetch_web_endpoint('fetchMarkets', 'webApiGetAjaxCoinCoinInfo', True)
|
215
|
+
response1, response2 = [promise1, promise2]
|
202
216
|
#
|
203
|
-
|
217
|
+
result2Data = self.safe_dict(response2, 'data', {})
|
218
|
+
marketIds = list(response1.keys())
|
204
219
|
markets = []
|
205
220
|
for i in range(0, len(marketIds)):
|
206
221
|
marketId = marketIds[i]
|
@@ -209,9 +224,11 @@ class btcbox(Exchange, ImplicitAPI):
|
|
209
224
|
quote = self.safe_string(symbolParts, 1)
|
210
225
|
quoteId = quote.lower()
|
211
226
|
id = baseCurr.lower()
|
212
|
-
res =
|
227
|
+
res = response1[marketId]
|
213
228
|
symbol = baseCurr + '/' + quote
|
214
229
|
fee = self.parse_number('0.0005') if (id == 'BTC') else self.parse_number('0.0010')
|
230
|
+
details = self.safe_dict(result2Data, id, {})
|
231
|
+
tradeDetails = self.safe_dict(details, 'trade', {})
|
215
232
|
markets.append(self.safe_market_structure({
|
216
233
|
'id': id,
|
217
234
|
'uppercaseId': None,
|
@@ -257,10 +274,10 @@ class btcbox(Exchange, ImplicitAPI):
|
|
257
274
|
},
|
258
275
|
},
|
259
276
|
'precision': {
|
260
|
-
'price':
|
277
|
+
'price': self.parse_number(self.parse_precision(self.safe_string(tradeDetails, 'pricedecimal'))),
|
261
278
|
'amount': None,
|
262
279
|
},
|
263
|
-
'active':
|
280
|
+
'active': self.safe_string(tradeDetails, 'enable') == '1',
|
264
281
|
'created': None,
|
265
282
|
'info': res,
|
266
283
|
}))
|
@@ -717,6 +734,8 @@ class btcbox(Exchange, ImplicitAPI):
|
|
717
734
|
if api == 'public':
|
718
735
|
if params:
|
719
736
|
url += '?' + self.urlencode(params)
|
737
|
+
elif api == 'webApi':
|
738
|
+
url = self.urls['www'] + '/' + path
|
720
739
|
else:
|
721
740
|
self.check_required_credentials()
|
722
741
|
nonce = str(self.nonce())
|
ccxt/bybit.py
CHANGED
@@ -1634,77 +1634,57 @@ class bybit(Exchange, ImplicitAPI):
|
|
1634
1634
|
name = self.safe_string(currency, 'name')
|
1635
1635
|
chains = self.safe_list(currency, 'chains', [])
|
1636
1636
|
networks: dict = {}
|
1637
|
-
minPrecision = None
|
1638
|
-
minWithdrawFeeString = None
|
1639
|
-
minWithdrawString = None
|
1640
|
-
minDepositString = None
|
1641
|
-
deposit = False
|
1642
|
-
withdraw = False
|
1643
1637
|
for j in range(0, len(chains)):
|
1644
1638
|
chain = chains[j]
|
1645
1639
|
networkId = self.safe_string(chain, 'chain')
|
1646
1640
|
networkCode = self.network_id_to_code(networkId)
|
1647
|
-
precision = self.parse_number(self.parse_precision(self.safe_string(chain, 'minAccuracy')))
|
1648
|
-
minPrecision = precision if (minPrecision is None) else min(minPrecision, precision)
|
1649
|
-
depositAllowed = self.safe_integer(chain, 'chainDeposit') == 1
|
1650
|
-
deposit = depositAllowed if (depositAllowed) else deposit
|
1651
|
-
withdrawAllowed = self.safe_integer(chain, 'chainWithdraw') == 1
|
1652
|
-
withdraw = withdrawAllowed if (withdrawAllowed) else withdraw
|
1653
|
-
withdrawFeeString = self.safe_string(chain, 'withdrawFee')
|
1654
|
-
if withdrawFeeString is not None:
|
1655
|
-
minWithdrawFeeString = withdrawFeeString if (minWithdrawFeeString is None) else Precise.string_min(withdrawFeeString, minWithdrawFeeString)
|
1656
|
-
minNetworkWithdrawString = self.safe_string(chain, 'withdrawMin')
|
1657
|
-
if minNetworkWithdrawString is not None:
|
1658
|
-
minWithdrawString = minNetworkWithdrawString if (minWithdrawString is None) else Precise.string_min(minNetworkWithdrawString, minWithdrawString)
|
1659
|
-
minNetworkDepositString = self.safe_string(chain, 'depositMin')
|
1660
|
-
if minNetworkDepositString is not None:
|
1661
|
-
minDepositString = minNetworkDepositString if (minDepositString is None) else Precise.string_min(minNetworkDepositString, minDepositString)
|
1662
1641
|
networks[networkCode] = {
|
1663
1642
|
'info': chain,
|
1664
1643
|
'id': networkId,
|
1665
1644
|
'network': networkCode,
|
1666
|
-
'active':
|
1667
|
-
'deposit':
|
1668
|
-
'withdraw':
|
1669
|
-
'fee': self.
|
1670
|
-
'precision':
|
1645
|
+
'active': None,
|
1646
|
+
'deposit': self.safe_integer(chain, 'chainDeposit') == 1,
|
1647
|
+
'withdraw': self.safe_integer(chain, 'chainWithdraw') == 1,
|
1648
|
+
'fee': self.safe_number(chain, 'withdrawFee'),
|
1649
|
+
'precision': self.parse_number(self.parse_precision(self.safe_string(chain, 'minAccuracy'))),
|
1671
1650
|
'limits': {
|
1672
1651
|
'withdraw': {
|
1673
|
-
'min': self.
|
1652
|
+
'min': self.safe_number(chain, 'withdrawMin'),
|
1674
1653
|
'max': None,
|
1675
1654
|
},
|
1676
1655
|
'deposit': {
|
1677
|
-
'min': self.
|
1656
|
+
'min': self.safe_number(chain, 'depositMin'),
|
1678
1657
|
'max': None,
|
1679
1658
|
},
|
1680
1659
|
},
|
1681
1660
|
}
|
1682
|
-
result[code] = {
|
1661
|
+
result[code] = self.safe_currency_structure({
|
1683
1662
|
'info': currency,
|
1684
1663
|
'code': code,
|
1685
1664
|
'id': currencyId,
|
1686
1665
|
'name': name,
|
1687
|
-
'active':
|
1688
|
-
'deposit':
|
1689
|
-
'withdraw':
|
1690
|
-
'fee':
|
1691
|
-
'precision':
|
1666
|
+
'active': None,
|
1667
|
+
'deposit': None,
|
1668
|
+
'withdraw': None,
|
1669
|
+
'fee': None,
|
1670
|
+
'precision': None,
|
1692
1671
|
'limits': {
|
1693
1672
|
'amount': {
|
1694
1673
|
'min': None,
|
1695
1674
|
'max': None,
|
1696
1675
|
},
|
1697
1676
|
'withdraw': {
|
1698
|
-
'min':
|
1677
|
+
'min': None,
|
1699
1678
|
'max': None,
|
1700
1679
|
},
|
1701
1680
|
'deposit': {
|
1702
|
-
'min':
|
1681
|
+
'min': None,
|
1703
1682
|
'max': None,
|
1704
1683
|
},
|
1705
1684
|
},
|
1706
1685
|
'networks': networks,
|
1707
|
-
|
1686
|
+
'type': 'crypto', # atm exchange api provides only cryptos
|
1687
|
+
})
|
1708
1688
|
return result
|
1709
1689
|
|
1710
1690
|
def fetch_markets(self, params={}) -> List[Market]:
|
@@ -2127,6 +2107,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
2127
2107
|
strike = self.safe_string(splitId, 2)
|
2128
2108
|
optionLetter = self.safe_string(splitId, 3)
|
2129
2109
|
isActive = (status == 'Trading')
|
2110
|
+
isInverse = base == settle
|
2130
2111
|
if isActive or (self.options['loadAllOptions']) or (self.options['loadExpiredOptions']):
|
2131
2112
|
result.append(self.safe_market_structure({
|
2132
2113
|
'id': id,
|
@@ -2146,8 +2127,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
2146
2127
|
'option': True,
|
2147
2128
|
'active': isActive,
|
2148
2129
|
'contract': True,
|
2149
|
-
'linear':
|
2150
|
-
'inverse':
|
2130
|
+
'linear': not isInverse,
|
2131
|
+
'inverse': isInverse,
|
2151
2132
|
'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
|
2152
2133
|
'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
|
2153
2134
|
'contractSize': self.parse_number('1'),
|
ccxt/cex.py
CHANGED
@@ -310,8 +310,6 @@ class cex(Exchange, ImplicitAPI):
|
|
310
310
|
id = self.safe_string(rawCurrency, 'currency')
|
311
311
|
code = self.safe_currency_code(id)
|
312
312
|
type = 'fiat' if self.safe_bool(rawCurrency, 'fiat') else 'crypto'
|
313
|
-
currencyDepositEnabled = self.safe_bool(rawCurrency, 'walletDeposit')
|
314
|
-
currencyWithdrawEnabled = self.safe_bool(rawCurrency, 'walletWithdrawal')
|
315
313
|
currencyPrecision = self.parse_number(self.parse_precision(self.safe_string(rawCurrency, 'precision')))
|
316
314
|
networks: dict = {}
|
317
315
|
rawNetworks = self.safe_dict(rawCurrency, 'blockchains', {})
|
@@ -349,8 +347,8 @@ class cex(Exchange, ImplicitAPI):
|
|
349
347
|
'name': None,
|
350
348
|
'type': type,
|
351
349
|
'active': None,
|
352
|
-
'deposit':
|
353
|
-
'withdraw':
|
350
|
+
'deposit': self.safe_bool(rawCurrency, 'walletDeposit'),
|
351
|
+
'withdraw': self.safe_bool(rawCurrency, 'walletWithdrawal'),
|
354
352
|
'fee': None,
|
355
353
|
'precision': currencyPrecision,
|
356
354
|
'limits': {
|
ccxt/coinbase.py
CHANGED
@@ -1832,45 +1832,46 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1832
1832
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1833
1833
|
:returns dict: an associative dictionary of currencies
|
1834
1834
|
"""
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
# name: 'Isle of Man Pound',
|
1843
|
-
# min_size: '0.01'
|
1844
|
-
# },
|
1845
|
-
#
|
1846
|
-
# crypto
|
1847
|
-
#
|
1848
|
-
# {
|
1849
|
-
# asset_id: '9476e3be-b731-47fa-82be-347fabc573d9',
|
1850
|
-
# code: 'AERO',
|
1851
|
-
# name: 'Aerodrome Finance',
|
1852
|
-
# color: '#0433FF',
|
1853
|
-
# sort_index: '340',
|
1854
|
-
# exponent: '8',
|
1855
|
-
# type: 'crypto',
|
1856
|
-
# address_regex: '^(?:0x)?[0-9a-fA-F]{40}$'
|
1857
|
-
# }
|
1835
|
+
promises = [
|
1836
|
+
self.v2PublicGetCurrencies(params),
|
1837
|
+
self.v2PublicGetCurrenciesCrypto(params),
|
1838
|
+
self.v2PublicGetExchangeRates(params),
|
1839
|
+
]
|
1840
|
+
promisesResult = promises
|
1841
|
+
fiatResponse = self.safe_dict(promisesResult, 0, {})
|
1858
1842
|
#
|
1843
|
+
# [
|
1844
|
+
# "data": [
|
1845
|
+
# {
|
1846
|
+
# id: 'IMP',
|
1847
|
+
# name: 'Isle of Man Pound',
|
1848
|
+
# min_size: '0.01'
|
1849
|
+
# },
|
1850
|
+
# ...
|
1859
1851
|
#
|
1860
|
-
|
1861
|
-
# "data":{
|
1862
|
-
# "currency":"USD",
|
1863
|
-
# "rates":{
|
1864
|
-
# "AED":"3.67",
|
1865
|
-
# "AFN":"78.21",
|
1866
|
-
# "ALL":"110.42",
|
1867
|
-
# "AMD":"474.18",
|
1868
|
-
# "ANG":"1.75",
|
1869
|
-
# ...
|
1870
|
-
# },
|
1871
|
-
# }
|
1872
|
-
# }
|
1852
|
+
cryptoResponse = self.safe_dict(promisesResult, 1, {})
|
1873
1853
|
#
|
1854
|
+
# [
|
1855
|
+
# "data": [
|
1856
|
+
# {
|
1857
|
+
# asset_id: '9476e3be-b731-47fa-82be-347fabc573d9',
|
1858
|
+
# code: 'AERO',
|
1859
|
+
# name: 'Aerodrome Finance',
|
1860
|
+
# color: '#0433FF',
|
1861
|
+
# sort_index: '340',
|
1862
|
+
# exponent: '8',
|
1863
|
+
# type: 'crypto',
|
1864
|
+
# address_regex: '^(?:0x)?[0-9a-fA-F]{40}$'
|
1865
|
+
# },
|
1866
|
+
# ...
|
1867
|
+
#
|
1868
|
+
ratesResponse = self.safe_dict(promisesResult, 2, {})
|
1869
|
+
fiatData = self.safe_list(fiatResponse, 'data', [])
|
1870
|
+
cryptoData = self.safe_list(cryptoResponse, 'data', [])
|
1871
|
+
ratesData = self.safe_dict(ratesResponse, 'data', {})
|
1872
|
+
rates = self.safe_dict(ratesData, 'rates', {})
|
1873
|
+
ratesIds = list(rates.keys())
|
1874
|
+
currencies = self.array_concat(fiatData, cryptoData)
|
1874
1875
|
result: dict = {}
|
1875
1876
|
networks: dict = {}
|
1876
1877
|
networksById: dict = {}
|
@@ -1882,18 +1883,19 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1882
1883
|
name = self.safe_string(currency, 'name')
|
1883
1884
|
self.options['networks'][code] = name.lower()
|
1884
1885
|
self.options['networksById'][code] = name.lower()
|
1885
|
-
|
1886
|
-
|
1886
|
+
type = 'crypto' if (assetId is not None) else 'fiat'
|
1887
|
+
result[code] = self.safe_currency_structure({
|
1888
|
+
'info': currency,
|
1887
1889
|
'id': id,
|
1888
1890
|
'code': code,
|
1889
|
-
'type':
|
1890
|
-
'name':
|
1891
|
+
'type': type,
|
1892
|
+
'name': name,
|
1891
1893
|
'active': True,
|
1892
1894
|
'deposit': None,
|
1893
1895
|
'withdraw': None,
|
1894
1896
|
'fee': None,
|
1895
1897
|
'precision': None,
|
1896
|
-
'networks': {},
|
1898
|
+
'networks': {}, # todo
|
1897
1899
|
'limits': {
|
1898
1900
|
'amount': {
|
1899
1901
|
'min': self.safe_number(currency, 'min_size'),
|
@@ -1904,11 +1906,23 @@ class coinbase(Exchange, ImplicitAPI):
|
|
1904
1906
|
'max': None,
|
1905
1907
|
},
|
1906
1908
|
},
|
1907
|
-
}
|
1909
|
+
})
|
1908
1910
|
if assetId is not None:
|
1909
1911
|
lowerCaseName = name.lower()
|
1910
1912
|
networks[code] = lowerCaseName
|
1911
1913
|
networksById[lowerCaseName] = code
|
1914
|
+
# we have to add other currencies here( https://discord.com/channels/1220414409550336183/1220464770239430761/1372215891940479098 )
|
1915
|
+
for i in range(0, len(ratesIds)):
|
1916
|
+
currencyId = ratesIds[i]
|
1917
|
+
code = self.safe_currency_code(currencyId)
|
1918
|
+
if not (code in result):
|
1919
|
+
result[code] = self.safe_currency_structure({
|
1920
|
+
'info': {},
|
1921
|
+
'id': currencyId,
|
1922
|
+
'code': code,
|
1923
|
+
'type': 'crypto',
|
1924
|
+
'networks': {}, # todo
|
1925
|
+
})
|
1912
1926
|
self.options['networks'] = self.extend(networks, self.options['networks'])
|
1913
1927
|
self.options['networksById'] = self.extend(networksById, self.options['networksById'])
|
1914
1928
|
return result
|