ccxt-look 1.81.50

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 (264) hide show
  1. package/.cache/eslintcache +1 -0
  2. package/.dockerignore +6 -0
  3. package/.eslintignore +1 -0
  4. package/.gitattributes +5 -0
  5. package/.readthedocs.yaml +16 -0
  6. package/CONTRIBUTING.md +1049 -0
  7. package/LICENSE.txt +21 -0
  8. package/README.md +537 -0
  9. package/SECURITY.md +5 -0
  10. package/build/cleanup-old-tags.js +94 -0
  11. package/build/countries.js +256 -0
  12. package/build/export-exchanges.js +520 -0
  13. package/build/fs.js +51 -0
  14. package/build/transpile.js +1772 -0
  15. package/build/vss.js +78 -0
  16. package/ccxt.browser.js +7 -0
  17. package/ccxt.d.ts +692 -0
  18. package/ccxt.js +171 -0
  19. package/cleanup.sh +2 -0
  20. package/composer-install.sh +20 -0
  21. package/dist/ccxt.browser.js +208383 -0
  22. package/gource.sh +3 -0
  23. package/index.html +7 -0
  24. package/js/.eslintrc +87 -0
  25. package/js/aax.js +2686 -0
  26. package/js/ascendex.js +2584 -0
  27. package/js/base/.eslintrc.js +43 -0
  28. package/js/base/Exchange.js +2371 -0
  29. package/js/base/Precise.js +283 -0
  30. package/js/base/errorHierarchy.js +47 -0
  31. package/js/base/errors.js +55 -0
  32. package/js/base/functions/crypto.js +158 -0
  33. package/js/base/functions/encode.js +118 -0
  34. package/js/base/functions/generic.js +270 -0
  35. package/js/base/functions/misc.js +138 -0
  36. package/js/base/functions/number.js +329 -0
  37. package/js/base/functions/platform.js +38 -0
  38. package/js/base/functions/string.js +21 -0
  39. package/js/base/functions/throttle.js +79 -0
  40. package/js/base/functions/time.js +210 -0
  41. package/js/base/functions/type.js +66 -0
  42. package/js/base/functions.js +28 -0
  43. package/js/bequant.js +32 -0
  44. package/js/bibox.js +1407 -0
  45. package/js/bigone.js +1366 -0
  46. package/js/binance.js +5652 -0
  47. package/js/binancecoinm.js +46 -0
  48. package/js/binanceus.js +46 -0
  49. package/js/binanceusdm.js +49 -0
  50. package/js/bit2c.js +535 -0
  51. package/js/bitbank.js +842 -0
  52. package/js/bitbay.js +16 -0
  53. package/js/bitbns.js +1073 -0
  54. package/js/bitcoincom.js +15 -0
  55. package/js/bitfinex.js +1433 -0
  56. package/js/bitfinex2.js +2025 -0
  57. package/js/bitflyer.js +840 -0
  58. package/js/bitforex.js +614 -0
  59. package/js/bitget.js +2397 -0
  60. package/js/bithumb.js +980 -0
  61. package/js/bitmart.js +2516 -0
  62. package/js/bitmex.js +1809 -0
  63. package/js/bitopro.js +1443 -0
  64. package/js/bitpanda.js +1782 -0
  65. package/js/bitrue.js +1747 -0
  66. package/js/bitso.js +1062 -0
  67. package/js/bitstamp.js +1757 -0
  68. package/js/bitstamp1.js +343 -0
  69. package/js/bittrex.js +1876 -0
  70. package/js/bitvavo.js +1579 -0
  71. package/js/bkex.js +1233 -0
  72. package/js/bl3p.js +346 -0
  73. package/js/blockchaincom.js +969 -0
  74. package/js/btcalpha.js +680 -0
  75. package/js/btcbox.js +477 -0
  76. package/js/btcmarkets.js +1022 -0
  77. package/js/btctradeua.js +466 -0
  78. package/js/btcturk.js +734 -0
  79. package/js/buda.js +946 -0
  80. package/js/bw.js +1265 -0
  81. package/js/bybit.js +3372 -0
  82. package/js/bytetrade.js +1336 -0
  83. package/js/cdax.js +1646 -0
  84. package/js/cex.js +1410 -0
  85. package/js/coinbase.js +1342 -0
  86. package/js/coinbaseprime.js +31 -0
  87. package/js/coinbasepro.js +1466 -0
  88. package/js/coincheck.js +755 -0
  89. package/js/coinex.js +3400 -0
  90. package/js/coinfalcon.js +880 -0
  91. package/js/coinmate.js +794 -0
  92. package/js/coinone.js +816 -0
  93. package/js/coinspot.js +345 -0
  94. package/js/crex24.js +1636 -0
  95. package/js/cryptocom.js +1832 -0
  96. package/js/currencycom.js +1748 -0
  97. package/js/delta.js +1547 -0
  98. package/js/deribit.js +2148 -0
  99. package/js/digifinex.js +1585 -0
  100. package/js/eqonex.js +1660 -0
  101. package/js/exmo.js +1670 -0
  102. package/js/fairdesk.js +1231 -0
  103. package/js/flowbtc.js +35 -0
  104. package/js/fmfwio.js +34 -0
  105. package/js/ftx.js +2751 -0
  106. package/js/ftxus.js +38 -0
  107. package/js/gateio.js +4174 -0
  108. package/js/gemini.js +1397 -0
  109. package/js/hitbtc.js +1343 -0
  110. package/js/hitbtc3.js +2329 -0
  111. package/js/hollaex.js +1486 -0
  112. package/js/huobi.js +5706 -0
  113. package/js/huobijp.js +1710 -0
  114. package/js/huobipro.js +18 -0
  115. package/js/idex.js +1439 -0
  116. package/js/independentreserve.js +649 -0
  117. package/js/indodax.js +742 -0
  118. package/js/itbit.js +722 -0
  119. package/js/kraken.js +2179 -0
  120. package/js/kucoin.js +2571 -0
  121. package/js/kucoinfutures.js +1771 -0
  122. package/js/kuna.js +809 -0
  123. package/js/latoken.js +1445 -0
  124. package/js/lbank.js +760 -0
  125. package/js/liquid.js +1432 -0
  126. package/js/luno.js +873 -0
  127. package/js/lykke.js +1147 -0
  128. package/js/mercado.js +771 -0
  129. package/js/mexc.js +3151 -0
  130. package/js/ndax.js +2233 -0
  131. package/js/novadax.js +1318 -0
  132. package/js/oceanex.js +816 -0
  133. package/js/okcoin.js +3841 -0
  134. package/js/okex.js +16 -0
  135. package/js/okex5.js +16 -0
  136. package/js/okx.js +4795 -0
  137. package/js/paymium.js +498 -0
  138. package/js/phemex.js +2957 -0
  139. package/js/poloniex.js +1674 -0
  140. package/js/probit.js +1346 -0
  141. package/js/qtrade.js +1588 -0
  142. package/js/ripio.js +1061 -0
  143. package/js/static_dependencies/BN/bn.js +3526 -0
  144. package/js/static_dependencies/README.md +1 -0
  145. package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
  146. package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
  147. package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
  148. package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
  149. package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
  150. package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
  151. package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
  152. package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
  153. package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
  154. package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
  155. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
  156. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
  157. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
  158. package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
  159. package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
  160. package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
  161. package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
  162. package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
  163. package/js/static_dependencies/node-fetch/index.js +1564 -0
  164. package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
  165. package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
  166. package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
  167. package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
  168. package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
  169. package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
  170. package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
  171. package/js/static_dependencies/node-rsa/formats/components.js +71 -0
  172. package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
  173. package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
  174. package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
  175. package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
  176. package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
  177. package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
  178. package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
  179. package/js/static_dependencies/node-rsa/utils.js +98 -0
  180. package/js/static_dependencies/qs/formats.js +18 -0
  181. package/js/static_dependencies/qs/index.js +11 -0
  182. package/js/static_dependencies/qs/parse.js +242 -0
  183. package/js/static_dependencies/qs/stringify.js +269 -0
  184. package/js/static_dependencies/qs/utils.js +230 -0
  185. package/js/stex.js +1925 -0
  186. package/js/test/.eslintrc.js +42 -0
  187. package/js/test/Exchange/test.balance.js +61 -0
  188. package/js/test/Exchange/test.borrowRate.js +32 -0
  189. package/js/test/Exchange/test.currency.js +52 -0
  190. package/js/test/Exchange/test.fetchBalance.js +23 -0
  191. package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
  192. package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
  193. package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
  194. package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
  195. package/js/test/Exchange/test.fetchCurrencies.js +35 -0
  196. package/js/test/Exchange/test.fetchDeposits.js +31 -0
  197. package/js/test/Exchange/test.fetchFundingFees.js +19 -0
  198. package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
  199. package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
  200. package/js/test/Exchange/test.fetchLedger.js +42 -0
  201. package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
  202. package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
  203. package/js/test/Exchange/test.fetchMarkets.js +33 -0
  204. package/js/test/Exchange/test.fetchMyTrades.js +42 -0
  205. package/js/test/Exchange/test.fetchOHLCV.js +46 -0
  206. package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
  207. package/js/test/Exchange/test.fetchOrderBook.js +25 -0
  208. package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
  209. package/js/test/Exchange/test.fetchOrders.js +41 -0
  210. package/js/test/Exchange/test.fetchPositions.js +47 -0
  211. package/js/test/Exchange/test.fetchStatus.js +35 -0
  212. package/js/test/Exchange/test.fetchTicker.js +38 -0
  213. package/js/test/Exchange/test.fetchTickers.js +49 -0
  214. package/js/test/Exchange/test.fetchTrades.js +39 -0
  215. package/js/test/Exchange/test.fetchTradingFee.js +18 -0
  216. package/js/test/Exchange/test.fetchTradingFees.js +22 -0
  217. package/js/test/Exchange/test.fetchTransactions.js +31 -0
  218. package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
  219. package/js/test/Exchange/test.ledgerItem.js +46 -0
  220. package/js/test/Exchange/test.leverageTier.js +33 -0
  221. package/js/test/Exchange/test.loadMarkets.js +35 -0
  222. package/js/test/Exchange/test.market.js +129 -0
  223. package/js/test/Exchange/test.ohlcv.js +33 -0
  224. package/js/test/Exchange/test.order.js +62 -0
  225. package/js/test/Exchange/test.orderbook.js +61 -0
  226. package/js/test/Exchange/test.position.js +21 -0
  227. package/js/test/Exchange/test.throttle.js +94 -0
  228. package/js/test/Exchange/test.ticker.js +95 -0
  229. package/js/test/Exchange/test.trade.js +68 -0
  230. package/js/test/Exchange/test.tradingFee.js +34 -0
  231. package/js/test/Exchange/test.transaction.js +35 -0
  232. package/js/test/base/.eslintrc +38 -0
  233. package/js/test/base/functions/test.crypto.js +110 -0
  234. package/js/test/base/functions/test.datetime.js +62 -0
  235. package/js/test/base/functions/test.generic.js +152 -0
  236. package/js/test/base/functions/test.number.js +362 -0
  237. package/js/test/base/functions/test.time.js +56 -0
  238. package/js/test/base/functions/test.type.js +53 -0
  239. package/js/test/base/test.base.js +193 -0
  240. package/js/test/errors/test.InsufficientFunds.js +86 -0
  241. package/js/test/errors/test.InvalidNonce.js +64 -0
  242. package/js/test/errors/test.InvalidOrder.js +35 -0
  243. package/js/test/errors/test.OrderNotFound.js +39 -0
  244. package/js/test/test.js +426 -0
  245. package/js/test/test.timeout_hang.js +12 -0
  246. package/js/therock.js +1431 -0
  247. package/js/tidebit.js +632 -0
  248. package/js/tidex.js +939 -0
  249. package/js/timex.js +1283 -0
  250. package/js/upbit.js +1622 -0
  251. package/js/vcc.js +1353 -0
  252. package/js/wavesexchange.js +2185 -0
  253. package/js/wazirx.js +732 -0
  254. package/js/whitebit.js +1352 -0
  255. package/js/woo.js +1577 -0
  256. package/js/xena.js +1948 -0
  257. package/js/yobit.js +1129 -0
  258. package/js/zaif.js +647 -0
  259. package/js/zb.js +4088 -0
  260. package/js/zipmex.js +40 -0
  261. package/js/zonda.js +1497 -0
  262. package/multilang.sh +159 -0
  263. package/package.json +591 -0
  264. package/postinstall.js +103 -0
package/js/bitmex.js ADDED
@@ -0,0 +1,1809 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { TICK_SIZE } = require ('./base/functions/number');
7
+ const { AuthenticationError, BadRequest, DDoSProtection, ExchangeError, ExchangeNotAvailable, InsufficientFunds, InvalidOrder, OrderNotFound, PermissionDenied, ArgumentsRequired, BadSymbol } = require ('./base/errors');
8
+ const Precise = require ('./base/Precise');
9
+
10
+ // ---------------------------------------------------------------------------
11
+
12
+ module.exports = class bitmex extends Exchange {
13
+ describe () {
14
+ return this.deepExtend (super.describe (), {
15
+ 'id': 'bitmex',
16
+ 'name': 'BitMEX',
17
+ 'countries': [ 'SC' ], // Seychelles
18
+ 'version': 'v1',
19
+ 'userAgent': undefined,
20
+ 'rateLimit': 2000,
21
+ 'pro': true,
22
+ 'has': {
23
+ 'CORS': undefined,
24
+ 'spot': false,
25
+ 'margin': false,
26
+ 'swap': undefined, // has but not fully implemented
27
+ 'future': undefined, // has but not fully implemented
28
+ 'option': undefined, // has but not fully implemented
29
+ 'cancelAllOrders': true,
30
+ 'cancelOrder': true,
31
+ 'cancelOrders': true,
32
+ 'createOrder': true,
33
+ 'editOrder': true,
34
+ 'fetchBalance': true,
35
+ 'fetchClosedOrders': true,
36
+ 'fetchIndexOHLCV': false,
37
+ 'fetchLedger': true,
38
+ 'fetchLeverageTiers': false,
39
+ 'fetchMarkets': true,
40
+ 'fetchMarkOHLCV': false,
41
+ 'fetchMyTrades': true,
42
+ 'fetchOHLCV': true,
43
+ 'fetchOpenOrders': true,
44
+ 'fetchOrder': true,
45
+ 'fetchOrderBook': true,
46
+ 'fetchOrders': true,
47
+ 'fetchPositions': true,
48
+ 'fetchPremiumIndexOHLCV': false,
49
+ 'fetchTicker': true,
50
+ 'fetchTickers': true,
51
+ 'fetchTrades': true,
52
+ 'fetchTransactions': 'emulated',
53
+ 'fetchTransfer': false,
54
+ 'fetchTransfers': false,
55
+ 'transfer': false,
56
+ 'withdraw': true,
57
+ },
58
+ 'timeframes': {
59
+ '1m': '1m',
60
+ '5m': '5m',
61
+ '1h': '1h',
62
+ '1d': '1d',
63
+ },
64
+ 'urls': {
65
+ 'test': {
66
+ 'public': 'https://testnet.bitmex.com',
67
+ 'private': 'https://testnet.bitmex.com',
68
+ },
69
+ 'logo': 'https://user-images.githubusercontent.com/1294454/27766319-f653c6e6-5ed4-11e7-933d-f0bc3699ae8f.jpg',
70
+ 'api': {
71
+ 'public': 'https://www.bitmex.com',
72
+ 'private': 'https://www.bitmex.com',
73
+ },
74
+ 'www': 'https://www.bitmex.com',
75
+ 'doc': [
76
+ 'https://www.bitmex.com/app/apiOverview',
77
+ 'https://github.com/BitMEX/api-connectors/tree/master/official-http',
78
+ ],
79
+ 'fees': 'https://www.bitmex.com/app/fees',
80
+ 'referral': 'https://www.bitmex.com/register/upZpOX',
81
+ },
82
+ 'api': {
83
+ 'public': {
84
+ 'get': [
85
+ 'announcement',
86
+ 'announcement/urgent',
87
+ 'funding',
88
+ 'instrument',
89
+ 'instrument/active',
90
+ 'instrument/activeAndIndices',
91
+ 'instrument/activeIntervals',
92
+ 'instrument/compositeIndex',
93
+ 'instrument/indices',
94
+ 'insurance',
95
+ 'leaderboard',
96
+ 'liquidation',
97
+ 'orderBook',
98
+ 'orderBook/L2',
99
+ 'quote',
100
+ 'quote/bucketed',
101
+ 'schema',
102
+ 'schema/websocketHelp',
103
+ 'settlement',
104
+ 'stats',
105
+ 'stats/history',
106
+ 'trade',
107
+ 'trade/bucketed',
108
+ ],
109
+ },
110
+ 'private': {
111
+ 'get': [
112
+ 'apiKey',
113
+ 'chat',
114
+ 'chat/channels',
115
+ 'chat/connected',
116
+ 'execution',
117
+ 'execution/tradeHistory',
118
+ 'notification',
119
+ 'order',
120
+ 'position',
121
+ 'user',
122
+ 'user/affiliateStatus',
123
+ 'user/checkReferralCode',
124
+ 'user/commission',
125
+ 'user/depositAddress',
126
+ 'user/executionHistory',
127
+ 'user/margin',
128
+ 'user/minWithdrawalFee',
129
+ 'user/wallet',
130
+ 'user/walletHistory',
131
+ 'user/walletSummary',
132
+ ],
133
+ 'post': [
134
+ 'apiKey',
135
+ 'apiKey/disable',
136
+ 'apiKey/enable',
137
+ 'chat',
138
+ 'order',
139
+ 'order/bulk',
140
+ 'order/cancelAllAfter',
141
+ 'order/closePosition',
142
+ 'position/isolate',
143
+ 'position/leverage',
144
+ 'position/riskLimit',
145
+ 'position/transferMargin',
146
+ 'user/cancelWithdrawal',
147
+ 'user/confirmEmail',
148
+ 'user/confirmEnableTFA',
149
+ 'user/confirmWithdrawal',
150
+ 'user/disableTFA',
151
+ 'user/logout',
152
+ 'user/logoutAll',
153
+ 'user/preferences',
154
+ 'user/requestEnableTFA',
155
+ 'user/requestWithdrawal',
156
+ ],
157
+ 'put': [
158
+ 'order',
159
+ 'order/bulk',
160
+ 'user',
161
+ ],
162
+ 'delete': [
163
+ 'apiKey',
164
+ 'order',
165
+ 'order/all',
166
+ ],
167
+ },
168
+ },
169
+ 'exceptions': {
170
+ 'exact': {
171
+ 'Invalid API Key.': AuthenticationError,
172
+ 'This key is disabled.': PermissionDenied,
173
+ 'Access Denied': PermissionDenied,
174
+ 'Duplicate clOrdID': InvalidOrder,
175
+ 'orderQty is invalid': InvalidOrder,
176
+ 'Invalid price': InvalidOrder,
177
+ 'Invalid stopPx for ordType': InvalidOrder,
178
+ },
179
+ 'broad': {
180
+ 'Signature not valid': AuthenticationError,
181
+ 'overloaded': ExchangeNotAvailable,
182
+ 'Account has insufficient Available Balance': InsufficientFunds,
183
+ 'Service unavailable': ExchangeNotAvailable, // {"error":{"message":"Service unavailable","name":"HTTPError"}}
184
+ 'Server Error': ExchangeError, // {"error":{"message":"Server Error","name":"HTTPError"}}
185
+ 'Unable to cancel order due to existing state': InvalidOrder,
186
+ },
187
+ },
188
+ 'precisionMode': TICK_SIZE,
189
+ 'options': {
190
+ // https://blog.bitmex.com/api_announcement/deprecation-of-api-nonce-header/
191
+ // https://github.com/ccxt/ccxt/issues/4789
192
+ 'api-expires': 5, // in seconds
193
+ 'fetchOHLCVOpenTimestamp': true,
194
+ },
195
+ 'commonCurrencies': {
196
+ 'USDt': 'USDT',
197
+ 'XBt': 'BTC',
198
+ 'XBT': 'BTC',
199
+ },
200
+ });
201
+ }
202
+
203
+ async fetchMarkets (params = {}) {
204
+ const response = await this.publicGetInstrumentActiveAndIndices (params);
205
+ //
206
+ // {
207
+ // "symbol": "LTCUSDT",
208
+ // "rootSymbol": "LTC",
209
+ // "state": "Open",
210
+ // "typ": "FFWCSX",
211
+ // "listing": "2021-11-10T04:00:00.000Z",
212
+ // "front": "2021-11-10T04:00:00.000Z",
213
+ // "expiry": null,
214
+ // "settle": null,
215
+ // "listedSettle": null,
216
+ // "relistInterval": null,
217
+ // "inverseLeg": "",
218
+ // "sellLeg": "",
219
+ // "buyLeg": "",
220
+ // "optionStrikePcnt": null,
221
+ // "optionStrikeRound": null,
222
+ // "optionStrikePrice": null,
223
+ // "optionMultiplier": null,
224
+ // "positionCurrency": "LTC",
225
+ // "underlying": "LTC",
226
+ // "quoteCurrency": "USDT",
227
+ // "underlyingSymbol": "LTCT=",
228
+ // "reference": "BMEX",
229
+ // "referenceSymbol": ".BLTCT",
230
+ // "calcInterval": null,
231
+ // "publishInterval": null,
232
+ // "publishTime": null,
233
+ // "maxOrderQty": 1000000000,
234
+ // "maxPrice": 1000000,
235
+ // "lotSize": 1000,
236
+ // "tickSize": 0.01,
237
+ // "multiplier": 100,
238
+ // "settlCurrency": "USDt",
239
+ // "underlyingToPositionMultiplier": 10000,
240
+ // "underlyingToSettleMultiplier": null,
241
+ // "quoteToSettleMultiplier": 1000000,
242
+ // "isQuanto": false,
243
+ // "isInverse": false,
244
+ // "initMargin": 0.03,
245
+ // "maintMargin": 0.015,
246
+ // "riskLimit": 1000000000000,
247
+ // "riskStep": 1000000000000,
248
+ // "limit": null,
249
+ // "capped": false,
250
+ // "taxed": true,
251
+ // "deleverage": true,
252
+ // "makerFee": -0.0001,
253
+ // "takerFee": 0.0005,
254
+ // "settlementFee": 0,
255
+ // "insuranceFee": 0,
256
+ // "fundingBaseSymbol": ".LTCBON8H",
257
+ // "fundingQuoteSymbol": ".USDTBON8H",
258
+ // "fundingPremiumSymbol": ".LTCUSDTPI8H",
259
+ // "fundingTimestamp": "2022-01-14T20:00:00.000Z",
260
+ // "fundingInterval": "2000-01-01T08:00:00.000Z",
261
+ // "fundingRate": 0.0001,
262
+ // "indicativeFundingRate": 0.0001,
263
+ // "rebalanceTimestamp": null,
264
+ // "rebalanceInterval": null,
265
+ // "openingTimestamp": "2022-01-14T17:00:00.000Z",
266
+ // "closingTimestamp": "2022-01-14T18:00:00.000Z",
267
+ // "sessionInterval": "2000-01-01T01:00:00.000Z",
268
+ // "prevClosePrice": 138.511,
269
+ // "limitDownPrice": null,
270
+ // "limitUpPrice": null,
271
+ // "bankruptLimitDownPrice": null,
272
+ // "bankruptLimitUpPrice": null,
273
+ // "prevTotalVolume": 12699024000,
274
+ // "totalVolume": 12702160000,
275
+ // "volume": 3136000,
276
+ // "volume24h": 114251000,
277
+ // "prevTotalTurnover": 232418052349000,
278
+ // "totalTurnover": 232463353260000,
279
+ // "turnover": 45300911000,
280
+ // "turnover24h": 1604331340000,
281
+ // "homeNotional24h": 11425.1,
282
+ // "foreignNotional24h": 1604331.3400000003,
283
+ // "prevPrice24h": 135.48,
284
+ // "vwap": 140.42165,
285
+ // "highPrice": 146.42,
286
+ // "lowPrice": 135.08,
287
+ // "lastPrice": 144.36,
288
+ // "lastPriceProtected": 144.36,
289
+ // "lastTickDirection": "MinusTick",
290
+ // "lastChangePcnt": 0.0655,
291
+ // "bidPrice": 143.75,
292
+ // "midPrice": 143.855,
293
+ // "askPrice": 143.96,
294
+ // "impactBidPrice": 143.75,
295
+ // "impactMidPrice": 143.855,
296
+ // "impactAskPrice": 143.96,
297
+ // "hasLiquidity": true,
298
+ // "openInterest": 38103000,
299
+ // "openValue": 547963053300,
300
+ // "fairMethod": "FundingRate",
301
+ // "fairBasisRate": 0.1095,
302
+ // "fairBasis": 0.004,
303
+ // "fairPrice": 143.811,
304
+ // "markMethod": "FairPrice",
305
+ // "markPrice": 143.811,
306
+ // "indicativeTaxRate": null,
307
+ // "indicativeSettlePrice": 143.807,
308
+ // "optionUnderlyingPrice": null,
309
+ // "settledPriceAdjustmentRate": null,
310
+ // "settledPrice": null,
311
+ // "timestamp": "2022-01-14T17:49:55.000Z"
312
+ // }
313
+ //
314
+ const result = [];
315
+ for (let i = 0; i < response.length; i++) {
316
+ const market = response[i];
317
+ const id = this.safeString (market, 'symbol');
318
+ const baseId = this.safeString (market, 'underlying');
319
+ const quoteId = this.safeString (market, 'quoteCurrency');
320
+ const settleId = this.safeString (market, 'settlCurrency');
321
+ const base = this.safeCurrencyCode (baseId);
322
+ const quote = this.safeCurrencyCode (quoteId);
323
+ const settle = this.safeCurrencyCode (settleId);
324
+ const basequote = baseId + quoteId;
325
+ const swap = (id === basequote);
326
+ // 'positionCurrency' may be empty ("", as Bitmex currently returns for ETHUSD)
327
+ // so let's take the quote currency first and then adjust if needed
328
+ let type = undefined;
329
+ let future = false;
330
+ let prediction = false;
331
+ let index = false;
332
+ let symbol = base + '/' + quote + ':' + settle;
333
+ const expiryDatetime = this.safeString (market, 'expiry');
334
+ const expiry = this.parse8601 (expiryDatetime);
335
+ const inverse = this.safeValue (market, 'isInverse');
336
+ const status = this.safeString (market, 'state');
337
+ let active = status !== 'Unlisted';
338
+ if (swap) {
339
+ type = 'swap';
340
+ } else if (id.indexOf ('B_') >= 0) {
341
+ prediction = true;
342
+ type = 'prediction';
343
+ symbol = id;
344
+ } else if (expiry !== undefined) {
345
+ future = true;
346
+ type = 'future';
347
+ symbol = symbol + '-' + this.yymmdd (expiry);
348
+ } else {
349
+ index = true;
350
+ type = 'index';
351
+ symbol = id;
352
+ active = false;
353
+ }
354
+ const positionId = this.safeString2 (market, 'positionCurrency', 'quoteCurrency');
355
+ const position = this.safeCurrencyCode (positionId);
356
+ const positionIsQuote = (position === quote);
357
+ const maxOrderQty = this.safeNumber (market, 'maxOrderQty');
358
+ const contract = !index;
359
+ const initMargin = this.safeString (market, 'initMargin', '1');
360
+ const maxLeverage = this.parseNumber (Precise.stringDiv ('1', initMargin));
361
+ result.push ({
362
+ 'id': id,
363
+ 'symbol': symbol,
364
+ 'base': base,
365
+ 'quote': quote,
366
+ 'settle': settle,
367
+ 'baseId': baseId,
368
+ 'quoteId': quoteId,
369
+ 'settleId': settleId,
370
+ 'type': type,
371
+ 'spot': false,
372
+ 'margin': false,
373
+ 'swap': swap,
374
+ 'future': future,
375
+ 'option': false,
376
+ 'prediction': prediction,
377
+ 'index': index,
378
+ 'active': active,
379
+ 'contract': contract,
380
+ 'linear': contract ? !inverse : undefined,
381
+ 'inverse': contract ? inverse : undefined,
382
+ 'taker': this.safeNumber (market, 'takerFee'),
383
+ 'maker': this.safeNumber (market, 'makerFee'),
384
+ 'contractSize': this.safeNumber (market, 'multiplier'),
385
+ 'expiry': expiry,
386
+ 'expiryDatetime': expiryDatetime,
387
+ 'strike': this.safeNumber (market, 'optionStrikePrice'),
388
+ 'optionType': undefined,
389
+ 'precision': {
390
+ 'amount': this.safeNumber (market, 'lotSize'),
391
+ 'price': this.safeNumber (market, 'tickSize'),
392
+ },
393
+ 'limits': {
394
+ 'leverage': {
395
+ 'min': contract ? this.parseNumber ('1') : undefined,
396
+ 'max': contract ? maxLeverage : undefined,
397
+ },
398
+ 'amount': {
399
+ 'min': undefined,
400
+ 'max': positionIsQuote ? undefined : maxOrderQty,
401
+ },
402
+ 'price': {
403
+ 'min': undefined,
404
+ 'max': this.safeNumber (market, 'maxPrice'),
405
+ },
406
+ 'cost': {
407
+ 'min': undefined,
408
+ 'max': positionIsQuote ? maxOrderQty : undefined,
409
+ },
410
+ },
411
+ 'info': market,
412
+ });
413
+ }
414
+ return result;
415
+ }
416
+
417
+ parseBalance (response) {
418
+ //
419
+ // [
420
+ // {
421
+ // "account":1455728,
422
+ // "currency":"XBt",
423
+ // "riskLimit":1000000000000,
424
+ // "prevState":"",
425
+ // "state":"",
426
+ // "action":"",
427
+ // "amount":263542,
428
+ // "pendingCredit":0,
429
+ // "pendingDebit":0,
430
+ // "confirmedDebit":0,
431
+ // "prevRealisedPnl":0,
432
+ // "prevUnrealisedPnl":0,
433
+ // "grossComm":0,
434
+ // "grossOpenCost":0,
435
+ // "grossOpenPremium":0,
436
+ // "grossExecCost":0,
437
+ // "grossMarkValue":0,
438
+ // "riskValue":0,
439
+ // "taxableMargin":0,
440
+ // "initMargin":0,
441
+ // "maintMargin":0,
442
+ // "sessionMargin":0,
443
+ // "targetExcessMargin":0,
444
+ // "varMargin":0,
445
+ // "realisedPnl":0,
446
+ // "unrealisedPnl":0,
447
+ // "indicativeTax":0,
448
+ // "unrealisedProfit":0,
449
+ // "syntheticMargin":null,
450
+ // "walletBalance":263542,
451
+ // "marginBalance":263542,
452
+ // "marginBalancePcnt":1,
453
+ // "marginLeverage":0,
454
+ // "marginUsedPcnt":0,
455
+ // "excessMargin":263542,
456
+ // "excessMarginPcnt":1,
457
+ // "availableMargin":263542,
458
+ // "withdrawableMargin":263542,
459
+ // "timestamp":"2020-08-03T12:01:01.246Z",
460
+ // "grossLastValue":0,
461
+ // "commission":null
462
+ // }
463
+ // ]
464
+ //
465
+ const result = { 'info': response };
466
+ for (let i = 0; i < response.length; i++) {
467
+ const balance = response[i];
468
+ const currencyId = this.safeString (balance, 'currency');
469
+ const code = this.safeCurrencyCode (currencyId);
470
+ const account = this.account ();
471
+ let free = this.safeString (balance, 'availableMargin');
472
+ let total = this.safeString (balance, 'marginBalance');
473
+ if (code === 'BTC') {
474
+ free = Precise.stringDiv (free, '1e8');
475
+ total = Precise.stringDiv (total, '1e8');
476
+ }
477
+ account['free'] = free;
478
+ account['total'] = total;
479
+ result[code] = account;
480
+ }
481
+ return this.safeBalance (result);
482
+ }
483
+
484
+ async fetchBalance (params = {}) {
485
+ await this.loadMarkets ();
486
+ const request = {
487
+ 'currency': 'all',
488
+ };
489
+ const response = await this.privateGetUserMargin (this.extend (request, params));
490
+ //
491
+ // [
492
+ // {
493
+ // "account":1455728,
494
+ // "currency":"XBt",
495
+ // "riskLimit":1000000000000,
496
+ // "prevState":"",
497
+ // "state":"",
498
+ // "action":"",
499
+ // "amount":263542,
500
+ // "pendingCredit":0,
501
+ // "pendingDebit":0,
502
+ // "confirmedDebit":0,
503
+ // "prevRealisedPnl":0,
504
+ // "prevUnrealisedPnl":0,
505
+ // "grossComm":0,
506
+ // "grossOpenCost":0,
507
+ // "grossOpenPremium":0,
508
+ // "grossExecCost":0,
509
+ // "grossMarkValue":0,
510
+ // "riskValue":0,
511
+ // "taxableMargin":0,
512
+ // "initMargin":0,
513
+ // "maintMargin":0,
514
+ // "sessionMargin":0,
515
+ // "targetExcessMargin":0,
516
+ // "varMargin":0,
517
+ // "realisedPnl":0,
518
+ // "unrealisedPnl":0,
519
+ // "indicativeTax":0,
520
+ // "unrealisedProfit":0,
521
+ // "syntheticMargin":null,
522
+ // "walletBalance":263542,
523
+ // "marginBalance":263542,
524
+ // "marginBalancePcnt":1,
525
+ // "marginLeverage":0,
526
+ // "marginUsedPcnt":0,
527
+ // "excessMargin":263542,
528
+ // "excessMarginPcnt":1,
529
+ // "availableMargin":263542,
530
+ // "withdrawableMargin":263542,
531
+ // "timestamp":"2020-08-03T12:01:01.246Z",
532
+ // "grossLastValue":0,
533
+ // "commission":null
534
+ // }
535
+ // ]
536
+ //
537
+ return this.parseBalance (response);
538
+ }
539
+
540
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
541
+ await this.loadMarkets ();
542
+ const market = this.market (symbol);
543
+ const request = {
544
+ 'symbol': market['id'],
545
+ };
546
+ if (limit !== undefined) {
547
+ request['depth'] = limit;
548
+ }
549
+ const response = await this.publicGetOrderBookL2 (this.extend (request, params));
550
+ const result = {
551
+ 'symbol': symbol,
552
+ 'bids': [],
553
+ 'asks': [],
554
+ 'timestamp': undefined,
555
+ 'datetime': undefined,
556
+ 'nonce': undefined,
557
+ };
558
+ for (let i = 0; i < response.length; i++) {
559
+ const order = response[i];
560
+ const side = (order['side'] === 'Sell') ? 'asks' : 'bids';
561
+ const amount = this.safeNumber (order, 'size');
562
+ const price = this.safeNumber (order, 'price');
563
+ // https://github.com/ccxt/ccxt/issues/4926
564
+ // https://github.com/ccxt/ccxt/issues/4927
565
+ // the exchange sometimes returns null price in the orderbook
566
+ if (price !== undefined) {
567
+ result[side].push ([ price, amount ]);
568
+ }
569
+ }
570
+ result['bids'] = this.sortBy (result['bids'], 0, true);
571
+ result['asks'] = this.sortBy (result['asks'], 0);
572
+ return result;
573
+ }
574
+
575
+ async fetchOrder (id, symbol = undefined, params = {}) {
576
+ const filter = {
577
+ 'filter': {
578
+ 'orderID': id,
579
+ },
580
+ };
581
+ const response = await this.fetchOrders (symbol, undefined, undefined, this.deepExtend (filter, params));
582
+ const numResults = response.length;
583
+ if (numResults === 1) {
584
+ return response[0];
585
+ }
586
+ throw new OrderNotFound (this.id + ': The order ' + id + ' not found.');
587
+ }
588
+
589
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
590
+ await this.loadMarkets ();
591
+ let market = undefined;
592
+ let request = {};
593
+ if (symbol !== undefined) {
594
+ market = this.market (symbol);
595
+ request['symbol'] = market['id'];
596
+ }
597
+ if (since !== undefined) {
598
+ request['startTime'] = this.iso8601 (since);
599
+ }
600
+ if (limit !== undefined) {
601
+ request['count'] = limit;
602
+ }
603
+ request = this.deepExtend (request, params);
604
+ // why the hassle? urlencode in python is kinda broken for nested dicts.
605
+ // E.g. self.urlencode({"filter": {"open": True}}) will return "filter={'open':+True}"
606
+ // Bitmex doesn't like that. Hence resorting to this hack.
607
+ if ('filter' in request) {
608
+ request['filter'] = this.json (request['filter']);
609
+ }
610
+ const response = await this.privateGetOrder (request);
611
+ return this.parseOrders (response, market, since, limit);
612
+ }
613
+
614
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
615
+ const request = {
616
+ 'filter': {
617
+ 'open': true,
618
+ },
619
+ };
620
+ return await this.fetchOrders (symbol, since, limit, this.deepExtend (request, params));
621
+ }
622
+
623
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
624
+ // Bitmex barfs if you set 'open': false in the filter...
625
+ const orders = await this.fetchOrders (symbol, since, limit, params);
626
+ return this.filterBy (orders, 'status', 'closed');
627
+ }
628
+
629
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
630
+ await this.loadMarkets ();
631
+ let market = undefined;
632
+ let request = {};
633
+ if (symbol !== undefined) {
634
+ market = this.market (symbol);
635
+ request['symbol'] = market['id'];
636
+ }
637
+ if (since !== undefined) {
638
+ request['startTime'] = this.iso8601 (since);
639
+ }
640
+ if (limit !== undefined) {
641
+ request['count'] = limit;
642
+ }
643
+ request = this.deepExtend (request, params);
644
+ // why the hassle? urlencode in python is kinda broken for nested dicts.
645
+ // E.g. self.urlencode({"filter": {"open": True}}) will return "filter={'open':+True}"
646
+ // Bitmex doesn't like that. Hence resorting to this hack.
647
+ if ('filter' in request) {
648
+ request['filter'] = this.json (request['filter']);
649
+ }
650
+ const response = await this.privateGetExecutionTradeHistory (request);
651
+ //
652
+ // [
653
+ // {
654
+ // "execID": "string",
655
+ // "orderID": "string",
656
+ // "clOrdID": "string",
657
+ // "clOrdLinkID": "string",
658
+ // "account": 0,
659
+ // "symbol": "string",
660
+ // "side": "string",
661
+ // "lastQty": 0,
662
+ // "lastPx": 0,
663
+ // "underlyingLastPx": 0,
664
+ // "lastMkt": "string",
665
+ // "lastLiquidityInd": "string",
666
+ // "simpleOrderQty": 0,
667
+ // "orderQty": 0,
668
+ // "price": 0,
669
+ // "displayQty": 0,
670
+ // "stopPx": 0,
671
+ // "pegOffsetValue": 0,
672
+ // "pegPriceType": "string",
673
+ // "currency": "string",
674
+ // "settlCurrency": "string",
675
+ // "execType": "string",
676
+ // "ordType": "string",
677
+ // "timeInForce": "string",
678
+ // "execInst": "string",
679
+ // "contingencyType": "string",
680
+ // "exDestination": "string",
681
+ // "ordStatus": "string",
682
+ // "triggered": "string",
683
+ // "workingIndicator": true,
684
+ // "ordRejReason": "string",
685
+ // "simpleLeavesQty": 0,
686
+ // "leavesQty": 0,
687
+ // "simpleCumQty": 0,
688
+ // "cumQty": 0,
689
+ // "avgPx": 0,
690
+ // "commission": 0,
691
+ // "tradePublishIndicator": "string",
692
+ // "multiLegReportingType": "string",
693
+ // "text": "string",
694
+ // "trdMatchID": "string",
695
+ // "execCost": 0,
696
+ // "execComm": 0,
697
+ // "homeNotional": 0,
698
+ // "foreignNotional": 0,
699
+ // "transactTime": "2019-03-05T12:47:02.762Z",
700
+ // "timestamp": "2019-03-05T12:47:02.762Z"
701
+ // }
702
+ // ]
703
+ //
704
+ return this.parseTrades (response, market, since, limit);
705
+ }
706
+
707
+ parseLedgerEntryType (type) {
708
+ const types = {
709
+ 'Withdrawal': 'transaction',
710
+ 'RealisedPNL': 'margin',
711
+ 'UnrealisedPNL': 'margin',
712
+ 'Deposit': 'transaction',
713
+ 'Transfer': 'transfer',
714
+ 'AffiliatePayout': 'referral',
715
+ };
716
+ return this.safeString (types, type, type);
717
+ }
718
+
719
+ parseLedgerEntry (item, currency = undefined) {
720
+ //
721
+ // {
722
+ // transactID: "69573da3-7744-5467-3207-89fd6efe7a47",
723
+ // account: 24321,
724
+ // currency: "XBt",
725
+ // transactType: "Withdrawal", // "AffiliatePayout", "Transfer", "Deposit", "RealisedPNL", ...
726
+ // amount: -1000000,
727
+ // fee: 300000,
728
+ // transactStatus: "Completed", // "Canceled", ...
729
+ // address: "1Ex4fkF4NhQaQdRWNoYpqiPbDBbq18Kdd9",
730
+ // tx: "3BMEX91ZhhKoWtsH9QRb5dNXnmnGpiEetA",
731
+ // text: "",
732
+ // transactTime: "2017-03-21T20:05:14.388Z",
733
+ // walletBalance: 0, // balance after
734
+ // marginBalance: null,
735
+ // timestamp: "2017-03-22T13:09:23.514Z"
736
+ // }
737
+ //
738
+ // ButMEX returns the unrealized pnl from the wallet history endpoint.
739
+ // The unrealized pnl transaction has an empty timestamp.
740
+ // It is not related to historical pnl it has status set to "Pending".
741
+ // Therefore it's not a part of the history at all.
742
+ // https://github.com/ccxt/ccxt/issues/6047
743
+ //
744
+ // {
745
+ // "transactID":"00000000-0000-0000-0000-000000000000",
746
+ // "account":121210,
747
+ // "currency":"XBt",
748
+ // "transactType":"UnrealisedPNL",
749
+ // "amount":-5508,
750
+ // "fee":0,
751
+ // "transactStatus":"Pending",
752
+ // "address":"XBTUSD",
753
+ // "tx":"",
754
+ // "text":"",
755
+ // "transactTime":null, # ←---------------------------- null
756
+ // "walletBalance":139198767,
757
+ // "marginBalance":139193259,
758
+ // "timestamp":null # ←---------------------------- null
759
+ // }
760
+ //
761
+ const id = this.safeString (item, 'transactID');
762
+ const account = this.safeString (item, 'account');
763
+ const referenceId = this.safeString (item, 'tx');
764
+ const referenceAccount = undefined;
765
+ const type = this.parseLedgerEntryType (this.safeString (item, 'transactType'));
766
+ const currencyId = this.safeString (item, 'currency');
767
+ const code = this.safeCurrencyCode (currencyId, currency);
768
+ let amount = this.safeNumber (item, 'amount');
769
+ if (amount !== undefined) {
770
+ amount = amount / 100000000;
771
+ }
772
+ let timestamp = this.parse8601 (this.safeString (item, 'transactTime'));
773
+ if (timestamp === undefined) {
774
+ // https://github.com/ccxt/ccxt/issues/6047
775
+ // set the timestamp to zero, 1970 Jan 1 00:00:00
776
+ // for unrealized pnl and other transactions without a timestamp
777
+ timestamp = 0; // see comments above
778
+ }
779
+ let feeCost = this.safeNumber (item, 'fee', 0);
780
+ if (feeCost !== undefined) {
781
+ feeCost = feeCost / 100000000;
782
+ }
783
+ const fee = {
784
+ 'cost': feeCost,
785
+ 'currency': code,
786
+ };
787
+ let after = this.safeNumber (item, 'walletBalance');
788
+ if (after !== undefined) {
789
+ after = after / 100000000;
790
+ }
791
+ const before = this.sum (after, -amount);
792
+ let direction = undefined;
793
+ if (amount < 0) {
794
+ direction = 'out';
795
+ amount = Math.abs (amount);
796
+ } else {
797
+ direction = 'in';
798
+ }
799
+ const status = this.parseTransactionStatus (this.safeString (item, 'transactStatus'));
800
+ return {
801
+ 'id': id,
802
+ 'info': item,
803
+ 'timestamp': timestamp,
804
+ 'datetime': this.iso8601 (timestamp),
805
+ 'direction': direction,
806
+ 'account': account,
807
+ 'referenceId': referenceId,
808
+ 'referenceAccount': referenceAccount,
809
+ 'type': type,
810
+ 'currency': code,
811
+ 'amount': amount,
812
+ 'before': before,
813
+ 'after': after,
814
+ 'status': status,
815
+ 'fee': fee,
816
+ };
817
+ }
818
+
819
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
820
+ await this.loadMarkets ();
821
+ let currency = undefined;
822
+ if (code !== undefined) {
823
+ currency = this.currency (code);
824
+ }
825
+ const request = {
826
+ // 'start': 123,
827
+ };
828
+ //
829
+ // if (since !== undefined) {
830
+ // // date-based pagination not supported
831
+ // }
832
+ //
833
+ if (limit !== undefined) {
834
+ request['count'] = limit;
835
+ }
836
+ const response = await this.privateGetUserWalletHistory (this.extend (request, params));
837
+ //
838
+ // [
839
+ // {
840
+ // transactID: "69573da3-7744-5467-3207-89fd6efe7a47",
841
+ // account: 24321,
842
+ // currency: "XBt",
843
+ // transactType: "Withdrawal", // "AffiliatePayout", "Transfer", "Deposit", "RealisedPNL", ...
844
+ // amount: -1000000,
845
+ // fee: 300000,
846
+ // transactStatus: "Completed", // "Canceled", ...
847
+ // address: "1Ex4fkF4NhQaQdRWNoYpqiPbDBbq18Kdd9",
848
+ // tx: "3BMEX91ZhhKoWtsH9QRb5dNXnmnGpiEetA",
849
+ // text: "",
850
+ // transactTime: "2017-03-21T20:05:14.388Z",
851
+ // walletBalance: 0, // balance after
852
+ // marginBalance: null,
853
+ // timestamp: "2017-03-22T13:09:23.514Z"
854
+ // }
855
+ // ]
856
+ //
857
+ return this.parseLedger (response, currency, since, limit);
858
+ }
859
+
860
+ async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
861
+ await this.loadMarkets ();
862
+ const request = {
863
+ // 'start': 123,
864
+ };
865
+ //
866
+ // if (since !== undefined) {
867
+ // // date-based pagination not supported
868
+ // }
869
+ //
870
+ if (limit !== undefined) {
871
+ request['count'] = limit;
872
+ }
873
+ const response = await this.privateGetUserWalletHistory (this.extend (request, params));
874
+ const transactions = this.filterByArray (response, 'transactType', [ 'Withdrawal', 'Deposit' ], false);
875
+ let currency = undefined;
876
+ if (code !== undefined) {
877
+ currency = this.currency (code);
878
+ }
879
+ return this.parseTransactions (transactions, currency, since, limit);
880
+ }
881
+
882
+ parseTransactionStatus (status) {
883
+ const statuses = {
884
+ 'Canceled': 'canceled',
885
+ 'Completed': 'ok',
886
+ 'Pending': 'pending',
887
+ };
888
+ return this.safeString (statuses, status, status);
889
+ }
890
+
891
+ parseTransaction (transaction, currency = undefined) {
892
+ //
893
+ // {
894
+ // 'transactID': 'ffe699c2-95ee-4c13-91f9-0faf41daec25',
895
+ // 'account': 123456,
896
+ // 'currency': 'XBt',
897
+ // 'transactType': 'Withdrawal',
898
+ // 'amount': -100100000,
899
+ // 'fee': 100000,
900
+ // 'transactStatus': 'Completed',
901
+ // 'address': '385cR5DM96n1HvBDMzLHPYcw89fZAXULJP',
902
+ // 'tx': '3BMEXabcdefghijklmnopqrstuvwxyz123',
903
+ // 'text': '',
904
+ // 'transactTime': '2019-01-02T01:00:00.000Z',
905
+ // 'walletBalance': 99900000,
906
+ // 'marginBalance': None,
907
+ // 'timestamp': '2019-01-02T13:00:00.000Z'
908
+ // }
909
+ //
910
+ const id = this.safeString (transaction, 'transactID');
911
+ // For deposits, transactTime == timestamp
912
+ // For withdrawals, transactTime is submission, timestamp is processed
913
+ const transactTime = this.parse8601 (this.safeString (transaction, 'transactTime'));
914
+ const timestamp = this.parse8601 (this.safeString (transaction, 'timestamp'));
915
+ const type = this.safeStringLower (transaction, 'transactType');
916
+ // Deposits have no from address or to address, withdrawals have both
917
+ let address = undefined;
918
+ let addressFrom = undefined;
919
+ let addressTo = undefined;
920
+ if (type === 'withdrawal') {
921
+ address = this.safeString (transaction, 'address');
922
+ addressFrom = this.safeString (transaction, 'tx');
923
+ addressTo = address;
924
+ }
925
+ let amountString = this.safeString (transaction, 'amount');
926
+ amountString = Precise.stringDiv (Precise.stringAbs (amountString), '1e8');
927
+ let feeCostString = this.safeString (transaction, 'fee');
928
+ feeCostString = Precise.stringDiv (feeCostString, '1e8');
929
+ const fee = {
930
+ 'cost': this.parseNumber (feeCostString),
931
+ 'currency': 'BTC',
932
+ };
933
+ let status = this.safeString (transaction, 'transactStatus');
934
+ if (status !== undefined) {
935
+ status = this.parseTransactionStatus (status);
936
+ }
937
+ return {
938
+ 'info': transaction,
939
+ 'id': id,
940
+ 'txid': undefined,
941
+ 'timestamp': transactTime,
942
+ 'datetime': this.iso8601 (transactTime),
943
+ 'network': undefined,
944
+ 'addressFrom': addressFrom,
945
+ 'address': address,
946
+ 'addressTo': addressTo,
947
+ 'tagFrom': undefined,
948
+ 'tag': undefined,
949
+ 'tagTo': undefined,
950
+ 'type': type,
951
+ 'amount': this.parseNumber (amountString),
952
+ // BTC is the only currency on Bitmex
953
+ 'currency': 'BTC',
954
+ 'status': status,
955
+ 'updated': timestamp,
956
+ 'comment': undefined,
957
+ 'fee': fee,
958
+ };
959
+ }
960
+
961
+ async fetchTicker (symbol, params = {}) {
962
+ await this.loadMarkets ();
963
+ const market = this.market (symbol);
964
+ const tickers = await this.fetchTickers ([ market['symbol'] ], params);
965
+ const ticker = this.safeValue (tickers, market['symbol']);
966
+ if (ticker === undefined) {
967
+ throw new BadSymbol (this.id + ' fetchTicker() symbol ' + symbol + ' not found');
968
+ }
969
+ return ticker;
970
+ }
971
+
972
+ async fetchTickers (symbols = undefined, params = {}) {
973
+ await this.loadMarkets ();
974
+ const response = await this.publicGetInstrumentActiveAndIndices (params);
975
+ const result = {};
976
+ for (let i = 0; i < response.length; i++) {
977
+ const ticker = this.parseTicker (response[i]);
978
+ const symbol = this.safeString (ticker, 'symbol');
979
+ if (symbol !== undefined) {
980
+ result[symbol] = ticker;
981
+ }
982
+ }
983
+ const uniformSymbols = [];
984
+ if (symbols !== undefined) {
985
+ for (let i = 0; i < symbols.length; i++) {
986
+ const symbol = symbols[i];
987
+ const market = this.market (symbol);
988
+ uniformSymbols.push (market['symbol']);
989
+ }
990
+ }
991
+ return this.filterByArray (result, 'symbol', uniformSymbols);
992
+ }
993
+
994
+ parseTicker (ticker, market = undefined) {
995
+ //
996
+ // { symbol: "ETHH19",
997
+ // rootSymbol: "ETH",
998
+ // state: "Open",
999
+ // typ: "FFCCSX",
1000
+ // listing: "2018-12-17T04:00:00.000Z",
1001
+ // front: "2019-02-22T12:00:00.000Z",
1002
+ // expiry: "2019-03-29T12:00:00.000Z",
1003
+ // settle: "2019-03-29T12:00:00.000Z",
1004
+ // relistInterval: null,
1005
+ // inverseLeg: "",
1006
+ // sellLeg: "",
1007
+ // buyLeg: "",
1008
+ // optionStrikePcnt: null,
1009
+ // optionStrikeRound: null,
1010
+ // optionStrikePrice: null,
1011
+ // optionMultiplier: null,
1012
+ // positionCurrency: "ETH",
1013
+ // underlying: "ETH",
1014
+ // quoteCurrency: "XBT",
1015
+ // underlyingSymbol: "ETHXBT=",
1016
+ // reference: "BMEX",
1017
+ // referenceSymbol: ".BETHXBT30M",
1018
+ // calcInterval: null,
1019
+ // publishInterval: null,
1020
+ // publishTime: null,
1021
+ // maxOrderQty: 100000000,
1022
+ // maxPrice: 10,
1023
+ // lotSize: 1,
1024
+ // tickSize: 0.00001,
1025
+ // multiplier: 100000000,
1026
+ // settlCurrency: "XBt",
1027
+ // underlyingToPositionMultiplier: 1,
1028
+ // underlyingToSettleMultiplier: null,
1029
+ // quoteToSettleMultiplier: 100000000,
1030
+ // isQuanto: false,
1031
+ // isInverse: false,
1032
+ // initMargin: 0.02,
1033
+ // maintMargin: 0.01,
1034
+ // riskLimit: 5000000000,
1035
+ // riskStep: 5000000000,
1036
+ // limit: null,
1037
+ // capped: false,
1038
+ // taxed: true,
1039
+ // deleverage: true,
1040
+ // makerFee: -0.0005,
1041
+ // takerFee: 0.0025,
1042
+ // settlementFee: 0,
1043
+ // insuranceFee: 0,
1044
+ // fundingBaseSymbol: "",
1045
+ // fundingQuoteSymbol: "",
1046
+ // fundingPremiumSymbol: "",
1047
+ // fundingTimestamp: null,
1048
+ // fundingInterval: null,
1049
+ // fundingRate: null,
1050
+ // indicativeFundingRate: null,
1051
+ // rebalanceTimestamp: null,
1052
+ // rebalanceInterval: null,
1053
+ // openingTimestamp: "2019-02-13T08:00:00.000Z",
1054
+ // closingTimestamp: "2019-02-13T09:00:00.000Z",
1055
+ // sessionInterval: "2000-01-01T01:00:00.000Z",
1056
+ // prevClosePrice: 0.03347,
1057
+ // limitDownPrice: null,
1058
+ // limitUpPrice: null,
1059
+ // bankruptLimitDownPrice: null,
1060
+ // bankruptLimitUpPrice: null,
1061
+ // prevTotalVolume: 1386531,
1062
+ // totalVolume: 1387062,
1063
+ // volume: 531,
1064
+ // volume24h: 17118,
1065
+ // prevTotalTurnover: 4741294246000,
1066
+ // totalTurnover: 4743103466000,
1067
+ // turnover: 1809220000,
1068
+ // turnover24h: 57919845000,
1069
+ // homeNotional24h: 17118,
1070
+ // foreignNotional24h: 579.19845,
1071
+ // prevPrice24h: 0.03349,
1072
+ // vwap: 0.03383564,
1073
+ // highPrice: 0.03458,
1074
+ // lowPrice: 0.03329,
1075
+ // lastPrice: 0.03406,
1076
+ // lastPriceProtected: 0.03406,
1077
+ // lastTickDirection: "ZeroMinusTick",
1078
+ // lastChangePcnt: 0.017,
1079
+ // bidPrice: 0.03406,
1080
+ // midPrice: 0.034065,
1081
+ // askPrice: 0.03407,
1082
+ // impactBidPrice: 0.03406,
1083
+ // impactMidPrice: 0.034065,
1084
+ // impactAskPrice: 0.03407,
1085
+ // hasLiquidity: true,
1086
+ // openInterest: 83679,
1087
+ // openValue: 285010674000,
1088
+ // fairMethod: "ImpactMidPrice",
1089
+ // fairBasisRate: 0,
1090
+ // fairBasis: 0,
1091
+ // fairPrice: 0.03406,
1092
+ // markMethod: "FairPrice",
1093
+ // markPrice: 0.03406,
1094
+ // indicativeTaxRate: 0,
1095
+ // indicativeSettlePrice: 0.03406,
1096
+ // optionUnderlyingPrice: null,
1097
+ // settledPrice: null,
1098
+ // timestamp: "2019-02-13T08:40:30.000Z",
1099
+ // }
1100
+ //
1101
+ const marketId = this.safeString (ticker, 'symbol');
1102
+ const symbol = this.safeSymbol (marketId, market);
1103
+ const timestamp = this.parse8601 (this.safeString (ticker, 'timestamp'));
1104
+ const open = this.safeString (ticker, 'prevPrice24h');
1105
+ const last = this.safeString (ticker, 'lastPrice');
1106
+ return this.safeTicker ({
1107
+ 'symbol': symbol,
1108
+ 'timestamp': timestamp,
1109
+ 'datetime': this.iso8601 (timestamp),
1110
+ 'high': this.safeString (ticker, 'highPrice'),
1111
+ 'low': this.safeString (ticker, 'lowPrice'),
1112
+ 'bid': this.safeString (ticker, 'bidPrice'),
1113
+ 'bidVolume': undefined,
1114
+ 'ask': this.safeString (ticker, 'askPrice'),
1115
+ 'askVolume': undefined,
1116
+ 'vwap': this.safeString (ticker, 'vwap'),
1117
+ 'open': open,
1118
+ 'close': last,
1119
+ 'last': last,
1120
+ 'previousClose': undefined,
1121
+ 'change': undefined,
1122
+ 'percentage': undefined,
1123
+ 'average': undefined,
1124
+ 'baseVolume': this.safeString (ticker, 'homeNotional24h'),
1125
+ 'quoteVolume': this.safeString (ticker, 'foreignNotional24h'),
1126
+ 'info': ticker,
1127
+ }, market, false);
1128
+ }
1129
+
1130
+ parseOHLCV (ohlcv, market = undefined) {
1131
+ //
1132
+ // {
1133
+ // "timestamp":"2015-09-25T13:38:00.000Z",
1134
+ // "symbol":"XBTUSD",
1135
+ // "open":237.45,
1136
+ // "high":237.45,
1137
+ // "low":237.45,
1138
+ // "close":237.45,
1139
+ // "trades":0,
1140
+ // "volume":0,
1141
+ // "vwap":null,
1142
+ // "lastSize":null,
1143
+ // "turnover":0,
1144
+ // "homeNotional":0,
1145
+ // "foreignNotional":0
1146
+ // }
1147
+ //
1148
+ return [
1149
+ this.parse8601 (this.safeString (ohlcv, 'timestamp')),
1150
+ this.safeNumber (ohlcv, 'open'),
1151
+ this.safeNumber (ohlcv, 'high'),
1152
+ this.safeNumber (ohlcv, 'low'),
1153
+ this.safeNumber (ohlcv, 'close'),
1154
+ this.safeNumber (ohlcv, 'volume'),
1155
+ ];
1156
+ }
1157
+
1158
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1159
+ await this.loadMarkets ();
1160
+ // send JSON key/value pairs, such as {"key": "value"}
1161
+ // filter by individual fields and do advanced queries on timestamps
1162
+ // let filter = { 'key': 'value' };
1163
+ // send a bare series (e.g. XBU) to nearest expiring contract in that series
1164
+ // you can also send a timeframe, e.g. XBU:monthly
1165
+ // timeframes: daily, weekly, monthly, quarterly, and biquarterly
1166
+ const market = this.market (symbol);
1167
+ const request = {
1168
+ 'symbol': market['id'],
1169
+ 'binSize': this.timeframes[timeframe],
1170
+ 'partial': true, // true == include yet-incomplete current bins
1171
+ // 'filter': filter, // filter by individual fields and do advanced queries
1172
+ // 'columns': [], // will return all columns if omitted
1173
+ // 'start': 0, // starting point for results (wtf?)
1174
+ // 'reverse': false, // true == newest first
1175
+ // 'endTime': '', // ending date filter for results
1176
+ };
1177
+ if (limit !== undefined) {
1178
+ request['count'] = limit; // default 100, max 500
1179
+ }
1180
+ const duration = this.parseTimeframe (timeframe) * 1000;
1181
+ const fetchOHLCVOpenTimestamp = this.safeValue (this.options, 'fetchOHLCVOpenTimestamp', true);
1182
+ // if since is not set, they will return candles starting from 2017-01-01
1183
+ if (since !== undefined) {
1184
+ let timestamp = since;
1185
+ if (fetchOHLCVOpenTimestamp) {
1186
+ timestamp = this.sum (timestamp, duration);
1187
+ }
1188
+ const ymdhms = this.ymdhms (timestamp);
1189
+ request['startTime'] = ymdhms; // starting date filter for results
1190
+ } else {
1191
+ request['reverse'] = true;
1192
+ }
1193
+ const response = await this.publicGetTradeBucketed (this.extend (request, params));
1194
+ //
1195
+ // [
1196
+ // {"timestamp":"2015-09-25T13:38:00.000Z","symbol":"XBTUSD","open":237.45,"high":237.45,"low":237.45,"close":237.45,"trades":0,"volume":0,"vwap":null,"lastSize":null,"turnover":0,"homeNotional":0,"foreignNotional":0},
1197
+ // {"timestamp":"2015-09-25T13:39:00.000Z","symbol":"XBTUSD","open":237.45,"high":237.45,"low":237.45,"close":237.45,"trades":0,"volume":0,"vwap":null,"lastSize":null,"turnover":0,"homeNotional":0,"foreignNotional":0},
1198
+ // {"timestamp":"2015-09-25T13:40:00.000Z","symbol":"XBTUSD","open":237.45,"high":237.45,"low":237.45,"close":237.45,"trades":0,"volume":0,"vwap":null,"lastSize":null,"turnover":0,"homeNotional":0,"foreignNotional":0}
1199
+ // ]
1200
+ //
1201
+ const result = this.parseOHLCVs (response, market, timeframe, since, limit);
1202
+ if (fetchOHLCVOpenTimestamp) {
1203
+ // bitmex returns the candle's close timestamp - https://github.com/ccxt/ccxt/issues/4446
1204
+ // we can emulate the open timestamp by shifting all the timestamps one place
1205
+ // so the previous close becomes the current open, and we drop the first candle
1206
+ for (let i = 0; i < result.length; i++) {
1207
+ result[i][0] = result[i][0] - duration;
1208
+ }
1209
+ }
1210
+ return result;
1211
+ }
1212
+
1213
+ parseTrade (trade, market = undefined) {
1214
+ //
1215
+ // fetchTrades (public)
1216
+ //
1217
+ // {
1218
+ // timestamp: '2018-08-28T00:00:02.735Z',
1219
+ // symbol: 'XBTUSD',
1220
+ // side: 'Buy',
1221
+ // size: 2000,
1222
+ // price: 6906.5,
1223
+ // tickDirection: 'PlusTick',
1224
+ // trdMatchID: 'b9a42432-0a46-6a2f-5ecc-c32e9ca4baf8',
1225
+ // grossValue: 28958000,
1226
+ // homeNotional: 0.28958,
1227
+ // foreignNotional: 2000
1228
+ // }
1229
+ //
1230
+ // fetchMyTrades (private)
1231
+ //
1232
+ // {
1233
+ // "execID": "string",
1234
+ // "orderID": "string",
1235
+ // "clOrdID": "string",
1236
+ // "clOrdLinkID": "string",
1237
+ // "account": 0,
1238
+ // "symbol": "string",
1239
+ // "side": "string",
1240
+ // "lastQty": 0,
1241
+ // "lastPx": 0,
1242
+ // "underlyingLastPx": 0,
1243
+ // "lastMkt": "string",
1244
+ // "lastLiquidityInd": "string",
1245
+ // "simpleOrderQty": 0,
1246
+ // "orderQty": 0,
1247
+ // "price": 0,
1248
+ // "displayQty": 0,
1249
+ // "stopPx": 0,
1250
+ // "pegOffsetValue": 0,
1251
+ // "pegPriceType": "string",
1252
+ // "currency": "string",
1253
+ // "settlCurrency": "string",
1254
+ // "execType": "string",
1255
+ // "ordType": "string",
1256
+ // "timeInForce": "string",
1257
+ // "execInst": "string",
1258
+ // "contingencyType": "string",
1259
+ // "exDestination": "string",
1260
+ // "ordStatus": "string",
1261
+ // "triggered": "string",
1262
+ // "workingIndicator": true,
1263
+ // "ordRejReason": "string",
1264
+ // "simpleLeavesQty": 0,
1265
+ // "leavesQty": 0,
1266
+ // "simpleCumQty": 0,
1267
+ // "cumQty": 0,
1268
+ // "avgPx": 0,
1269
+ // "commission": 0,
1270
+ // "tradePublishIndicator": "string",
1271
+ // "multiLegReportingType": "string",
1272
+ // "text": "string",
1273
+ // "trdMatchID": "string",
1274
+ // "execCost": 0,
1275
+ // "execComm": 0,
1276
+ // "homeNotional": 0,
1277
+ // "foreignNotional": 0,
1278
+ // "transactTime": "2019-03-05T12:47:02.762Z",
1279
+ // "timestamp": "2019-03-05T12:47:02.762Z"
1280
+ // }
1281
+ //
1282
+ const timestamp = this.parse8601 (this.safeString (trade, 'timestamp'));
1283
+ const priceString = this.safeString2 (trade, 'avgPx', 'price');
1284
+ const amountString = this.safeString2 (trade, 'size', 'lastQty');
1285
+ const execCost = this.safeString (trade, 'execCost');
1286
+ const costString = Precise.stringDiv (Precise.stringAbs (execCost), '1e8');
1287
+ const id = this.safeString (trade, 'trdMatchID');
1288
+ const order = this.safeString (trade, 'orderID');
1289
+ const side = this.safeStringLower (trade, 'side');
1290
+ // price * amount doesn't work for all symbols (e.g. XBT, ETH)
1291
+ let fee = undefined;
1292
+ const feeCostString = Precise.stringDiv (this.safeString (trade, 'execComm'), '1e8');
1293
+ if (feeCostString !== undefined) {
1294
+ const currencyId = this.safeString (trade, 'settlCurrency');
1295
+ const feeCurrencyCode = this.safeCurrencyCode (currencyId);
1296
+ const feeRateString = this.safeString (trade, 'commission');
1297
+ fee = {
1298
+ 'cost': feeCostString,
1299
+ 'currency': feeCurrencyCode,
1300
+ 'rate': feeRateString,
1301
+ };
1302
+ }
1303
+ // Trade or Funding
1304
+ const execType = this.safeString (trade, 'execType');
1305
+ let takerOrMaker = undefined;
1306
+ if (feeCostString !== undefined && execType === 'Trade') {
1307
+ takerOrMaker = Precise.stringLt (feeCostString, '0') ? 'maker' : 'taker';
1308
+ }
1309
+ const marketId = this.safeString (trade, 'symbol');
1310
+ const symbol = this.safeSymbol (marketId, market);
1311
+ const type = this.safeStringLower (trade, 'ordType');
1312
+ return this.safeTrade ({
1313
+ 'info': trade,
1314
+ 'timestamp': timestamp,
1315
+ 'datetime': this.iso8601 (timestamp),
1316
+ 'symbol': symbol,
1317
+ 'id': id,
1318
+ 'order': order,
1319
+ 'type': type,
1320
+ 'takerOrMaker': takerOrMaker,
1321
+ 'side': side,
1322
+ 'price': priceString,
1323
+ 'cost': costString,
1324
+ 'amount': amountString,
1325
+ 'fee': fee,
1326
+ }, market);
1327
+ }
1328
+
1329
+ parseOrderStatus (status) {
1330
+ const statuses = {
1331
+ 'New': 'open',
1332
+ 'PartiallyFilled': 'open',
1333
+ 'Filled': 'closed',
1334
+ 'DoneForDay': 'open',
1335
+ 'Canceled': 'canceled',
1336
+ 'PendingCancel': 'open',
1337
+ 'PendingNew': 'open',
1338
+ 'Rejected': 'rejected',
1339
+ 'Expired': 'expired',
1340
+ 'Stopped': 'open',
1341
+ 'Untriggered': 'open',
1342
+ 'Triggered': 'open',
1343
+ };
1344
+ return this.safeString (statuses, status, status);
1345
+ }
1346
+
1347
+ parseTimeInForce (timeInForce) {
1348
+ const timeInForces = {
1349
+ 'Day': 'Day',
1350
+ 'GoodTillCancel': 'GTC',
1351
+ 'ImmediateOrCancel': 'IOC',
1352
+ 'FillOrKill': 'FOK',
1353
+ };
1354
+ return this.safeString (timeInForces, timeInForce, timeInForce);
1355
+ }
1356
+
1357
+ parseOrder (order, market = undefined) {
1358
+ //
1359
+ // {
1360
+ // "orderID":"56222c7a-9956-413a-82cf-99f4812c214b",
1361
+ // "clOrdID":"",
1362
+ // "clOrdLinkID":"",
1363
+ // "account":1455728,
1364
+ // "symbol":"XBTUSD",
1365
+ // "side":"Sell",
1366
+ // "simpleOrderQty":null,
1367
+ // "orderQty":1,
1368
+ // "price":40000,
1369
+ // "displayQty":null,
1370
+ // "stopPx":null,
1371
+ // "pegOffsetValue":null,
1372
+ // "pegPriceType":"",
1373
+ // "currency":"USD",
1374
+ // "settlCurrency":"XBt",
1375
+ // "ordType":"Limit",
1376
+ // "timeInForce":"GoodTillCancel",
1377
+ // "execInst":"",
1378
+ // "contingencyType":"",
1379
+ // "exDestination":"XBME",
1380
+ // "ordStatus":"New",
1381
+ // "triggered":"",
1382
+ // "workingIndicator":true,
1383
+ // "ordRejReason":"",
1384
+ // "simpleLeavesQty":null,
1385
+ // "leavesQty":1,
1386
+ // "simpleCumQty":null,
1387
+ // "cumQty":0,
1388
+ // "avgPx":null,
1389
+ // "multiLegReportingType":"SingleSecurity",
1390
+ // "text":"Submitted via API.",
1391
+ // "transactTime":"2021-01-02T21:38:49.246Z",
1392
+ // "timestamp":"2021-01-02T21:38:49.246Z"
1393
+ // }
1394
+ //
1395
+ const status = this.parseOrderStatus (this.safeString (order, 'ordStatus'));
1396
+ const marketId = this.safeString (order, 'symbol');
1397
+ const symbol = this.safeSymbol (marketId, market);
1398
+ const timestamp = this.parse8601 (this.safeString (order, 'timestamp'));
1399
+ const lastTradeTimestamp = this.parse8601 (this.safeString (order, 'transactTime'));
1400
+ const price = this.safeString (order, 'price');
1401
+ const amount = this.safeString (order, 'orderQty');
1402
+ const filled = this.safeString (order, 'cumQty', 0.0);
1403
+ const average = this.safeString (order, 'avgPx');
1404
+ const id = this.safeString (order, 'orderID');
1405
+ const type = this.safeStringLower (order, 'ordType');
1406
+ const side = this.safeStringLower (order, 'side');
1407
+ const clientOrderId = this.safeString (order, 'clOrdID');
1408
+ const timeInForce = this.parseTimeInForce (this.safeString (order, 'timeInForce'));
1409
+ const stopPrice = this.safeNumber (order, 'stopPx');
1410
+ const execInst = this.safeString (order, 'execInst');
1411
+ const postOnly = (execInst === 'ParticipateDoNotInitiate');
1412
+ return this.safeOrder ({
1413
+ 'info': order,
1414
+ 'id': id,
1415
+ 'clientOrderId': clientOrderId,
1416
+ 'timestamp': timestamp,
1417
+ 'datetime': this.iso8601 (timestamp),
1418
+ 'lastTradeTimestamp': lastTradeTimestamp,
1419
+ 'symbol': symbol,
1420
+ 'type': type,
1421
+ 'timeInForce': timeInForce,
1422
+ 'postOnly': postOnly,
1423
+ 'side': side,
1424
+ 'price': price,
1425
+ 'stopPrice': stopPrice,
1426
+ 'amount': amount,
1427
+ 'cost': undefined,
1428
+ 'average': average,
1429
+ 'filled': filled,
1430
+ 'remaining': undefined,
1431
+ 'status': status,
1432
+ 'fee': undefined,
1433
+ 'trades': undefined,
1434
+ }, market);
1435
+ }
1436
+
1437
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
1438
+ await this.loadMarkets ();
1439
+ const market = this.market (symbol);
1440
+ const request = {
1441
+ 'symbol': market['id'],
1442
+ };
1443
+ if (since !== undefined) {
1444
+ request['startTime'] = this.iso8601 (since);
1445
+ } else {
1446
+ // by default reverse=false, i.e. trades are fetched since the time of market inception (year 2015 for XBTUSD)
1447
+ request['reverse'] = true;
1448
+ }
1449
+ if (limit !== undefined) {
1450
+ request['count'] = limit;
1451
+ }
1452
+ const response = await this.publicGetTrade (this.extend (request, params));
1453
+ //
1454
+ // [
1455
+ // {
1456
+ // timestamp: '2018-08-28T00:00:02.735Z',
1457
+ // symbol: 'XBTUSD',
1458
+ // side: 'Buy',
1459
+ // size: 2000,
1460
+ // price: 6906.5,
1461
+ // tickDirection: 'PlusTick',
1462
+ // trdMatchID: 'b9a42432-0a46-6a2f-5ecc-c32e9ca4baf8',
1463
+ // grossValue: 28958000,
1464
+ // homeNotional: 0.28958,
1465
+ // foreignNotional: 2000
1466
+ // },
1467
+ // {
1468
+ // timestamp: '2018-08-28T00:00:03.778Z',
1469
+ // symbol: 'XBTUSD',
1470
+ // side: 'Sell',
1471
+ // size: 1000,
1472
+ // price: 6906,
1473
+ // tickDirection: 'MinusTick',
1474
+ // trdMatchID: '0d4f1682-5270-a800-569b-4a0eb92db97c',
1475
+ // grossValue: 14480000,
1476
+ // homeNotional: 0.1448,
1477
+ // foreignNotional: 1000
1478
+ // },
1479
+ // ]
1480
+ //
1481
+ return this.parseTrades (response, market, since, limit);
1482
+ }
1483
+
1484
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1485
+ await this.loadMarkets ();
1486
+ const market = this.market (symbol);
1487
+ const orderType = this.capitalize (type);
1488
+ const request = {
1489
+ 'symbol': market['id'],
1490
+ 'side': this.capitalize (side),
1491
+ 'orderQty': parseFloat (this.amountToPrecision (symbol, amount)),
1492
+ 'ordType': orderType,
1493
+ };
1494
+ if ((orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched')) {
1495
+ const stopPrice = this.safeNumber2 (params, 'stopPx', 'stopPrice');
1496
+ if (stopPrice === undefined) {
1497
+ throw new ArgumentsRequired (this.id + ' createOrder() requires a stopPx or stopPrice parameter for the ' + orderType + ' order type');
1498
+ } else {
1499
+ request['stopPx'] = parseFloat (this.priceToPrecision (symbol, stopPrice));
1500
+ params = this.omit (params, [ 'stopPx', 'stopPrice' ]);
1501
+ }
1502
+ }
1503
+ if ((orderType === 'Limit') || (orderType === 'StopLimit') || (orderType === 'LimitIfTouched')) {
1504
+ request['price'] = parseFloat (this.priceToPrecision (symbol, price));
1505
+ }
1506
+ const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
1507
+ if (clientOrderId !== undefined) {
1508
+ request['clOrdID'] = clientOrderId;
1509
+ params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]);
1510
+ }
1511
+ const response = await this.privatePostOrder (this.extend (request, params));
1512
+ return this.parseOrder (response, market);
1513
+ }
1514
+
1515
+ async editOrder (id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1516
+ await this.loadMarkets ();
1517
+ const request = {};
1518
+ const origClOrdID = this.safeString2 (params, 'origClOrdID', 'clientOrderId');
1519
+ if (origClOrdID !== undefined) {
1520
+ request['origClOrdID'] = origClOrdID;
1521
+ const clientOrderId = this.safeString (params, 'clOrdID', 'clientOrderId');
1522
+ if (clientOrderId !== undefined) {
1523
+ request['clOrdID'] = clientOrderId;
1524
+ }
1525
+ params = this.omit (params, [ 'origClOrdID', 'clOrdID', 'clientOrderId' ]);
1526
+ } else {
1527
+ request['orderID'] = id;
1528
+ }
1529
+ if (amount !== undefined) {
1530
+ request['orderQty'] = amount;
1531
+ }
1532
+ if (price !== undefined) {
1533
+ request['price'] = price;
1534
+ }
1535
+ const response = await this.privatePutOrder (this.extend (request, params));
1536
+ return this.parseOrder (response);
1537
+ }
1538
+
1539
+ async cancelOrder (id, symbol = undefined, params = {}) {
1540
+ await this.loadMarkets ();
1541
+ // https://github.com/ccxt/ccxt/issues/6507
1542
+ const clientOrderId = this.safeValue2 (params, 'clOrdID', 'clientOrderId');
1543
+ const request = {};
1544
+ if (clientOrderId === undefined) {
1545
+ request['orderID'] = id;
1546
+ } else {
1547
+ request['clOrdID'] = clientOrderId;
1548
+ params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]);
1549
+ }
1550
+ const response = await this.privateDeleteOrder (this.extend (request, params));
1551
+ const order = this.safeValue (response, 0, {});
1552
+ const error = this.safeString (order, 'error');
1553
+ if (error !== undefined) {
1554
+ if (error.indexOf ('Unable to cancel order due to existing state') >= 0) {
1555
+ throw new OrderNotFound (this.id + ' cancelOrder() failed: ' + error);
1556
+ }
1557
+ }
1558
+ return this.parseOrder (order);
1559
+ }
1560
+
1561
+ async cancelOrders (ids, symbol = undefined, params = {}) {
1562
+ return await this.cancelOrder (ids, symbol, params);
1563
+ }
1564
+
1565
+ async cancelAllOrders (symbol = undefined, params = {}) {
1566
+ await this.loadMarkets ();
1567
+ const request = {};
1568
+ let market = undefined;
1569
+ if (symbol !== undefined) {
1570
+ market = this.market (symbol);
1571
+ request['symbol'] = market['id'];
1572
+ }
1573
+ const response = await this.privateDeleteOrderAll (this.extend (request, params));
1574
+ //
1575
+ // [
1576
+ // {
1577
+ // "orderID": "string",
1578
+ // "clOrdID": "string",
1579
+ // "clOrdLinkID": "string",
1580
+ // "account": 0,
1581
+ // "symbol": "string",
1582
+ // "side": "string",
1583
+ // "simpleOrderQty": 0,
1584
+ // "orderQty": 0,
1585
+ // "price": 0,
1586
+ // "displayQty": 0,
1587
+ // "stopPx": 0,
1588
+ // "pegOffsetValue": 0,
1589
+ // "pegPriceType": "string",
1590
+ // "currency": "string",
1591
+ // "settlCurrency": "string",
1592
+ // "ordType": "string",
1593
+ // "timeInForce": "string",
1594
+ // "execInst": "string",
1595
+ // "contingencyType": "string",
1596
+ // "exDestination": "string",
1597
+ // "ordStatus": "string",
1598
+ // "triggered": "string",
1599
+ // "workingIndicator": true,
1600
+ // "ordRejReason": "string",
1601
+ // "simpleLeavesQty": 0,
1602
+ // "leavesQty": 0,
1603
+ // "simpleCumQty": 0,
1604
+ // "cumQty": 0,
1605
+ // "avgPx": 0,
1606
+ // "multiLegReportingType": "string",
1607
+ // "text": "string",
1608
+ // "transactTime": "2020-06-01T09:36:35.290Z",
1609
+ // "timestamp": "2020-06-01T09:36:35.290Z"
1610
+ // }
1611
+ // ]
1612
+ //
1613
+ return this.parseOrders (response, market);
1614
+ }
1615
+
1616
+ async fetchPositions (symbols = undefined, params = {}) {
1617
+ await this.loadMarkets ();
1618
+ const response = await this.privateGetPosition (params);
1619
+ // [
1620
+ // {
1621
+ // "account": 0,
1622
+ // "symbol": "string",
1623
+ // "currency": "string",
1624
+ // "underlying": "string",
1625
+ // "quoteCurrency": "string",
1626
+ // "commission": 0,
1627
+ // "initMarginReq": 0,
1628
+ // "maintMarginReq": 0,
1629
+ // "riskLimit": 0,
1630
+ // "leverage": 0,
1631
+ // "crossMargin": true,
1632
+ // "deleveragePercentile": 0,
1633
+ // "rebalancedPnl": 0,
1634
+ // "prevRealisedPnl": 0,
1635
+ // "prevUnrealisedPnl": 0,
1636
+ // "prevClosePrice": 0,
1637
+ // "openingTimestamp": "2020-11-09T06:53:59.892Z",
1638
+ // "openingQty": 0,
1639
+ // "openingCost": 0,
1640
+ // "openingComm": 0,
1641
+ // "openOrderBuyQty": 0,
1642
+ // "openOrderBuyCost": 0,
1643
+ // "openOrderBuyPremium": 0,
1644
+ // "openOrderSellQty": 0,
1645
+ // "openOrderSellCost": 0,
1646
+ // "openOrderSellPremium": 0,
1647
+ // "execBuyQty": 0,
1648
+ // "execBuyCost": 0,
1649
+ // "execSellQty": 0,
1650
+ // "execSellCost": 0,
1651
+ // "execQty": 0,
1652
+ // "execCost": 0,
1653
+ // "execComm": 0,
1654
+ // "currentTimestamp": "2020-11-09T06:53:59.893Z",
1655
+ // "currentQty": 0,
1656
+ // "currentCost": 0,
1657
+ // "currentComm": 0,
1658
+ // "realisedCost": 0,
1659
+ // "unrealisedCost": 0,
1660
+ // "grossOpenCost": 0,
1661
+ // "grossOpenPremium": 0,
1662
+ // "grossExecCost": 0,
1663
+ // "isOpen": true,
1664
+ // "markPrice": 0,
1665
+ // "markValue": 0,
1666
+ // "riskValue": 0,
1667
+ // "homeNotional": 0,
1668
+ // "foreignNotional": 0,
1669
+ // "posState": "string",
1670
+ // "posCost": 0,
1671
+ // "posCost2": 0,
1672
+ // "posCross": 0,
1673
+ // "posInit": 0,
1674
+ // "posComm": 0,
1675
+ // "posLoss": 0,
1676
+ // "posMargin": 0,
1677
+ // "posMaint": 0,
1678
+ // "posAllowance": 0,
1679
+ // "taxableMargin": 0,
1680
+ // "initMargin": 0,
1681
+ // "maintMargin": 0,
1682
+ // "sessionMargin": 0,
1683
+ // "targetExcessMargin": 0,
1684
+ // "varMargin": 0,
1685
+ // "realisedGrossPnl": 0,
1686
+ // "realisedTax": 0,
1687
+ // "realisedPnl": 0,
1688
+ // "unrealisedGrossPnl": 0,
1689
+ // "longBankrupt": 0,
1690
+ // "shortBankrupt": 0,
1691
+ // "taxBase": 0,
1692
+ // "indicativeTaxRate": 0,
1693
+ // "indicativeTax": 0,
1694
+ // "unrealisedTax": 0,
1695
+ // "unrealisedPnl": 0,
1696
+ // "unrealisedPnlPcnt": 0,
1697
+ // "unrealisedRoePcnt": 0,
1698
+ // "simpleQty": 0,
1699
+ // "simpleCost": 0,
1700
+ // "simpleValue": 0,
1701
+ // "simplePnl": 0,
1702
+ // "simplePnlPcnt": 0,
1703
+ // "avgCostPrice": 0,
1704
+ // "avgEntryPrice": 0,
1705
+ // "breakEvenPrice": 0,
1706
+ // "marginCallPrice": 0,
1707
+ // "liquidationPrice": 0,
1708
+ // "bankruptPrice": 0,
1709
+ // "timestamp": "2020-11-09T06:53:59.894Z",
1710
+ // "lastPrice": 0,
1711
+ // "lastValue": 0
1712
+ // }
1713
+ // ]
1714
+ //
1715
+ // todo unify parsePosition/parsePositions
1716
+ return response;
1717
+ }
1718
+
1719
+ isFiat (currency) {
1720
+ if (currency === 'EUR') {
1721
+ return true;
1722
+ }
1723
+ if (currency === 'PLN') {
1724
+ return true;
1725
+ }
1726
+ return false;
1727
+ }
1728
+
1729
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
1730
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
1731
+ this.checkAddress (address);
1732
+ await this.loadMarkets ();
1733
+ // let currency = this.currency (code);
1734
+ if (code !== 'BTC') {
1735
+ throw new ExchangeError (this.id + ' supoprts BTC withdrawals only, other currencies coming soon...');
1736
+ }
1737
+ const currency = this.currency (code);
1738
+ const request = {
1739
+ 'currency': 'XBt', // temporarily
1740
+ 'amount': amount,
1741
+ 'address': address,
1742
+ // 'otpToken': '123456', // requires if two-factor auth (OTP) is enabled
1743
+ // 'fee': 0.001, // bitcoin network fee
1744
+ };
1745
+ const response = await this.privatePostUserRequestWithdrawal (this.extend (request, params));
1746
+ return this.parseTransaction (response, currency);
1747
+ }
1748
+
1749
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
1750
+ if (response === undefined) {
1751
+ return;
1752
+ }
1753
+ if (code === 429) {
1754
+ throw new DDoSProtection (this.id + ' ' + body);
1755
+ }
1756
+ if (code >= 400) {
1757
+ const error = this.safeValue (response, 'error', {});
1758
+ const message = this.safeString (error, 'message');
1759
+ const feedback = this.id + ' ' + body;
1760
+ this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
1761
+ this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
1762
+ if (code === 400) {
1763
+ throw new BadRequest (feedback);
1764
+ }
1765
+ throw new ExchangeError (feedback); // unknown message
1766
+ }
1767
+ }
1768
+
1769
+ nonce () {
1770
+ return this.milliseconds ();
1771
+ }
1772
+
1773
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
1774
+ let query = '/api/' + this.version + '/' + path;
1775
+ if (method === 'GET') {
1776
+ if (Object.keys (params).length) {
1777
+ query += '?' + this.urlencode (params);
1778
+ }
1779
+ } else {
1780
+ const format = this.safeString (params, '_format');
1781
+ if (format !== undefined) {
1782
+ query += '?' + this.urlencode ({ '_format': format });
1783
+ params = this.omit (params, '_format');
1784
+ }
1785
+ }
1786
+ const url = this.urls['api'][api] + query;
1787
+ if (api === 'private') {
1788
+ this.checkRequiredCredentials ();
1789
+ let auth = method + query;
1790
+ let expires = this.safeInteger (this.options, 'api-expires');
1791
+ headers = {
1792
+ 'Content-Type': 'application/json',
1793
+ 'api-key': this.apiKey,
1794
+ };
1795
+ expires = this.sum (this.seconds (), expires);
1796
+ expires = expires.toString ();
1797
+ auth += expires;
1798
+ headers['api-expires'] = expires;
1799
+ if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
1800
+ if (Object.keys (params).length) {
1801
+ body = this.json (params);
1802
+ auth += body;
1803
+ }
1804
+ }
1805
+ headers['api-signature'] = this.hmac (this.encode (auth), this.encode (this.secret));
1806
+ }
1807
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
1808
+ }
1809
+ };