ccxt 4.4.88__py2.py3-none-any.whl → 4.4.91__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.
Files changed (101) hide show
  1. ccxt/__init__.py +1 -3
  2. ccxt/abstract/bitget.py +58 -0
  3. ccxt/abstract/bitrue.py +65 -65
  4. ccxt/abstract/cryptocom.py +2 -0
  5. ccxt/abstract/luno.py +1 -0
  6. ccxt/async_support/__init__.py +1 -3
  7. ccxt/async_support/base/exchange.py +6 -3
  8. ccxt/async_support/base/ws/client.py +173 -64
  9. ccxt/async_support/base/ws/future.py +23 -50
  10. ccxt/async_support/binance.py +2 -2
  11. ccxt/async_support/bingx.py +55 -29
  12. ccxt/async_support/bitget.py +469 -147
  13. ccxt/async_support/bitmex.py +2 -1
  14. ccxt/async_support/bitrue.py +72 -66
  15. ccxt/async_support/bitvavo.py +34 -0
  16. ccxt/async_support/btcalpha.py +35 -0
  17. ccxt/async_support/btcbox.py +35 -0
  18. ccxt/async_support/btcmarkets.py +35 -0
  19. ccxt/async_support/btcturk.py +35 -0
  20. ccxt/async_support/bybit.py +9 -3
  21. ccxt/async_support/cex.py +61 -0
  22. ccxt/async_support/coinbase.py +1 -3
  23. ccxt/async_support/cryptocom.py +66 -2
  24. ccxt/async_support/cryptomus.py +1 -1
  25. ccxt/async_support/delta.py +2 -2
  26. ccxt/async_support/digifinex.py +39 -99
  27. ccxt/async_support/exmo.py +14 -7
  28. ccxt/async_support/gate.py +14 -7
  29. ccxt/async_support/hashkey.py +15 -28
  30. ccxt/async_support/hollaex.py +27 -22
  31. ccxt/async_support/hyperliquid.py +104 -53
  32. ccxt/async_support/kraken.py +54 -50
  33. ccxt/async_support/luno.py +87 -1
  34. ccxt/async_support/mexc.py +1 -0
  35. ccxt/async_support/modetrade.py +2 -2
  36. ccxt/async_support/okx.py +2 -1
  37. ccxt/async_support/paradex.py +1 -1
  38. ccxt/async_support/phemex.py +16 -8
  39. ccxt/async_support/tradeogre.py +3 -3
  40. ccxt/async_support/xt.py +1 -1
  41. ccxt/base/exchange.py +20 -8
  42. ccxt/binance.py +2 -2
  43. ccxt/bingx.py +55 -29
  44. ccxt/bitget.py +469 -147
  45. ccxt/bitmex.py +2 -1
  46. ccxt/bitrue.py +72 -66
  47. ccxt/bitvavo.py +34 -0
  48. ccxt/btcalpha.py +35 -0
  49. ccxt/btcbox.py +35 -0
  50. ccxt/btcmarkets.py +35 -0
  51. ccxt/btcturk.py +35 -0
  52. ccxt/bybit.py +9 -3
  53. ccxt/cex.py +61 -0
  54. ccxt/coinbase.py +1 -3
  55. ccxt/cryptocom.py +66 -2
  56. ccxt/cryptomus.py +1 -1
  57. ccxt/delta.py +2 -2
  58. ccxt/digifinex.py +39 -99
  59. ccxt/exmo.py +13 -7
  60. ccxt/gate.py +14 -7
  61. ccxt/hashkey.py +15 -28
  62. ccxt/hollaex.py +27 -22
  63. ccxt/hyperliquid.py +104 -53
  64. ccxt/kraken.py +53 -50
  65. ccxt/luno.py +87 -1
  66. ccxt/mexc.py +1 -0
  67. ccxt/modetrade.py +2 -2
  68. ccxt/okx.py +2 -1
  69. ccxt/paradex.py +1 -1
  70. ccxt/phemex.py +16 -8
  71. ccxt/pro/__init__.py +1 -127
  72. ccxt/pro/bitstamp.py +1 -1
  73. ccxt/pro/bybit.py +6 -136
  74. ccxt/pro/coinbase.py +2 -0
  75. ccxt/pro/cryptocom.py +27 -0
  76. ccxt/pro/kraken.py +249 -267
  77. ccxt/pro/mexc.py +0 -1
  78. ccxt/tradeogre.py +3 -3
  79. ccxt/xt.py +1 -1
  80. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/METADATA +64 -23
  81. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/RECORD +84 -101
  82. ccxt/abstract/coinlist.py +0 -57
  83. ccxt/async_support/base/ws/aiohttp_client.py +0 -147
  84. ccxt/async_support/bitcoincom.py +0 -18
  85. ccxt/async_support/bitfinex1.py +0 -1711
  86. ccxt/async_support/bitpanda.py +0 -17
  87. ccxt/async_support/coinlist.py +0 -2542
  88. ccxt/async_support/poloniexfutures.py +0 -1875
  89. ccxt/bitcoincom.py +0 -18
  90. ccxt/bitfinex1.py +0 -1710
  91. ccxt/bitpanda.py +0 -17
  92. ccxt/coinlist.py +0 -2542
  93. ccxt/poloniexfutures.py +0 -1875
  94. ccxt/pro/bitcoincom.py +0 -35
  95. ccxt/pro/bitfinex1.py +0 -635
  96. ccxt/pro/bitpanda.py +0 -16
  97. ccxt/pro/poloniexfutures.py +0 -1004
  98. ccxt/pro/wazirx.py +0 -766
  99. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
  100. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
  101. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
@@ -1,1875 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
- # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
-
6
- from ccxt.async_support.base.exchange import Exchange
7
- from ccxt.abstract.poloniexfutures import ImplicitAPI
8
- import hashlib
9
- from ccxt.base.types import Any, Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade
10
- from typing import List
11
- from ccxt.base.errors import AuthenticationError
12
- from ccxt.base.errors import AccountSuspended
13
- from ccxt.base.errors import ArgumentsRequired
14
- from ccxt.base.errors import BadRequest
15
- from ccxt.base.errors import InvalidOrder
16
- from ccxt.base.errors import OrderNotFound
17
- from ccxt.base.errors import NotSupported
18
- from ccxt.base.errors import RateLimitExceeded
19
- from ccxt.base.errors import ExchangeNotAvailable
20
- from ccxt.base.errors import InvalidNonce
21
- from ccxt.base.decimal_to_precision import TICK_SIZE
22
- from ccxt.base.precise import Precise
23
-
24
-
25
- class poloniexfutures(Exchange, ImplicitAPI):
26
-
27
- def describe(self) -> Any:
28
- return self.deep_extend(super(poloniexfutures, self).describe(), {
29
- 'id': 'poloniexfutures',
30
- 'name': 'Poloniex Futures',
31
- 'countries': ['US'],
32
- # 30 requests per second
33
- 'rateLimit': 33.3,
34
- 'certified': False,
35
- 'pro': True,
36
- 'version': 'v1',
37
- 'has': {
38
- 'CORS': None,
39
- 'spot': False,
40
- 'margin': True,
41
- 'swap': True,
42
- 'future': False,
43
- 'option': None,
44
- 'createOrder': True,
45
- 'createStopOrder': True,
46
- 'createTriggerOrder': True,
47
- 'fetchBalance': True,
48
- 'fetchClosedOrders': True,
49
- 'fetchCurrencies': False,
50
- 'fetchDepositAddress': False,
51
- 'fetchDepositAddresses': False,
52
- 'fetchDepositAddressesByNetwork': False,
53
- 'fetchFundingInterval': True,
54
- 'fetchFundingIntervals': False,
55
- 'fetchFundingRate': True,
56
- 'fetchFundingRateHistory': False,
57
- 'fetchL3OrderBook': True,
58
- 'fetchMarkets': True,
59
- 'fetchMyTrades': True,
60
- 'fetchOHLCV': True,
61
- 'fetchOpenOrders': True,
62
- 'fetchOrder': True,
63
- 'fetchOrderBook': True,
64
- 'fetchOrdersByStatus': True,
65
- 'fetchPositions': True,
66
- 'fetchTicker': True,
67
- 'fetchTickers': True,
68
- 'fetchTime': True,
69
- 'fetchTrades': True,
70
- 'setMarginMode': True,
71
- },
72
- 'timeframes': {
73
- '1m': 1,
74
- '5m': 5,
75
- '15m': 15,
76
- '30m': 30,
77
- '1h': 60,
78
- '2h': 120,
79
- '4h': 480,
80
- '12h': 720,
81
- '1d': 1440,
82
- '1w': 10080,
83
- },
84
- 'urls': {
85
- 'logo': 'https://user-images.githubusercontent.com/1294454/27766817-e9456312-5ee6-11e7-9b3c-b628ca5626a5.jpg',
86
- 'api': {
87
- 'public': 'https://futures-api.poloniex.com',
88
- 'private': 'https://futures-api.poloniex.com',
89
- },
90
- 'www': 'https://www.poloniex.com',
91
- 'doc': 'https://api-docs.poloniex.com/futures/',
92
- 'fees': 'https://poloniex.com/fee-schedule',
93
- 'referral': 'https://poloniex.com/signup?c=UBFZJRPJ',
94
- },
95
- 'api': {
96
- 'public': {
97
- 'get': {
98
- 'contracts/active': 10,
99
- 'contracts/{symbol}': 10,
100
- 'ticker': 10,
101
- 'tickers': 10, # v2
102
- 'level2/snapshot': 180.002,
103
- 'level2/depth': 180.002,
104
- 'level2/message/query': 180.002,
105
- 'level3/snapshot': 180.002, # v2
106
- 'trade/history': 10,
107
- 'interest/query': 10,
108
- 'index/query': 10,
109
- 'mark-price/{symbol}/current': 10,
110
- 'premium/query': 10,
111
- 'funding-rate/{symbol}/current': 10,
112
- 'timestamp': 10,
113
- 'status': 10,
114
- 'kline/query': 10,
115
- },
116
- 'post': {
117
- 'bullet-public': 10,
118
- },
119
- },
120
- 'private': {
121
- 'get': {
122
- 'account-overview': 1,
123
- 'transaction-history': 1,
124
- 'maxActiveOrders': 1,
125
- 'maxRiskLimit': 1,
126
- 'userFeeRate': 1,
127
- 'marginType/query': 1,
128
- 'orders': 1,
129
- 'stopOrders': 1,
130
- 'recentDoneOrders': 1,
131
- 'orders/{order-id}': 1,
132
- 'clientOrderId/{clientOid}': 1,
133
- 'fills': 1,
134
- 'openOrderStatistics': 1,
135
- 'position': 1.5,
136
- 'positions': 1.5,
137
- 'funding-history': 1,
138
- },
139
- 'post': {
140
- 'orders': 1.5,
141
- 'batchOrders': 1.5,
142
- 'position/margin/auto-deposit-status': 1.5,
143
- 'position/margin/deposit-margin': 1.5,
144
- 'position/margin/withdraw-margin': 1.5,
145
- 'bullet-private': 1,
146
- 'marginType/change': 1,
147
- },
148
- 'delete': {
149
- 'orders/{order-id}': 1.5,
150
- 'orders': 150.016,
151
- 'stopOrders': 150.016,
152
- },
153
- },
154
- },
155
- 'precisionMode': TICK_SIZE,
156
- 'fees': {
157
- 'trading': {
158
- 'tierBased': False,
159
- 'percentage': True,
160
- 'taker': self.parse_number('0.00075'),
161
- 'maker': self.parse_number('0.0001'),
162
- },
163
- 'funding': {
164
- 'tierBased': False,
165
- 'percentage': False,
166
- 'withdraw': {},
167
- 'deposit': {},
168
- },
169
- },
170
- 'commonCurrencies': {
171
- },
172
- 'requiredCredentials': {
173
- 'apiKey': True,
174
- 'secret': True,
175
- 'password': True,
176
- },
177
- 'options': {
178
- 'networks': {
179
- 'OMNI': 'omni',
180
- 'ERC20': 'eth',
181
- 'TRC20': 'trx',
182
- },
183
- 'versions': {
184
- 'public': {
185
- 'GET': {
186
- 'ticker': 'v2',
187
- 'tickers': 'v2',
188
- 'level3/snapshot': 'v2',
189
- },
190
- },
191
- },
192
- },
193
- 'features': {
194
- 'default': {
195
- 'sandbox': False,
196
- 'createOrder': {
197
- 'marginMode': False,
198
- 'triggerPrice': True,
199
- # todo implementation
200
- 'triggerPriceType': {
201
- 'last': True,
202
- 'mark': True,
203
- 'index': True,
204
- },
205
- 'triggerDirection': True,
206
- 'stopLossPrice': False, # todo
207
- 'takeProfitPrice': False, # todo
208
- 'attachedStopLossTakeProfit': None,
209
- 'timeInForce': {
210
- 'IOC': True,
211
- 'FOK': False,
212
- 'PO': True,
213
- 'GTD': False,
214
- },
215
- 'hedged': False,
216
- 'leverage': True, # deprecated?
217
- 'marketBuyByCost': True,
218
- 'marketBuyRequiresPrice': False,
219
- 'selfTradePrevention': False,
220
- 'trailing': False,
221
- 'iceberg': True, # deprecated?
222
- },
223
- 'createOrders': None,
224
- 'fetchMyTrades': {
225
- 'marginMode': False,
226
- 'limit': None,
227
- 'daysBack': 100000,
228
- 'untilDays': 7,
229
- 'symbolRequired': False,
230
- },
231
- 'fetchOrder': {
232
- 'marginMode': False,
233
- 'trigger': False,
234
- 'trailing': False,
235
- 'symbolRequired': False,
236
- },
237
- 'fetchOpenOrders': {
238
- 'marginMode': True,
239
- 'limit': None,
240
- 'trigger': False,
241
- 'trailing': False,
242
- 'symbolRequired': False,
243
- },
244
- 'fetchOrders': None, # todo
245
- 'fetchClosedOrders': {
246
- 'marginMode': False,
247
- 'limit': 100,
248
- 'daysBack': 100000,
249
- 'daysBackCanceled': 1,
250
- 'untilDays': 100000,
251
- 'trigger': False,
252
- 'trailing': False,
253
- 'symbolRequired': False,
254
- },
255
- 'fetchOHLCV': {
256
- 'limit': 200, # todo implement
257
- },
258
- },
259
- 'spot': None,
260
- 'swap': {
261
- 'linear': {
262
- 'extends': 'default',
263
- },
264
- 'inverse': None,
265
- },
266
- 'future': {
267
- 'linear': None,
268
- 'inverse': None,
269
- },
270
- },
271
- 'exceptions': {
272
- 'exact': {
273
- '400': BadRequest, # Bad Request -- Invalid request format
274
- '401': AuthenticationError, # Unauthorized -- Invalid API Key
275
- '403': NotSupported, # Forbidden -- The request is forbidden
276
- '404': NotSupported, # Not Found -- The specified resource could not be found
277
- '405': NotSupported, # Method Not Allowed -- You tried to access the resource with an invalid method.
278
- '415': BadRequest, # Content-Type -- application/json
279
- '429': RateLimitExceeded, # Too Many Requests -- Access limit breached
280
- '500': ExchangeNotAvailable, # Internal Server Error -- We had a problem with our server. Try again later.
281
- '503': ExchangeNotAvailable, # Service Unavailable -- We're temporarily offline for maintenance. Please try again later.
282
- '400001': AuthenticationError, # Any of KC-API-KEY, KC-API-SIGN, KC-API-TIMESTAMP, KC-API-PASSPHRASE is missing in your request header.
283
- '400002': InvalidNonce, # KC-API-TIMESTAMP Invalid -- Time differs from server time by more than 5 seconds
284
- '400003': AuthenticationError, # KC-API-KEY not exists
285
- '400004': AuthenticationError, # KC-API-PASSPHRASE error
286
- '400005': AuthenticationError, # Signature error -- Please check your signature
287
- '400006': AuthenticationError, # The IP address is not in the API whitelist
288
- '400007': AuthenticationError, # Access Denied -- Your API key does not have sufficient permissions to access the URI
289
- '404000': NotSupported, # URL Not Found -- The requested resource could not be found
290
- '400100': BadRequest, # Parameter Error -- You tried to access the resource with invalid parameters
291
- '411100': AccountSuspended, # User is frozen -- Please contact us via support center
292
- '500000': ExchangeNotAvailable, # Internal Server Error -- We had a problem with our server. Try again later.
293
- },
294
- 'broad': {
295
- 'Position does not exist': OrderNotFound, # {"code":"200000", "msg":"Position does not exist"}
296
- },
297
- },
298
- })
299
-
300
- async def fetch_markets(self, params={}) -> List[Market]:
301
- """
302
- retrieves data on all markets for poloniexfutures
303
-
304
- https://api-docs.poloniex.com/futures/api/symbol
305
-
306
- :param dict [params]: extra parameters specific to the exchange API endpoint
307
- :returns dict[]: an array of objects representing market data
308
- """
309
- response = await self.publicGetContractsActive(params)
310
- #
311
- # {
312
- # "code": "200000",
313
- # "data": [
314
- # {
315
- # "symbol": "APTUSDTPERP",
316
- # "takerFixFee": "0E-10",
317
- # "nextFundingRateTime": "20145603",
318
- # "makerFixFee": "0E-10",
319
- # "type": "FFWCSX",
320
- # "predictedFundingFeeRate": "0.000000",
321
- # "turnoverOf24h": "386037.46704292",
322
- # "initialMargin": "0.05",
323
- # "isDeleverage": True,
324
- # "createdAt": "1666681959000",
325
- # "fundingBaseSymbol": ".APTINT8H",
326
- # "lowPriceOf24h": "4.34499979019165",
327
- # "lastTradePrice": "4.4090000000",
328
- # "indexPriceTickSize": "0.001",
329
- # "fairMethod": "FundingRate",
330
- # "takerFeeRate": "0.00040",
331
- # "order": "102",
332
- # "updatedAt": "1671076377000",
333
- # "displaySettleCurrency": "USDT",
334
- # "indexPrice": "4.418",
335
- # "multiplier": "1.0",
336
- # "maxLeverage": "20",
337
- # "fundingQuoteSymbol": ".USDTINT8H",
338
- # "quoteCurrency": "USDT",
339
- # "maxOrderQty": "1000000",
340
- # "maxPrice": "1000000.0000000000",
341
- # "maintainMargin": "0.025",
342
- # "status": "Open",
343
- # "displayNameMap": [Object],
344
- # "openInterest": "2367",
345
- # "highPriceOf24h": "4.763999938964844",
346
- # "fundingFeeRate": "0.000000",
347
- # "volumeOf24h": "83540.00000000",
348
- # "riskStep": "500000",
349
- # "isQuanto": True,
350
- # "maxRiskLimit": "20000",
351
- # "rootSymbol": "USDT",
352
- # "baseCurrency": "APT",
353
- # "firstOpenDate": "1666701000000",
354
- # "tickSize": "0.001",
355
- # "markMethod": "FairPrice",
356
- # "indexSymbol": ".PAPTUSDT",
357
- # "markPrice": "4.418",
358
- # "minRiskLimit": "1000000",
359
- # "settlementFixFee": "0E-10",
360
- # "settlementSymbol": '',
361
- # "priceChgPctOf24h": "-0.0704",
362
- # "fundingRateSymbol": ".APTUSDTPERPFPI8H",
363
- # "makerFeeRate": "0.00010",
364
- # "isInverse": False,
365
- # "lotSize": "1",
366
- # "settleCurrency": "USDT",
367
- # "settlementFeeRate": "0.0"
368
- # },
369
- # ]
370
- # }
371
- #
372
- data = self.safe_value(response, 'data', [])
373
- return self.parse_markets(data)
374
-
375
- def parse_market(self, market: dict) -> Market:
376
- id = self.safe_string(market, 'symbol')
377
- baseId = self.safe_string(market, 'baseCurrency')
378
- quoteId = self.safe_string(market, 'quoteCurrency')
379
- settleId = self.safe_string(market, 'rootSymbol')
380
- base = self.safe_currency_code(baseId)
381
- quote = self.safe_currency_code(quoteId)
382
- settle = self.safe_currency_code(settleId)
383
- symbol = base + '/' + quote + ':' + settle
384
- inverse = self.safe_value(market, 'isInverse')
385
- status = self.safe_string(market, 'status')
386
- multiplier = self.safe_string(market, 'multiplier')
387
- tickSize = self.safe_number(market, 'indexPriceTickSize')
388
- lotSize = self.safe_number(market, 'lotSize')
389
- limitAmountMax = self.safe_number(market, 'maxOrderQty')
390
- limitPriceMax = self.safe_number(market, 'maxPrice')
391
- return {
392
- 'id': id,
393
- 'symbol': symbol,
394
- 'base': base,
395
- 'quote': quote,
396
- 'settle': settle,
397
- 'baseId': baseId,
398
- 'quoteId': quoteId,
399
- 'settleId': settleId,
400
- 'type': 'swap',
401
- 'spot': False,
402
- 'margin': False,
403
- 'swap': True,
404
- 'future': False,
405
- 'option': False,
406
- 'active': (status == 'Open'),
407
- 'contract': True,
408
- 'linear': not inverse,
409
- 'inverse': inverse,
410
- 'taker': self.safe_number(market, 'takerFeeRate'),
411
- 'maker': self.safe_number(market, 'makerFeeRate'),
412
- 'contractSize': self.parse_number(Precise.string_abs(multiplier)),
413
- 'expiry': None,
414
- 'expiryDatetime': None,
415
- 'strike': None,
416
- 'optionType': None,
417
- 'precision': {
418
- 'amount': lotSize,
419
- 'price': tickSize,
420
- },
421
- 'limits': {
422
- 'leverage': {
423
- 'min': self.parse_number('1'),
424
- 'max': self.safe_number(market, 'maxLeverage'),
425
- },
426
- 'amount': {
427
- 'min': lotSize,
428
- 'max': limitAmountMax,
429
- },
430
- 'price': {
431
- 'min': tickSize,
432
- 'max': limitPriceMax,
433
- },
434
- 'cost': {
435
- 'min': None,
436
- 'max': None,
437
- },
438
- },
439
- 'created': self.safe_integer(market, 'firstOpenDate'),
440
- 'info': market,
441
- }
442
-
443
- def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
444
- #
445
- # {
446
- # "symbol": "BTCUSDTPERP", # Market of the symbol
447
- # "sequence": 45, # Sequence number which is used to judge the continuity of the pushed messages
448
- # "side": "sell", # Transaction side of the last traded taker order
449
- # "price": 3600.00, # Filled price
450
- # "size": 16, # Filled quantity
451
- # "tradeId": "5c9dcf4170744d6f5a3d32fb", # Order ID
452
- # "bestBidSize": 795, # Best bid size
453
- # "bestBidPrice": 3200.00, # Best bid
454
- # "bestAskPrice": 3600.00, # Best ask size
455
- # "bestAskSize": 284, # Best ask
456
- # "ts": 1553846081210004941 # Filled time - nanosecond
457
- # }
458
- #
459
- # {
460
- # "volume": 30449670, #24h Volume
461
- # "turnover": 845169919063, #24h Turnover
462
- # "lastPrice": 3551, #Last price
463
- # "priceChgPct": 0.0043, #24h Change
464
- # "ts": 1547697294838004923 #Snapshot time(nanosecond)
465
- # }
466
- #
467
- marketId = self.safe_string(ticker, 'symbol')
468
- symbol = self.safe_symbol(marketId, market)
469
- timestampString = self.safe_string(ticker, 'ts')
470
- multiplier = None
471
- if len(timestampString) == 16:
472
- # 16 digits: https://app.travis-ci.com/github/ccxt/ccxt/builds/270587157#L5454
473
- multiplier = 0.001
474
- elif len(timestampString) == 17:
475
- # 17 digits: https://app.travis-ci.com/github/ccxt/ccxt/builds/269959181#L4011
476
- multiplier = 0.0001
477
- elif len(timestampString) == 18:
478
- multiplier = 0.00001
479
- else:
480
- # 19 length default
481
- multiplier = 0.000001
482
- timestamp = self.safe_integer_product(ticker, 'ts', multiplier)
483
- last = self.safe_string_2(ticker, 'price', 'lastPrice')
484
- percentage = Precise.string_mul(self.safe_string(ticker, 'priceChgPct'), '100')
485
- return self.safe_ticker({
486
- 'symbol': symbol,
487
- 'timestamp': timestamp,
488
- 'datetime': self.iso8601(timestamp),
489
- 'high': None,
490
- 'low': None,
491
- 'bid': self.safe_string(ticker, 'bestBidPrice'),
492
- 'bidVolume': self.safe_string(ticker, 'bestBidSize'),
493
- 'ask': self.safe_string(ticker, 'bestAskPrice'),
494
- 'askVolume': self.safe_string(ticker, 'bestAskSize'),
495
- 'vwap': None,
496
- 'open': None,
497
- 'close': last,
498
- 'last': last,
499
- 'previousClose': None,
500
- 'change': None,
501
- 'percentage': percentage,
502
- 'average': None,
503
- 'baseVolume': self.safe_string_2(ticker, 'size', 'volume'),
504
- 'quoteVolume': self.safe_string(ticker, 'turnover'),
505
- 'info': ticker,
506
- }, market)
507
-
508
- async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
509
- """
510
- fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
511
-
512
- https://api-docs.poloniex.com/futures/api/ticker#get-real-time-ticker-20
513
-
514
- :param str symbol: unified symbol of the market to fetch the ticker for
515
- :param dict [params]: extra parameters specific to the exchange API endpoint
516
- :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
517
- """
518
- await self.load_markets()
519
- market = self.market(symbol)
520
- request: dict = {
521
- 'symbol': market['id'],
522
- }
523
- response = await self.publicGetTicker(self.extend(request, params))
524
- #
525
- # {
526
- # "code": "200000",
527
- # "data": {
528
- # "sequence": "11574719",
529
- # "symbol": "BTCUSDTPERP",
530
- # "side": "sell",
531
- # "size": "1",
532
- # "price": "16990.1",
533
- # "bestBidSize": "3",
534
- # "bestBidPrice": "16990.1",
535
- # "bestAskPrice": "16991.0",
536
- # "tradeId": "639c8a529fd7cf0001af4157",
537
- # "bestAskSize": "505",
538
- # "ts": "1671203410721232337"
539
- # }
540
- # }
541
- #
542
- return self.parse_ticker(self.safe_value(response, 'data', {}), market)
543
-
544
- async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
545
- """
546
- fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
547
-
548
- https://api-docs.poloniex.com/futures/api/ticker#get-real-time-ticker-of-all-symbols
549
-
550
- :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
551
- :param dict [params]: extra parameters specific to the exchange API endpoint
552
- :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
553
- """
554
- await self.load_markets()
555
- response = await self.publicGetTickers(params)
556
- data = self.safe_list(response, 'data', [])
557
- return self.parse_tickers(data, symbols)
558
-
559
- async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
560
- """
561
- fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
562
-
563
- https://api-docs.poloniex.com/futures/api/orderbook#get-full-order-book---level-2
564
- https://api-docs.poloniex.com/futures/api/orderbook#get-full-order-book--level-3
565
-
566
- :param str symbol: unified symbol of the market to fetch the order book for
567
- :param int [limit]: the maximum amount of order book entries to return
568
- :param dict [params]: extra parameters specific to the exchange API endpoint
569
- :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
570
- """
571
- await self.load_markets()
572
- level = self.safe_number(params, 'level')
573
- params = self.omit(params, 'level')
574
- if level is not None and level != 2 and level != 3:
575
- raise BadRequest(self.id + ' fetchOrderBook() can only return level 2 & 3')
576
- market = self.market(symbol)
577
- request: dict = {
578
- 'symbol': market['id'],
579
- }
580
- response = None
581
- if level == 3:
582
- response = await self.publicGetLevel3Snapshot(self.extend(request, params))
583
- else:
584
- response = await self.publicGetLevel2Snapshot(self.extend(request, params))
585
- # L2
586
- #
587
- # {
588
- # "code": "200000",
589
- # "data": {
590
- # "symbol": "BTCUSDTPERP",
591
- # "sequence": 1669149851334,
592
- # "asks": [
593
- # [
594
- # 16952,
595
- # 12
596
- # ],
597
- # ],
598
- # "bids": [
599
- # [
600
- # 16951.9,
601
- # 13
602
- # ],
603
- # ],
604
- # }
605
- #
606
- # L3
607
- #
608
- # {
609
- # "code": "200000",
610
- # "data": {
611
- # "symbol": "BTCUSDTPERP",
612
- # "sequence": 1669149851334,
613
- # "asks": [
614
- # [
615
- # "639c95388cba5100084eabce",
616
- # "16952.0",
617
- # "1",
618
- # 1671206200542484700
619
- # ],
620
- # ],
621
- # "bids": [
622
- # [
623
- # "626659d83385c200072e690b",
624
- # "17.0",
625
- # "1000",
626
- # 1650874840161291000
627
- # ],
628
- # ],
629
- # }
630
- #
631
- data = self.safe_value(response, 'data', {})
632
- timestamp = self.safe_integer_product(data, 'ts', 0.000001)
633
- orderbook = None
634
- if level == 3:
635
- orderbook = self.parse_order_book(data, market['symbol'], timestamp, 'bids', 'asks', 1, 2)
636
- else:
637
- orderbook = self.parse_order_book(data, market['symbol'], timestamp, 'bids', 'asks', 0, 1)
638
- orderbook['nonce'] = self.safe_integer(data, 'sequence')
639
- return orderbook
640
-
641
- async def fetch_l3_order_book(self, symbol: str, limit: Int = None, params={}):
642
- """
643
- fetches level 3 information on open orders with bid(buy) and ask(sell) prices, volumes and other data
644
-
645
- https://api-docs.poloniex.com/futures/api/orderbook#get-full-order-book--level-3
646
-
647
- :param str symbol: unified market symbol
648
- :param int [limit]: max number of orders to return, default is None
649
- :param dict [params]: extra parameters specific to the exchange API endpoint
650
- :returns dict: an `order book structure <https://docs.ccxt.com/#/?id=order-book-structure>`
651
- """
652
- await self.load_markets()
653
- market = self.market(symbol)
654
- return self.fetch_order_book(market['id'], None, {'level': 3})
655
-
656
- def parse_trade(self, trade: dict, market: Market = None) -> Trade:
657
- #
658
- # fetchTrades(public)
659
- #
660
- # {
661
- # "sequence": 11827985,
662
- # "side": "buy",
663
- # "size": 101,
664
- # "price": "16864.0000000000",
665
- # "takerOrderId": "639c986f0ac2470007be75ee",
666
- # "makerOrderId": "639c986fa69d280007b76111",
667
- # "tradeId": "639c986f9fd7cf0001afd7ee",
668
- # "ts": 1671207023485924400
669
- # }
670
- #
671
- # fetchMyTrades
672
- #
673
- # {
674
- # "symbol": "BTCUSDTPERP", #Ticker symbol of the contract
675
- # "tradeId": "5ce24c1f0c19fc3c58edc47c", #Trade ID
676
- # "orderId": "5ce24c16b210233c36ee321d", # Order ID
677
- # "side": "sell", #Transaction side
678
- # "liquidity": "taker", #Liquidity- taker or maker
679
- # "price": "8302", #Filled price
680
- # "size": 10, #Filled amount
681
- # "value": "0.001204529", #Order value
682
- # "feeRate": "0.0005", #Floating fees
683
- # "fixFee": "0.00000006", #Fixed fees
684
- # "feeCurrency": "XBT", #Charging currency
685
- # "stop": "", #A mark to the stop order type
686
- # "fee": "0.0000012022", #Transaction fee
687
- # "orderType": "limit", #Order type
688
- # "tradeType": "trade", #Trade type(trade, liquidation, ADL or settlement)
689
- # "createdAt": 1558334496000, #Time the order created
690
- # "settleCurrency": "XBT", #settlement currency
691
- # "tradeTime": 1558334496000000000 #trade time in nanosecond
692
- # }
693
- #
694
- marketId = self.safe_string(trade, 'symbol')
695
- market = self.safe_market(marketId, market, '-')
696
- id = self.safe_string(trade, 'tradeId')
697
- orderId = self.safe_string(trade, 'orderId')
698
- takerOrMaker = self.safe_string(trade, 'liquidity')
699
- timestamp = self.safe_integer(trade, 'ts')
700
- if timestamp is not None:
701
- timestamp = self.parse_to_int(timestamp / 1000000)
702
- else:
703
- timestamp = self.safe_integer(trade, 'createdAt')
704
- # if it's a historical v1 trade, the exchange returns timestamp in seconds
705
- if ('dealValue' in trade) and (timestamp is not None):
706
- timestamp = timestamp * 1000
707
- priceString = self.safe_string(trade, 'price')
708
- amountString = self.safe_string(trade, 'size')
709
- side = self.safe_string(trade, 'side')
710
- fee = None
711
- feeCostString = self.safe_string(trade, 'fee')
712
- if feeCostString is not None:
713
- feeCurrencyId = self.safe_string(trade, 'feeCurrency')
714
- feeCurrency = self.safe_currency_code(feeCurrencyId)
715
- if feeCurrency is None:
716
- feeCurrency = market['quote'] if (side == 'sell') else market['base']
717
- fee = {
718
- 'cost': feeCostString,
719
- 'currency': feeCurrency,
720
- 'rate': self.safe_string(trade, 'feeRate'),
721
- }
722
- type = self.safe_string(trade, 'orderType')
723
- if type == 'match':
724
- type = None
725
- costString = self.safe_string(trade, 'value')
726
- return self.safe_trade({
727
- 'info': trade,
728
- 'id': id,
729
- 'order': orderId,
730
- 'timestamp': timestamp,
731
- 'datetime': self.iso8601(timestamp),
732
- 'symbol': market['symbol'],
733
- 'type': type,
734
- 'takerOrMaker': takerOrMaker,
735
- 'side': side,
736
- 'price': priceString,
737
- 'amount': amountString,
738
- 'cost': costString,
739
- 'fee': fee,
740
- }, market)
741
-
742
- async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
743
- """
744
- get the list of most recent trades for a particular symbol
745
-
746
- https://api-docs.poloniex.com/futures/api/historical#transaction-history
747
-
748
- :param str symbol: unified symbol of the market to fetch trades for
749
- :param int [since]: timestamp in ms of the earliest trade to fetch
750
- :param int [limit]: the maximum amount of trades to fetch
751
- :param dict [params]: extra parameters specific to the exchange API endpoint
752
- :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
753
- """
754
- await self.load_markets()
755
- market = self.market(symbol)
756
- request: dict = {
757
- 'symbol': market['id'],
758
- }
759
- response = await self.publicGetTradeHistory(self.extend(request, params))
760
- #
761
- # {
762
- # "code": "200000",
763
- # "data": [
764
- # {
765
- # "sequence": 11827985,
766
- # "side": "buy",
767
- # "size": 101,
768
- # "price": "16864.0000000000",
769
- # "takerOrderId": "639c986f0ac2470007be75ee",
770
- # "makerOrderId": "639c986fa69d280007b76111",
771
- # "tradeId": "639c986f9fd7cf0001afd7ee",
772
- # "ts": 1671207023485924400
773
- # },
774
- # }
775
- #
776
- trades = self.safe_list(response, 'data', [])
777
- return self.parse_trades(trades, market, since, limit)
778
-
779
- async def fetch_time(self, params={}) -> Int:
780
- """
781
- fetches the current integer timestamp in milliseconds from the poloniexfutures server
782
-
783
- https://api-docs.poloniex.com/futures/api/time#server-time
784
-
785
- :param dict [params]: extra parameters specific to the exchange API endpoint
786
- :returns int: the current integer timestamp in milliseconds from the poloniexfutures server
787
- """
788
- response = await self.publicGetTimestamp(params)
789
- #
790
- # {
791
- # "code":"200000",
792
- # "msg":"success",
793
- # "data":1546837113087
794
- # }
795
- #
796
- return self.safe_integer(response, 'data')
797
-
798
- async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
799
- """
800
- fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
801
-
802
- https://api-docs.poloniex.com/futures/api/kline#get-k-line-data-of-contract
803
-
804
- :param str symbol: unified symbol of the market to fetch OHLCV data for
805
- :param str timeframe: the length of time each candle represents
806
- :param int [since]: timestamp in ms of the earliest candle to fetch
807
- :param int [limit]: the maximum amount of candles to fetch
808
- :param dict [params]: extra parameters specific to the exchange API endpoint
809
- :returns int[][]: A list of candles ordered, open, high, low, close, volume
810
- """
811
- await self.load_markets()
812
- market = self.market(symbol)
813
- marketId = market['id']
814
- parsedTimeframe = self.safe_integer(self.timeframes, timeframe)
815
- request: dict = {
816
- 'symbol': marketId,
817
- }
818
- if parsedTimeframe is not None:
819
- request['granularity'] = parsedTimeframe
820
- else:
821
- request['granularity'] = timeframe
822
- duration = self.parse_timeframe(timeframe) * 1000
823
- endAt = self.milliseconds()
824
- if since is not None:
825
- request['from'] = since
826
- if limit is None:
827
- limit = self.safe_integer(self.options, 'fetchOHLCVLimit', 200)
828
- endAt = self.sum(since, limit * duration)
829
- request['to'] = endAt
830
- elif limit is not None:
831
- since = endAt - limit * duration
832
- request['from'] = since
833
- response = await self.publicGetKlineQuery(self.extend(request, params))
834
- #
835
- # {
836
- # "code": "200000",
837
- # "data": [
838
- # [1636459200000, 4779.3, 4792.1, 4768.7, 4770.3, 78051],
839
- # [1636460100000, 4770.25, 4778.55, 4757.55, 4777.25, 80164],
840
- # [1636461000000, 4777.25, 4791.45, 4774.5, 4791.3, 51555]
841
- # ]
842
- # }
843
- #
844
- data = self.safe_list(response, 'data', [])
845
- return self.parse_ohlcvs(data, market, timeframe, since, limit)
846
-
847
- def parse_balance(self, response) -> Balances:
848
- result: dict = {
849
- 'info': response,
850
- 'timestamp': None,
851
- 'datetime': None,
852
- }
853
- data = self.safe_value(response, 'data')
854
- currencyId = self.safe_string(data, 'currency')
855
- code = self.safe_currency_code(currencyId)
856
- account = self.account()
857
- account['free'] = self.safe_string(data, 'availableBalance')
858
- account['total'] = self.safe_string(data, 'accountEquity')
859
- result[code] = account
860
- return self.safe_balance(result)
861
-
862
- async def fetch_balance(self, params={}) -> Balances:
863
- """
864
- query for balance and get the amount of funds available for trading or funds locked in orders
865
-
866
- https://api-docs.poloniex.com/futures/api/account#get-account-overview
867
-
868
- :param dict [params]: extra parameters specific to the exchange API endpoint
869
- :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
870
- """
871
- await self.load_markets()
872
- currencyId = self.safe_string(params, 'currency')
873
- request: dict = {}
874
- if currencyId is not None:
875
- currency = self.currency(currencyId)
876
- request = {
877
- 'currency': currency['id'],
878
- }
879
- response = await self.privateGetAccountOverview(self.extend(request, params))
880
- #
881
- # {
882
- # "code": "200000",
883
- # "data": {
884
- # "accountEquity": 0.00005,
885
- # "unrealisedPNL": 0,
886
- # "marginBalance": 0.00005,
887
- # "positionMargin": 0,
888
- # "orderMargin": 0,
889
- # "frozenFunds": 0,
890
- # "availableBalance": 0.00005,
891
- # "currency": "XBT"
892
- # }
893
- # }
894
- #
895
- return self.parse_balance(response)
896
-
897
- async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
898
- """
899
- Create an order on the exchange
900
-
901
- https://api-docs.poloniex.com/futures/api/orders#place-an-order
902
-
903
- :param str symbol: Unified CCXT market symbol
904
- :param str type: 'limit' or 'market'
905
- :param str side: 'buy' or 'sell'
906
- :param float amount: the amount of currency to trade
907
- :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
908
- :param dict [params]: extra parameters specific to the exchange API endpoint
909
- :param float [params.leverage]: Leverage size of the order
910
- :param float [params.triggerPrice]: The price at which a trigger order is triggered at
911
- :param bool [params.reduceOnly]: A mark to reduce the position size only. Set to False by default. Need to set the position size when reduceOnly is True.
912
- :param str [params.timeInForce]: GTC, GTT, IOC, or FOK, default is GTC, limit orders only
913
- :param str [params.postOnly]: Post only flag, invalid when timeInForce is IOC or FOK
914
- :param str [params.clientOid]: client order id, defaults to uuid if not passed
915
- :param str [params.remark]: remark for the order, length cannot exceed 100 utf8 characters
916
- :param str [params.stop]: 'up' or 'down', defaults to 'up' if side is sell and 'down' if side is buy, requires stopPrice
917
- :param str [params.stopPriceType]: TP, IP or MP, defaults to TP
918
- :param bool [params.closeOrder]: set to True to close position
919
- :param bool [params.forceHold]: A mark to forcely hold the funds for an order, even though it's an order to reduce the position size. This helps the order stay on the order book and not get canceled when the position size changes. Set to False by default.
920
- :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
921
- """
922
- await self.load_markets()
923
- market = self.market(symbol)
924
- # required param, cannot be used twice
925
- clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId', self.uuid())
926
- params = self.omit(params, ['clientOid', 'clientOrderId'])
927
- if amount < 1:
928
- raise InvalidOrder(self.id + ' createOrder() minimum contract order amount is 1')
929
- preciseAmount = int(self.amount_to_precision(symbol, amount))
930
- request: dict = {
931
- 'clientOid': clientOrderId,
932
- 'side': side,
933
- 'symbol': market['id'],
934
- 'type': type, # limit or market
935
- 'size': preciseAmount,
936
- 'leverage': 1,
937
- }
938
- triggerPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
939
- if triggerPrice:
940
- request['stop'] = 'up' if (side == 'buy') else 'down'
941
- stopPriceType = self.safe_string(params, 'stopPriceType', 'TP')
942
- request['stopPriceType'] = stopPriceType
943
- request['stopPrice'] = self.price_to_precision(symbol, triggerPrice)
944
- timeInForce = self.safe_string_upper(params, 'timeInForce')
945
- if type == 'limit':
946
- if price is None:
947
- raise ArgumentsRequired(self.id + ' createOrder() requires a price argument for limit orders')
948
- else:
949
- request['price'] = self.price_to_precision(symbol, price)
950
- if timeInForce is not None:
951
- request['timeInForce'] = timeInForce
952
- postOnly = self.safe_bool(params, 'postOnly', False)
953
- hidden = self.safe_value(params, 'hidden')
954
- if postOnly and (hidden is not None):
955
- raise BadRequest(self.id + ' createOrder() does not support the postOnly parameter together with a hidden parameter')
956
- iceberg = self.safe_value(params, 'iceberg')
957
- if iceberg:
958
- visibleSize = self.safe_value(params, 'visibleSize')
959
- if visibleSize is None:
960
- raise ArgumentsRequired(self.id + ' createOrder() requires a visibleSize parameter for iceberg orders')
961
- params = self.omit(params, ['timeInForce', 'stopPrice', 'triggerPrice']) # Time in force only valid for limit orders, exchange error when gtc for market orders
962
- response = await self.privatePostOrders(self.extend(request, params))
963
- #
964
- # {
965
- # "code": "200000",
966
- # "data": {
967
- # "orderId": "619717484f1d010001510cde",
968
- # },
969
- # }
970
- #
971
- data = self.safe_value(response, 'data', {})
972
- return self.safe_order({
973
- 'id': self.safe_string(data, 'orderId'),
974
- 'clientOrderId': None,
975
- 'timestamp': None,
976
- 'datetime': None,
977
- 'lastTradeTimestamp': None,
978
- 'symbol': None,
979
- 'type': None,
980
- 'side': None,
981
- 'price': None,
982
- 'amount': None,
983
- 'cost': None,
984
- 'average': None,
985
- 'filled': None,
986
- 'remaining': None,
987
- 'status': None,
988
- 'fee': None,
989
- 'trades': None,
990
- 'timeInForce': None,
991
- 'postOnly': None,
992
- 'triggerPrice': None,
993
- 'info': response,
994
- }, market)
995
-
996
- async def cancel_order(self, id: str, symbol: Str = None, params={}):
997
- """
998
- cancels an open order
999
-
1000
- https://api-docs.poloniex.com/futures/api/orders#cancel-an-order
1001
-
1002
- :param str id: order id
1003
- :param str symbol: unified symbol of the market the order was made in
1004
- :param dict [params]: extra parameters specific to the exchange API endpoint
1005
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1006
- """
1007
- await self.load_markets()
1008
- request: dict = {
1009
- 'order-id': id,
1010
- }
1011
- response = await self.privateDeleteOrdersOrderId(self.extend(request, params))
1012
- #
1013
- # {
1014
- # "code": "200000",
1015
- # "data": {
1016
- # "cancelledOrderIds": [
1017
- # "619714b8b6353000014c505a",
1018
- # ],
1019
- # "cancelFailedOrders": [
1020
- # {
1021
- # "orderId": "63a9c5c2b9e7d70007eb0cd5",
1022
- # "orderState": "2"
1023
- # }
1024
- # ],
1025
- # },
1026
- # }
1027
- #
1028
- data = self.safe_value(response, 'data')
1029
- cancelledOrderIds = self.safe_value(data, 'cancelledOrderIds')
1030
- cancelledOrderIdsLength = len(cancelledOrderIds)
1031
- if cancelledOrderIdsLength == 0:
1032
- raise InvalidOrder(self.id + ' cancelOrder() order already cancelled')
1033
- return self.parse_order(data)
1034
-
1035
- async def fetch_positions(self, symbols: Strings = None, params={}):
1036
- """
1037
- fetch all open positions
1038
-
1039
- https://api-docs.poloniex.com/futures/api/positions#get-position-list
1040
-
1041
- :param str[]|None symbols: list of unified market symbols
1042
- :param dict [params]: extra parameters specific to the exchange API endpoint
1043
- :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
1044
- """
1045
- await self.load_markets()
1046
- response = await self.privateGetPositions(params)
1047
- #
1048
- # {
1049
- # "code": "200000",
1050
- # "data": [
1051
- # {
1052
- # "id": "615ba79f83a3410001cde321",
1053
- # "symbol": "ETHUSDTM",
1054
- # "autoDeposit": False,
1055
- # "maintMarginReq": 0.005,
1056
- # "riskLimit": 1000000,
1057
- # "realLeverage": 18.61,
1058
- # "crossMode": False,
1059
- # "delevPercentage": 0.86,
1060
- # "openingTimestamp": 1638563515618,
1061
- # "currentTimestamp": 1638576872774,
1062
- # "currentQty": 2,
1063
- # "currentCost": 83.64200000,
1064
- # "currentComm": 0.05018520,
1065
- # "unrealisedCost": 83.64200000,
1066
- # "realisedGrossCost": 0.00000000,
1067
- # "realisedCost": 0.05018520,
1068
- # "isOpen": True,
1069
- # "markPrice": 4225.01,
1070
- # "markValue": 84.50020000,
1071
- # "posCost": 83.64200000,
1072
- # "posCross": 0.0000000000,
1073
- # "posInit": 3.63660870,
1074
- # "posComm": 0.05236717,
1075
- # "posLoss": 0.00000000,
1076
- # "posMargin": 3.68897586,
1077
- # "posMaint": 0.50637594,
1078
- # "maintMargin": 4.54717586,
1079
- # "realisedGrossPnl": 0.00000000,
1080
- # "realisedPnl": -0.05018520,
1081
- # "unrealisedPnl": 0.85820000,
1082
- # "unrealisedPnlPcnt": 0.0103,
1083
- # "unrealisedRoePcnt": 0.2360,
1084
- # "avgEntryPrice": 4182.10,
1085
- # "liquidationPrice": 4023.00,
1086
- # "bankruptPrice": 4000.25,
1087
- # "settleCurrency": "USDT",
1088
- # "isInverse": False
1089
- # }
1090
- # ]
1091
- # }
1092
- #
1093
- data = self.safe_list(response, 'data')
1094
- return self.parse_positions(data, symbols)
1095
-
1096
- def parse_position(self, position: dict, market: Market = None):
1097
- #
1098
- # {
1099
- # "code": "200000",
1100
- # "data": [
1101
- # {
1102
- # "id": "615ba79f83a3410001cde321", # Position ID
1103
- # "symbol": "ETHUSDTM", # Symbol
1104
- # "autoDeposit": False, # Auto deposit margin or not
1105
- # "maintMarginReq": 0.005, # Maintenance margin requirement
1106
- # "riskLimit": 1000000, # Risk limit
1107
- # "realLeverage": 25.92, # Leverage of the order
1108
- # "crossMode": False, # Cross mode or not
1109
- # "delevPercentage": 0.76, # ADL ranking percentile
1110
- # "openingTimestamp": 1638578546031, # Open time
1111
- # "currentTimestamp": 1638578563580, # Current timestamp
1112
- # "currentQty": 2, # Current postion quantity
1113
- # "currentCost": 83.787, # Current postion value
1114
- # "currentComm": 0.0167574, # Current commission
1115
- # "unrealisedCost": 83.787, # Unrealised value
1116
- # "realisedGrossCost": 0.0, # Accumulated realised gross profit value
1117
- # "realisedCost": 0.0167574, # Current realised position value
1118
- # "isOpen": True, # Opened position or not
1119
- # "markPrice": 4183.38, # Mark price
1120
- # "markValue": 83.6676, # Mark value
1121
- # "posCost": 83.787, # Position value
1122
- # "posCross": 0.0, # added margin
1123
- # "posInit": 3.35148, # Leverage margin
1124
- # "posComm": 0.05228309, # Bankruptcy cost
1125
- # "posLoss": 0.0, # Funding fees paid out
1126
- # "posMargin": 3.40376309, # Position margin
1127
- # "posMaint": 0.50707892, # Maintenance margin
1128
- # "maintMargin": 3.28436309, # Position margin
1129
- # "realisedGrossPnl": 0.0, # Accumulated realised gross profit value
1130
- # "realisedPnl": -0.0167574, # Realised profit and loss
1131
- # "unrealisedPnl": -0.1194, # Unrealised profit and loss
1132
- # "unrealisedPnlPcnt": -0.0014, # Profit-loss ratio of the position
1133
- # "unrealisedRoePcnt": -0.0356, # Rate of return on investment
1134
- # "avgEntryPrice": 4189.35, # Average entry price
1135
- # "liquidationPrice": 4044.55, # Liquidation price
1136
- # "bankruptPrice": 4021.75, # Bankruptcy price
1137
- # "settleCurrency": "USDT", # Currency used to clear and settle the trades
1138
- # "isInverse": False
1139
- # }
1140
- # ]
1141
- # }
1142
- #
1143
- symbol = self.safe_string(position, 'symbol')
1144
- market = self.safe_market(symbol, market)
1145
- timestamp = self.safe_integer(position, 'currentTimestamp')
1146
- size = self.safe_string(position, 'currentQty')
1147
- side: Str
1148
- if Precise.string_gt(size, '0'):
1149
- side = 'long'
1150
- elif Precise.string_lt(size, '0'):
1151
- side = 'short'
1152
- notional = Precise.string_abs(self.safe_string(position, 'posCost'))
1153
- initialMargin = self.safe_string(position, 'posInit')
1154
- initialMarginPercentage = Precise.string_div(initialMargin, notional)
1155
- # marginRatio = Precise.string_div(maintenanceRate, collateral)
1156
- unrealisedPnl = self.safe_string(position, 'unrealisedPnl')
1157
- crossMode = self.safe_value(position, 'crossMode')
1158
- # currently crossMode is always set to False and only isolated positions are supported
1159
- marginMode = 'cross' if crossMode else 'isolated'
1160
- return {
1161
- 'info': position,
1162
- 'id': None,
1163
- 'symbol': self.safe_string(market, 'symbol'),
1164
- 'timestamp': timestamp,
1165
- 'datetime': self.iso8601(timestamp),
1166
- 'initialMargin': self.parse_number(initialMargin),
1167
- 'initialMarginPercentage': self.parse_number(initialMarginPercentage),
1168
- 'maintenanceMargin': self.safe_number(position, 'posMaint'),
1169
- 'maintenanceMarginPercentage': self.safe_number(position, 'maintMarginReq'),
1170
- 'entryPrice': self.safe_number(position, 'avgEntryPrice'),
1171
- 'notional': self.parse_number(notional),
1172
- 'leverage': self.safe_number(position, 'realLeverage'),
1173
- 'unrealizedPnl': self.parse_number(unrealisedPnl),
1174
- 'contracts': self.parse_number(Precise.string_abs(size)),
1175
- 'contractSize': self.safe_value(market, 'contractSize'),
1176
- 'marginRatio': None,
1177
- 'liquidationPrice': self.safe_number(position, 'liquidationPrice'),
1178
- 'markPrice': self.safe_number(position, 'markPrice'),
1179
- 'collateral': self.safe_number(position, 'maintMargin'),
1180
- 'marginMode': marginMode,
1181
- 'side': side,
1182
- 'percentage': self.parse_number(Precise.string_div(unrealisedPnl, initialMargin)),
1183
- 'stopLossPrice': None,
1184
- 'takeProfitPrice': None,
1185
- }
1186
-
1187
- async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1188
- """
1189
- fetch the history of funding payments paid and received on self account
1190
-
1191
- https://api-docs.poloniex.com/futures/api/funding-fees#get-funding-history
1192
-
1193
- :param str symbol: unified market symbol
1194
- :param int [since]: the earliest time in ms to fetch funding history for
1195
- :param int [limit]: the maximum number of funding history structures to retrieve
1196
- :param dict [params]: extra parameters specific to the exchange API endpoint
1197
- :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
1198
- """
1199
- if symbol is None:
1200
- raise ArgumentsRequired(self.id + ' fetchFundingHistory() requires a symbol argument')
1201
- await self.load_markets()
1202
- market = self.market(symbol)
1203
- request: dict = {
1204
- 'symbol': market['id'],
1205
- }
1206
- if since is not None:
1207
- request['startAt'] = since
1208
- if limit is not None:
1209
- # * Since is ignored if limit is defined
1210
- request['maxCount'] = limit
1211
- response = await self.privateGetFundingHistory(self.extend(request, params))
1212
- #
1213
- # {
1214
- # "code": "200000",
1215
- # "data": {
1216
- # "dataList": [
1217
- # {
1218
- # "id": 239471298749817,
1219
- # "symbol": "ETHUSDTM",
1220
- # "timePoint": 1638532800000,
1221
- # "fundingRate": 0.000100,
1222
- # "markPrice": 4612.8300000000,
1223
- # "positionQty": 12,
1224
- # "positionCost": 553.5396000000,
1225
- # "funding": -0.0553539600,
1226
- # "settleCurrency": "USDT"
1227
- # },
1228
- # ...
1229
- # ],
1230
- # "hasMore": True
1231
- # }
1232
- # }
1233
- #
1234
- data = self.safe_value(response, 'data')
1235
- dataList = self.safe_value(data, 'dataList', [])
1236
- dataListLength = len(dataList)
1237
- fees = []
1238
- for i in range(0, dataListLength):
1239
- listItem = dataList[i]
1240
- timestamp = self.safe_integer(listItem, 'timePoint')
1241
- fees.append({
1242
- 'info': listItem,
1243
- 'symbol': symbol,
1244
- 'code': self.safe_currency_code(self.safe_string(listItem, 'settleCurrency')),
1245
- 'timestamp': timestamp,
1246
- 'datetime': self.iso8601(timestamp),
1247
- 'id': self.safe_number(listItem, 'id'),
1248
- 'amount': self.safe_number(listItem, 'funding'),
1249
- 'fundingRate': self.safe_number(listItem, 'fundingRate'),
1250
- 'markPrice': self.safe_number(listItem, 'markPrice'),
1251
- 'positionQty': self.safe_number(listItem, 'positionQty'),
1252
- 'positionCost': self.safe_number(listItem, 'positionCost'),
1253
- })
1254
- return fees
1255
-
1256
- async def cancel_all_orders(self, symbol: Str = None, params={}):
1257
- """
1258
- cancel all open orders
1259
- :param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
1260
- :param dict [params]: extra parameters specific to the exchange API endpoint
1261
- :param dict [params.trigger]: When True, all the trigger orders will be cancelled
1262
- :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1263
- """
1264
- await self.load_markets()
1265
- request: dict = {}
1266
- if symbol is not None:
1267
- request['symbol'] = self.market_id(symbol)
1268
- trigger = self.safe_value_2(params, 'stop', 'trigger')
1269
- params = self.omit(params, ['stop', 'trigger'])
1270
- response = None
1271
- if trigger:
1272
- response = await self.privateDeleteStopOrders(self.extend(request, params))
1273
- else:
1274
- response = await self.privateDeleteOrders(self.extend(request, params))
1275
- #
1276
- # {
1277
- # "code": "200000",
1278
- # "data": {
1279
- # "cancelledOrderIds": [
1280
- # "619714b8b6353000014c505a",
1281
- # ],
1282
- # },
1283
- # }
1284
- #
1285
- data = self.safe_value(response, 'data')
1286
- result = []
1287
- cancelledOrderIds = self.safe_value(data, 'cancelledOrderIds')
1288
- cancelledOrderIdsLength = len(cancelledOrderIds)
1289
- for i in range(0, cancelledOrderIdsLength):
1290
- cancelledOrderId = self.safe_string(cancelledOrderIds, i)
1291
- result.append(self.safe_order({
1292
- 'id': cancelledOrderId,
1293
- 'clientOrderId': None,
1294
- 'timestamp': None,
1295
- 'datetime': None,
1296
- 'lastTradeTimestamp': None,
1297
- 'symbol': None,
1298
- 'type': None,
1299
- 'side': None,
1300
- 'price': None,
1301
- 'amount': None,
1302
- 'cost': None,
1303
- 'average': None,
1304
- 'filled': None,
1305
- 'remaining': None,
1306
- 'status': None,
1307
- 'fee': None,
1308
- 'trades': None,
1309
- 'timeInForce': None,
1310
- 'postOnly': None,
1311
- 'triggerPrice': None,
1312
- 'info': response,
1313
- }))
1314
- return result
1315
-
1316
- async def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1317
- """
1318
- fetches a list of orders placed on the exchange
1319
-
1320
- https://api-docs.poloniex.com/futures/api/orders#get-order-listdeprecated
1321
- https://api-docs.poloniex.com/futures/api/orders#get-untriggered-stop-order-list
1322
-
1323
- :param str status: 'active' or 'closed', only 'active' is valid for stop orders
1324
- :param str symbol: unified symbol for the market to retrieve orders from
1325
- :param int [since]: timestamp in ms of the earliest order to retrieve
1326
- :param int [limit]: The maximum number of orders to retrieve
1327
- :param dict [params]: exchange specific parameters
1328
- :param bool [params.stop]: set to True to retrieve untriggered stop orders
1329
- :param int [params.until]: End time in ms
1330
- :param str [params.side]: buy or sell
1331
- :param str [params.type]: limit or market
1332
- :returns: An `array of order structures <https://docs.ccxt.com/#/?id=order-structure>`
1333
- """
1334
- await self.load_markets()
1335
- trigger = self.safe_value_2(params, 'stop', 'trigger')
1336
- until = self.safe_integer(params, 'until')
1337
- params = self.omit(params, ['trigger', 'stop', 'until'])
1338
- if status == 'closed':
1339
- status = 'done'
1340
- request: dict = {}
1341
- if not trigger:
1342
- request['status'] = 'active' if (status == 'open') else 'done'
1343
- elif status != 'open':
1344
- raise BadRequest(self.id + ' fetchOrdersByStatus() can only fetch untriggered stop orders')
1345
- market: Market = None
1346
- if symbol is not None:
1347
- market = self.market(symbol)
1348
- request['symbol'] = market['id']
1349
- if since is not None:
1350
- request['startAt'] = since
1351
- if until is not None:
1352
- request['endAt'] = until
1353
- response = None
1354
- if trigger:
1355
- response = await self.privateGetStopOrders(self.extend(request, params))
1356
- else:
1357
- response = await self.privateGetOrders(self.extend(request, params))
1358
- #
1359
- # {
1360
- # "code": "200000",
1361
- # "data": {
1362
- # "totalNum": 1,
1363
- # "totalPage": 1,
1364
- # "pageSize": 50,
1365
- # "currentPage": 1,
1366
- # "items": [
1367
- # {
1368
- # "symbol": "ADAUSDTPERP",
1369
- # "leverage": "1",
1370
- # "hidden": False,
1371
- # "forceHold": False,
1372
- # "closeOrder": False,
1373
- # "type": "limit",
1374
- # "isActive": True,
1375
- # "createdAt": 1678936920000,
1376
- # "orderTime": 1678936920480905922,
1377
- # "price": "0.3",
1378
- # "iceberg": False,
1379
- # "stopTriggered": False,
1380
- # "id": "64128b582cc0710007a3c840",
1381
- # "value": "3",
1382
- # "timeInForce": "GTC",
1383
- # "updatedAt": 1678936920000,
1384
- # "side": "buy",
1385
- # "stopPriceType": "",
1386
- # "dealValue": "0",
1387
- # "dealSize": 0,
1388
- # "settleCurrency": "USDT",
1389
- # "stp": "",
1390
- # "filledValue": "0",
1391
- # "postOnly": False,
1392
- # "size": 1,
1393
- # "stop": "",
1394
- # "filledSize": 0,
1395
- # "reduceOnly": False,
1396
- # "marginType": 1,
1397
- # "cancelExist": False,
1398
- # "clientOid": "ba669f39-dfcc-4664-9801-a42d06e59c2e",
1399
- # "status": "open"
1400
- # }
1401
- # ]
1402
- # }
1403
- # }
1404
- #
1405
- responseData = self.safe_value(response, 'data', {})
1406
- orders = self.safe_value(responseData, 'items', [])
1407
- ordersLength = len(orders)
1408
- result = []
1409
- for i in range(0, ordersLength):
1410
- order = orders[i]
1411
- orderStatus = self.safe_string(order, 'status')
1412
- if status == orderStatus:
1413
- result.append(orders[i])
1414
- return self.parse_orders(result, market, since, limit)
1415
-
1416
- async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1417
- """
1418
- fetch all unfilled currently open orders
1419
-
1420
- https://api-docs.poloniex.com/futures/api/orders#get-order-listdeprecated
1421
- https://api-docs.poloniex.com/futures/api/orders#get-untriggered-stop-order-list
1422
-
1423
- :param str symbol: unified market symbol
1424
- :param int [since]: the earliest time in ms to fetch open orders for
1425
- :param int [limit]: the maximum number of open orders structures to retrieve
1426
- :param dict [params]: extra parameters specific to the exchange API endpoint
1427
- :param int [params.until]: end time in ms
1428
- :param str [params.side]: buy or sell
1429
- :param str [params.type]: limit, or market
1430
- :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1431
- """
1432
- return await self.fetch_orders_by_status('open', symbol, since, limit, params)
1433
-
1434
- async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1435
- """
1436
- fetches information on multiple closed orders made by the user
1437
-
1438
- https://api-docs.poloniex.com/futures/api/orders#get-order-listdeprecated
1439
- https://api-docs.poloniex.com/futures/api/orders#get-untriggered-stop-order-list
1440
-
1441
- :param str symbol: unified market symbol of the market orders were made in
1442
- :param int [since]: the earliest time in ms to fetch orders for
1443
- :param int [limit]: the maximum number of order structures to retrieve
1444
- :param dict [params]: extra parameters specific to the exchange API endpoint
1445
- :param int [params.until]: end time in ms
1446
- :param str [params.side]: buy or sell
1447
- :param str [params.type]: limit, or market
1448
- :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1449
- """
1450
- return await self.fetch_orders_by_status('closed', symbol, since, limit, params)
1451
-
1452
- async def fetch_order(self, id: Str, symbol: Str = None, params={}):
1453
- """
1454
- fetches information on an order made by the user
1455
-
1456
- https://api-docs.poloniex.com/futures/api/orders#get-details-of-a-single-order
1457
- https://api-docs.poloniex.com/futures/api/orders#get-single-order-by-clientoid
1458
-
1459
- :param str id: the order id
1460
- :param str symbol: unified symbol of the market the order was made in
1461
- :param dict [params]: extra parameters specific to the exchange API endpoint
1462
- :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1463
- """
1464
- await self.load_markets()
1465
- request: dict = {}
1466
- response = None
1467
- if id is None:
1468
- clientOrderId = self.safe_string_2(params, 'clientOid', 'clientOrderId')
1469
- if clientOrderId is None:
1470
- raise InvalidOrder(self.id + ' fetchOrder() requires parameter id or params.clientOid')
1471
- request['clientOid'] = clientOrderId
1472
- params = self.omit(params, ['clientOid', 'clientOrderId'])
1473
- response = await self.privateGetClientOrderIdClientOid(self.extend(request, params))
1474
- else:
1475
- request['order-id'] = id
1476
- response = await self.privateGetOrdersOrderId(self.extend(request, params))
1477
- #
1478
- # {
1479
- # "code": "200000",
1480
- # "data": {
1481
- # "symbol": "ADAUSDTPERP",
1482
- # "leverage": "1",
1483
- # "hidden": False,
1484
- # "forceHold": False,
1485
- # "closeOrder": False,
1486
- # "type": "market",
1487
- # "isActive": False,
1488
- # "createdAt": 1678929587000,
1489
- # "orderTime": 1678929587248115582,
1490
- # "iceberg": False,
1491
- # "stopTriggered": False,
1492
- # "id": "64126eb38c6919000737dcdc",
1493
- # "value": "3.1783",
1494
- # "timeInForce": "GTC",
1495
- # "updatedAt": 1678929587000,
1496
- # "side": "buy",
1497
- # "stopPriceType": "",
1498
- # "dealValue": "3.1783",
1499
- # "dealSize": 1,
1500
- # "settleCurrency": "USDT",
1501
- # "trades": [
1502
- # {
1503
- # "feePay": "0.00158915",
1504
- # "tradeId": "64126eb36803eb0001ff99bc"
1505
- # }
1506
- # ],
1507
- # "endAt": 1678929587000,
1508
- # "stp": "",
1509
- # "filledValue": "3.1783",
1510
- # "postOnly": False,
1511
- # "size": 1,
1512
- # "stop": "",
1513
- # "filledSize": 1,
1514
- # "reduceOnly": False,
1515
- # "marginType": 1,
1516
- # "cancelExist": False,
1517
- # "clientOid": "d19e8fcb-2df4-44bc-afd4-67dd42048246",
1518
- # "status": "done"
1519
- # }
1520
- # }
1521
- #
1522
- market = self.market(symbol) if (symbol is not None) else None
1523
- responseData = self.safe_dict(response, 'data')
1524
- return self.parse_order(responseData, market)
1525
-
1526
- def parse_order(self, order: dict, market: Market = None) -> Order:
1527
- #
1528
- # createOrder
1529
- #
1530
- # {
1531
- # "code": "200000",
1532
- # "data": {
1533
- # "orderId": "619717484f1d010001510cde",
1534
- # },
1535
- # }
1536
- #
1537
- # fetchOrder
1538
- #
1539
- # {
1540
- # "symbol": "ADAUSDTPERP",
1541
- # "leverage": "1",
1542
- # "hidden": False,
1543
- # "forceHold": False,
1544
- # "closeOrder": False,
1545
- # "type": "market",
1546
- # "isActive": False,
1547
- # "createdAt": 1678929587000,
1548
- # "orderTime": 1678929587248115582,
1549
- # "iceberg": False,
1550
- # "stopTriggered": False,
1551
- # "id": "64126eb38c6919000737dcdc",
1552
- # "value": "3.1783",
1553
- # "timeInForce": "GTC",
1554
- # "updatedAt": 1678929587000,
1555
- # "side": "buy",
1556
- # "stopPriceType": "",
1557
- # "dealValue": "3.1783",
1558
- # "dealSize": 1,
1559
- # "settleCurrency": "USDT",
1560
- # "trades": [
1561
- # {
1562
- # "feePay": "0.00158915",
1563
- # "tradeId": "64126eb36803eb0001ff99bc"
1564
- # }
1565
- # ],
1566
- # "endAt": 1678929587000,
1567
- # "stp": "",
1568
- # "filledValue": "3.1783",
1569
- # "postOnly": False,
1570
- # "size": 1,
1571
- # "stop": "",
1572
- # "filledSize": 1,
1573
- # "reduceOnly": False,
1574
- # "marginType": 1,
1575
- # "cancelExist": False,
1576
- # "clientOid": "d19e8fcb-2df4-44bc-afd4-67dd42048246",
1577
- # "status": "done"
1578
- # }
1579
- #
1580
- # cancelOrder
1581
- #
1582
- # {
1583
- # "cancelledOrderIds": [
1584
- # "619714b8b6353000014c505a",
1585
- # ],
1586
- # "cancelFailedOrders": [
1587
- # {
1588
- # "orderId": "63a9c5c2b9e7d70007eb0cd5",
1589
- # "orderState": "2"
1590
- # }
1591
- # ],
1592
- # },
1593
- #
1594
- marketId = self.safe_string(order, 'symbol')
1595
- market = self.safe_market(marketId, market)
1596
- timestamp = self.safe_integer(order, 'createdAt')
1597
- # price is zero for market order
1598
- # omitZero is called in safeOrder2
1599
- feeCurrencyId = self.safe_string(order, 'feeCurrency')
1600
- filled = self.safe_string(order, 'dealSize')
1601
- rawCost = self.safe_string_2(order, 'dealFunds', 'filledValue')
1602
- average: Str = None
1603
- if Precise.string_gt(filled, '0'):
1604
- contractSize = self.safe_string(market, 'contractSize')
1605
- if market['linear']:
1606
- average = Precise.string_div(rawCost, Precise.string_mul(contractSize, filled))
1607
- else:
1608
- average = Precise.string_div(Precise.string_mul(contractSize, filled), rawCost)
1609
- # precision reported by their api is 8 d.p.
1610
- # average = Precise.string_div(rawCost, Precise.string_mul(filled, market['contractSize']))
1611
- # bool
1612
- isActive = self.safe_bool(order, 'isActive', False)
1613
- cancelExist = self.safe_bool(order, 'cancelExist', False)
1614
- status = 'open' if isActive else 'closed'
1615
- id = self.safe_string(order, 'id')
1616
- if 'cancelledOrderIds' in order:
1617
- cancelledOrderIds = self.safe_value(order, 'cancelledOrderIds')
1618
- id = self.safe_string(cancelledOrderIds, 0)
1619
- return self.safe_order({
1620
- 'info': order,
1621
- 'id': id,
1622
- 'clientOrderId': self.safe_string(order, 'clientOid'),
1623
- 'symbol': self.safe_string(market, 'symbol'),
1624
- 'type': self.safe_string(order, 'type'),
1625
- 'timeInForce': self.safe_string(order, 'timeInForce'),
1626
- 'postOnly': self.safe_value(order, 'postOnly'),
1627
- 'side': self.safe_string(order, 'side'),
1628
- 'amount': self.safe_string(order, 'size'),
1629
- 'price': self.safe_string(order, 'price'),
1630
- 'triggerPrice': self.safe_string(order, 'stopPrice'),
1631
- 'cost': self.safe_string(order, 'dealValue'),
1632
- 'filled': filled,
1633
- 'remaining': None,
1634
- 'timestamp': timestamp,
1635
- 'datetime': self.iso8601(timestamp),
1636
- 'fee': {
1637
- 'currency': self.safe_currency_code(feeCurrencyId),
1638
- 'cost': self.safe_string(order, 'fee'),
1639
- },
1640
- 'status': 'canceled' if cancelExist else status,
1641
- 'lastTradeTimestamp': None,
1642
- 'average': average,
1643
- 'trades': None,
1644
- }, market)
1645
-
1646
- async def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
1647
- """
1648
- fetch the current funding rate
1649
-
1650
- https://api-docs.poloniex.com/futures/api/futures-index#get-premium-index
1651
-
1652
- :param str symbol: unified market symbol
1653
- :param dict [params]: extra parameters specific to the exchange API endpoint
1654
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
1655
- """
1656
- await self.load_markets()
1657
- market = self.market(symbol)
1658
- request: dict = {
1659
- 'symbol': market['id'],
1660
- }
1661
- response = await self.publicGetFundingRateSymbolCurrent(self.extend(request, params))
1662
- #
1663
- # {
1664
- # "symbol": ".BTCUSDTPERPFPI8H",
1665
- # "granularity": 28800000,
1666
- # "timePoint": 1558000800000,
1667
- # "value": 0.00375,
1668
- # "predictedValue": 0.00375
1669
- # }
1670
- #
1671
- data = self.safe_dict(response, 'data', {})
1672
- return self.parse_funding_rate(data, market)
1673
-
1674
- async def fetch_funding_interval(self, symbol: str, params={}) -> FundingRate:
1675
- """
1676
- fetch the current funding rate interval
1677
-
1678
- https://api-docs.poloniex.com/futures/api/futures-index#get-premium-index
1679
-
1680
- :param str symbol: unified market symbol
1681
- :param dict [params]: extra parameters specific to the exchange API endpoint
1682
- :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
1683
- """
1684
- return await self.fetch_funding_rate(symbol, params)
1685
-
1686
- def parse_funding_rate(self, data, market: Market = None) -> FundingRate:
1687
- #
1688
- # {
1689
- # "symbol": ".ETHUSDTMFPI8H",
1690
- # "granularity": 28800000,
1691
- # "timePoint": 1637380800000,
1692
- # "value": 0.0001,
1693
- # "predictedValue": 0.0001,
1694
- # }
1695
- #
1696
- fundingTimestamp = self.safe_integer(data, 'timePoint')
1697
- marketId = self.safe_string(data, 'symbol')
1698
- return {
1699
- 'info': data,
1700
- 'symbol': self.safe_symbol(marketId, market, None, 'contract'),
1701
- 'markPrice': None,
1702
- 'indexPrice': None,
1703
- 'interestRate': None,
1704
- 'estimatedSettlePrice': None,
1705
- 'timestamp': None,
1706
- 'datetime': None,
1707
- 'fundingRate': self.safe_number(data, 'value'),
1708
- 'fundingTimestamp': fundingTimestamp,
1709
- 'fundingDatetime': self.iso8601(fundingTimestamp),
1710
- 'nextFundingRate': self.safe_number(data, 'predictedValue'),
1711
- 'nextFundingTimestamp': None,
1712
- 'nextFundingDatetime': None,
1713
- 'previousFundingRate': None,
1714
- 'previousFundingTimestamp': None,
1715
- 'previousFundingDatetime': None,
1716
- 'interval': self.parse_funding_interval(self.safe_string(data, 'granularity')),
1717
- }
1718
-
1719
- def parse_funding_interval(self, interval):
1720
- intervals: dict = {
1721
- '3600000': '1h',
1722
- '14400000': '4h',
1723
- '28800000': '8h',
1724
- '57600000': '16h',
1725
- '86400000': '24h',
1726
- }
1727
- return self.safe_string(intervals, interval, interval)
1728
-
1729
- async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1730
- """
1731
- fetch all trades made by the user
1732
-
1733
- https://api-docs.poloniex.com/futures/api/fills#get-fillsdeprecated
1734
-
1735
- :param str symbol: unified market symbol
1736
- :param int [since]: the earliest time in ms to fetch trades for
1737
- :param int [limit]: the maximum number of trades structures to retrieve
1738
- :param dict [params]: extra parameters specific to the exchange API endpoint
1739
- :param str [params.orderIdFills]: filles for a specific order(other parameters can be ignored if specified)
1740
- :param str [params.side]: buy or sell
1741
- :param str [params.type]: limit, market, limit_stop or market_stop
1742
- :param int [params.endAt]: end time(milisecond)
1743
- :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1744
- """
1745
- await self.load_markets()
1746
- request: dict = {
1747
- }
1748
- market = None
1749
- if symbol is not None:
1750
- market = self.market(symbol)
1751
- request['symbol'] = market['id']
1752
- if since is not None:
1753
- request['startAt'] = since
1754
- response = await self.privateGetFills(self.extend(request, params))
1755
- #
1756
- # {
1757
- # "code": "200000",
1758
- # "data": {
1759
- # "currentPage":1,
1760
- # "pageSize":1,
1761
- # "totalNum":251915,
1762
- # "totalPage":251915,
1763
- # "items":[
1764
- # {
1765
- # "symbol": "BTCUSDTPERP", #Ticker symbol of the contract
1766
- # "tradeId": "5ce24c1f0c19fc3c58edc47c", #Trade ID
1767
- # "orderId": "5ce24c16b210233c36ee321d", # Order ID
1768
- # "side": "sell", #Transaction side
1769
- # "liquidity": "taker", #Liquidity- taker or maker
1770
- # "price": "8302", #Filled price
1771
- # "size": 10, #Filled amount
1772
- # "value": "0.001204529", #Order value
1773
- # "feeRate": "0.0005", #Floating fees
1774
- # "fixFee": "0.00000006", #Fixed fees
1775
- # "feeCurrency": "XBT", #Charging currency
1776
- # "stop": "", #A mark to the stop order type
1777
- # "fee": "0.0000012022", #Transaction fee
1778
- # "orderType": "limit", #Order type
1779
- # "tradeType": "trade", #Trade type(trade, liquidation, ADL or settlement)
1780
- # "createdAt": 1558334496000, #Time the order created
1781
- # "settleCurrency": "XBT", #settlement currency
1782
- # "tradeTime": 1558334496000000000 #trade time in nanosecond
1783
- # }
1784
- # ]
1785
- # }
1786
- # }
1787
- #
1788
- data = self.safe_value(response, 'data', {})
1789
- trades = self.safe_list(data, 'items', [])
1790
- return self.parse_trades(trades, market, since, limit)
1791
-
1792
- async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
1793
- """
1794
- set margin mode to 'cross' or 'isolated'
1795
-
1796
- https://api-docs.poloniex.com/futures/api/margin-mode#change-margin-mode
1797
-
1798
- :param str marginMode: "0"(isolated) or "1"(cross)
1799
- :param str symbol: unified market symbol
1800
- :param dict [params]: extra parameters specific to the exchange API endpoint
1801
- :returns dict: response from the exchange
1802
- """
1803
- if symbol is None:
1804
- raise ArgumentsRequired(self.id + ' setMarginMode() requires a symbol argument')
1805
- if (marginMode != '0') and (marginMode != '1') and (marginMode != 'isolated') and (marginMode != 'cross'):
1806
- raise ArgumentsRequired(self.id + ' setMarginMode() marginMode must be 0/isolated or 1/cross')
1807
- await self.load_markets()
1808
- if marginMode == 'isolated':
1809
- marginMode = '0'
1810
- if marginMode == 'cross':
1811
- marginMode = '1'
1812
- market = self.market(symbol)
1813
- request: dict = {
1814
- 'symbol': market['id'],
1815
- 'marginType': self.parse_to_int(marginMode),
1816
- }
1817
- return await self.privatePostMarginTypeChange(request)
1818
-
1819
- def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
1820
- url = self.urls['api'][api]
1821
- versions = self.safe_value(self.options, 'versions', {})
1822
- apiVersions = self.safe_value(versions, api, {})
1823
- methodVersions = self.safe_value(apiVersions, method, {})
1824
- defaultVersion = self.safe_string(methodVersions, path, self.version)
1825
- version = self.safe_string(params, 'version', defaultVersion)
1826
- tail = '/api/' + version + '/' + self.implode_params(path, params)
1827
- url += tail
1828
- query = self.omit(params, self.extract_params(path))
1829
- queryLength = query
1830
- if api == 'public':
1831
- if queryLength:
1832
- url += '?' + self.urlencode(query)
1833
- else:
1834
- self.check_required_credentials()
1835
- endpoint = '/api/v1/' + self.implode_params(path, params)
1836
- bodyEncoded = self.urlencode(query)
1837
- if method != 'GET' and method != 'HEAD':
1838
- body = query
1839
- else:
1840
- if queryLength and bodyEncoded != '':
1841
- url += '?' + bodyEncoded
1842
- endpoint += '?' + bodyEncoded
1843
- now = str(self.milliseconds())
1844
- endpart = ''
1845
- if body is not None:
1846
- body = self.json(query)
1847
- endpart = body
1848
- payload = now + method + endpoint + endpart
1849
- signature = self.hmac(self.encode(payload), self.encode(self.secret), hashlib.sha256, 'base64')
1850
- headers = {
1851
- 'PF-API-SIGN': signature,
1852
- 'PF-API-TIMESTAMP': now,
1853
- 'PF-API-KEY': self.apiKey,
1854
- 'PF-API-PASSPHRASE': self.password,
1855
- }
1856
- headers['Content-Type'] = 'application/json'
1857
- return {'url': url, 'method': method, 'body': body, 'headers': headers}
1858
-
1859
- def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
1860
- if not response:
1861
- self.throw_broadly_matched_exception(self.exceptions['broad'], body, body)
1862
- return None
1863
- #
1864
- # bad
1865
- # {"code": "400100", "msg": "validation.createOrder.clientOidIsRequired"}
1866
- # good
1867
- # {code: "200000", data: {...}}
1868
- #
1869
- errorCode = self.safe_string(response, 'code')
1870
- message = self.safe_string(response, 'msg', '')
1871
- feedback = self.id + ' ' + message
1872
- self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
1873
- self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
1874
- self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
1875
- return None