ccxt-ir 4.3.46.0.2__py2.py3-none-any.whl → 4.5.0__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 (528) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +9 -9
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +10 -10
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/abstract/ace.py +0 -15
  438. ccxt/abstract/bitbay.py +0 -53
  439. ccxt/abstract/bitcoincom.py +0 -115
  440. ccxt/abstract/bitfinex2.py +0 -139
  441. ccxt/abstract/bitpanda.py +0 -35
  442. ccxt/abstract/bl3p.py +0 -19
  443. ccxt/abstract/coinlist.py +0 -54
  444. ccxt/abstract/currencycom.py +0 -68
  445. ccxt/abstract/hitbtc3.py +0 -115
  446. ccxt/abstract/idex.py +0 -26
  447. ccxt/abstract/kuna.py +0 -182
  448. ccxt/abstract/lykke.py +0 -29
  449. ccxt/abstract/poloniexfutures.py +0 -48
  450. ccxt/abstract/wazirx.py +0 -30
  451. ccxt/ace.py +0 -1012
  452. ccxt/async_support/ace.py +0 -1012
  453. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  454. ccxt/async_support/base/ws/fast_client.py +0 -96
  455. ccxt/async_support/bitbay.py +0 -17
  456. ccxt/async_support/bitcoincom.py +0 -17
  457. ccxt/async_support/bitfinex2.py +0 -3552
  458. ccxt/async_support/bitpanda.py +0 -16
  459. ccxt/async_support/bl3p.py +0 -485
  460. ccxt/async_support/coinlist.py +0 -2243
  461. ccxt/async_support/currencycom.py +0 -1950
  462. ccxt/async_support/hitbtc3.py +0 -16
  463. ccxt/async_support/idex.py +0 -1766
  464. ccxt/async_support/kuna.py +0 -1841
  465. ccxt/async_support/lykke.py +0 -1270
  466. ccxt/async_support/poloniexfutures.py +0 -1717
  467. ccxt/async_support/wazirx.py +0 -1224
  468. ccxt/bitbay.py +0 -17
  469. ccxt/bitcoincom.py +0 -17
  470. ccxt/bitfinex2.py +0 -3552
  471. ccxt/bitpanda.py +0 -16
  472. ccxt/bl3p.py +0 -485
  473. ccxt/coinlist.py +0 -2243
  474. ccxt/currencycom.py +0 -1950
  475. ccxt/hitbtc3.py +0 -16
  476. ccxt/idex.py +0 -1766
  477. ccxt/kuna.py +0 -1841
  478. ccxt/lykke.py +0 -1270
  479. ccxt/poloniexfutures.py +0 -1717
  480. ccxt/pro/bitcoincom.py +0 -34
  481. ccxt/pro/bitfinex2.py +0 -1083
  482. ccxt/pro/bitpanda.py +0 -15
  483. ccxt/pro/currencycom.py +0 -536
  484. ccxt/pro/idex.py +0 -672
  485. ccxt/pro/poloniexfutures.py +0 -990
  486. ccxt/pro/wazirx.py +0 -749
  487. ccxt/test/base/__init__.py +0 -29
  488. ccxt/test/base/test_account.py +0 -26
  489. ccxt/test/base/test_balance.py +0 -56
  490. ccxt/test/base/test_borrow_interest.py +0 -35
  491. ccxt/test/base/test_borrow_rate.py +0 -32
  492. ccxt/test/base/test_calculate_fee.py +0 -51
  493. ccxt/test/base/test_crypto.py +0 -127
  494. ccxt/test/base/test_currency.py +0 -76
  495. ccxt/test/base/test_datetime.py +0 -109
  496. ccxt/test/base/test_decimal_to_precision.py +0 -392
  497. ccxt/test/base/test_deep_extend.py +0 -68
  498. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  499. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  500. ccxt/test/base/test_funding_rate_history.py +0 -29
  501. ccxt/test/base/test_last_price.py +0 -31
  502. ccxt/test/base/test_ledger_entry.py +0 -45
  503. ccxt/test/base/test_ledger_item.py +0 -48
  504. ccxt/test/base/test_leverage_tier.py +0 -33
  505. ccxt/test/base/test_liquidation.py +0 -50
  506. ccxt/test/base/test_margin_mode.py +0 -24
  507. ccxt/test/base/test_margin_modification.py +0 -35
  508. ccxt/test/base/test_market.py +0 -193
  509. ccxt/test/base/test_number.py +0 -411
  510. ccxt/test/base/test_ohlcv.py +0 -33
  511. ccxt/test/base/test_open_interest.py +0 -32
  512. ccxt/test/base/test_order.py +0 -64
  513. ccxt/test/base/test_order_book.py +0 -69
  514. ccxt/test/base/test_position.py +0 -60
  515. ccxt/test/base/test_shared_methods.py +0 -353
  516. ccxt/test/base/test_status.py +0 -24
  517. ccxt/test/base/test_throttle.py +0 -126
  518. ccxt/test/base/test_ticker.py +0 -92
  519. ccxt/test/base/test_trade.py +0 -47
  520. ccxt/test/base/test_trading_fee.py +0 -26
  521. ccxt/test/base/test_transaction.py +0 -39
  522. ccxt/test/test_async.py +0 -1649
  523. ccxt/test/test_sync.py +0 -1648
  524. ccxt/wazirx.py +0 -1224
  525. ccxt_ir-4.3.46.0.2.dist-info/RECORD +0 -772
  526. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  527. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  528. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/pro/modetrade.py ADDED
@@ -0,0 +1,1271 @@
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
+ import ccxt.async_support
7
+ from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
+ from ccxt.base.types import Any, Balances, Bool, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.async_support.base.ws.client import Client
10
+ from typing import List
11
+ from ccxt.base.errors import AuthenticationError
12
+ from ccxt.base.errors import NotSupported
13
+ from ccxt.base.precise import Precise
14
+
15
+
16
+ class modetrade(ccxt.async_support.modetrade):
17
+
18
+ def describe(self) -> Any:
19
+ return self.deep_extend(super(modetrade, self).describe(), {
20
+ 'has': {
21
+ 'ws': True,
22
+ 'watchBalance': True,
23
+ 'watchMyTrades': True,
24
+ 'watchOHLCV': True,
25
+ 'watchOrderBook': True,
26
+ 'watchOrders': True,
27
+ 'watchTicker': True,
28
+ 'watchTickers': True,
29
+ 'watchBidsAsks': True,
30
+ 'watchTrades': True,
31
+ 'watchTradesForSymbols': False,
32
+ 'watchPositions': True,
33
+ },
34
+ 'urls': {
35
+ 'api': {
36
+ 'ws': {
37
+ 'public': 'wss://ws-evm.orderly.org/ws/stream',
38
+ 'private': 'wss://ws-private-evm.orderly.org/v2/ws/private/stream',
39
+ },
40
+ },
41
+ 'test': {
42
+ 'ws': {
43
+ 'public': 'wss://testnet-ws-evm.orderly.org/ws/stream',
44
+ 'private': 'wss://testnet-ws-private-evm.orderly.org/v2/ws/private/stream',
45
+ },
46
+ },
47
+ },
48
+ 'requiredCredentials': {
49
+ 'apiKey': True,
50
+ 'secret': True,
51
+ 'accountId': True,
52
+ },
53
+ 'options': {
54
+ 'tradesLimit': 1000,
55
+ 'ordersLimit': 1000,
56
+ 'requestId': {},
57
+ 'watchPositions': {
58
+ 'fetchPositionsSnapshot': True, # or False
59
+ 'awaitPositionsSnapshot': True, # whether to wait for the positions snapshot before providing updates
60
+ },
61
+ },
62
+ 'streaming': {
63
+ 'ping': self.ping,
64
+ 'keepAlive': 10000,
65
+ },
66
+ 'exceptions': {
67
+ 'ws': {
68
+ 'exact': {
69
+ 'Auth is needed.': AuthenticationError,
70
+ },
71
+ },
72
+ },
73
+ })
74
+
75
+ def request_id(self, url):
76
+ options = self.safe_dict(self.options, 'requestId', {})
77
+ previousValue = self.safe_integer(options, url, 0)
78
+ newValue = self.sum(previousValue, 1)
79
+ self.options['requestId'][url] = newValue
80
+ return newValue
81
+
82
+ async def watch_public(self, messageHash, message):
83
+ # the default id
84
+ id = 'OqdphuyCtYWxwzhxyLLjOWNdFP7sQt8RPWzmb5xY'
85
+ if self.accountId is not None:
86
+ id = self.accountId
87
+ url = self.urls['api']['ws']['public'] + '/' + id
88
+ requestId = self.request_id(url)
89
+ subscribe: dict = {
90
+ 'id': requestId,
91
+ }
92
+ request = self.extend(subscribe, message)
93
+ return await self.watch(url, messageHash, request, messageHash, subscribe)
94
+
95
+ async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
96
+ """
97
+
98
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/orderbook
99
+
100
+ watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
101
+ :param str symbol: unified symbol of the market to fetch the order book for
102
+ :param int [limit]: the maximum amount of order book entries to return.
103
+ :param dict [params]: extra parameters specific to the exchange API endpoint
104
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
105
+ """
106
+ await self.load_markets()
107
+ name = 'orderbook'
108
+ market = self.market(symbol)
109
+ topic = market['id'] + '@' + name
110
+ request: dict = {
111
+ 'event': 'subscribe',
112
+ 'topic': topic,
113
+ }
114
+ message = self.extend(request, params)
115
+ orderbook = await self.watch_public(topic, message)
116
+ return orderbook.limit()
117
+
118
+ def handle_order_book(self, client: Client, message):
119
+ #
120
+ # {
121
+ # "topic": "PERP_BTC_USDC@orderbook",
122
+ # "ts": 1650121915308,
123
+ # "data": {
124
+ # "symbol": "PERP_BTC_USDC",
125
+ # "bids": [
126
+ # [
127
+ # 0.30891,
128
+ # 2469.98
129
+ # ]
130
+ # ],
131
+ # "asks": [
132
+ # [
133
+ # 0.31075,
134
+ # 2379.63
135
+ # ]
136
+ # ]
137
+ # }
138
+ # }
139
+ #
140
+ data = self.safe_dict(message, 'data', {})
141
+ marketId = self.safe_string(data, 'symbol')
142
+ market = self.safe_market(marketId)
143
+ symbol = market['symbol']
144
+ topic = self.safe_string(message, 'topic')
145
+ if not (symbol in self.orderbooks):
146
+ self.orderbooks[symbol] = self.order_book()
147
+ orderbook = self.orderbooks[symbol]
148
+ timestamp = self.safe_integer(message, 'ts')
149
+ snapshot = self.parse_order_book(data, symbol, timestamp, 'bids', 'asks')
150
+ orderbook.reset(snapshot)
151
+ client.resolve(orderbook, topic)
152
+
153
+ async def watch_ticker(self, symbol: str, params={}) -> Ticker:
154
+ """
155
+
156
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/24-hour-ticker
157
+
158
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
159
+ :param str symbol: unified symbol of the market to fetch the ticker for
160
+ :param dict [params]: extra parameters specific to the exchange API endpoint
161
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
162
+ """
163
+ await self.load_markets()
164
+ name = 'ticker'
165
+ market = self.market(symbol)
166
+ symbol = market['symbol']
167
+ topic = market['id'] + '@' + name
168
+ request: dict = {
169
+ 'event': 'subscribe',
170
+ 'topic': topic,
171
+ }
172
+ message = self.extend(request, params)
173
+ return await self.watch_public(topic, message)
174
+
175
+ def parse_ws_ticker(self, ticker, market=None):
176
+ #
177
+ # {
178
+ # "symbol": "PERP_BTC_USDC",
179
+ # "open": 19441.5,
180
+ # "close": 20147.07,
181
+ # "high": 20761.87,
182
+ # "low": 19320.54,
183
+ # "volume": 2481.103,
184
+ # "amount": 50037935.0286,
185
+ # "count": 3689
186
+ # }
187
+ #
188
+ return self.safe_ticker({
189
+ 'symbol': self.safe_symbol(None, market),
190
+ 'timestamp': None,
191
+ 'datetime': None,
192
+ 'high': self.safe_string(ticker, 'high'),
193
+ 'low': self.safe_string(ticker, 'low'),
194
+ 'bid': None,
195
+ 'bidVolume': None,
196
+ 'ask': None,
197
+ 'askVolume': None,
198
+ 'vwap': None,
199
+ 'open': self.safe_string(ticker, 'open'),
200
+ 'close': self.safe_string(ticker, 'close'),
201
+ 'last': None,
202
+ 'previousClose': None,
203
+ 'change': None,
204
+ 'percentage': None,
205
+ 'average': None,
206
+ 'baseVolume': self.safe_string(ticker, 'volume'),
207
+ 'quoteVolume': self.safe_string(ticker, 'amount'),
208
+ 'info': ticker,
209
+ }, market)
210
+
211
+ def handle_ticker(self, client: Client, message):
212
+ #
213
+ # {
214
+ # "topic": "PERP_BTC_USDC@ticker",
215
+ # "ts": 1657120017000,
216
+ # "data": {
217
+ # "symbol": "PERP_BTC_USDC",
218
+ # "open": 19441.5,
219
+ # "close": 20147.07,
220
+ # "high": 20761.87,
221
+ # "low": 19320.54,
222
+ # "volume": 2481.103,
223
+ # "amount": 50037935.0286,
224
+ # "count": 3689
225
+ # }
226
+ # }
227
+ #
228
+ data = self.safe_dict(message, 'data', {})
229
+ topic = self.safe_string(message, 'topic')
230
+ marketId = self.safe_string(data, 'symbol')
231
+ market = self.safe_market(marketId)
232
+ timestamp = self.safe_integer(message, 'ts')
233
+ data['date'] = timestamp
234
+ ticker = self.parse_ws_ticker(data, market)
235
+ ticker['symbol'] = market['symbol']
236
+ self.tickers[market['symbol']] = ticker
237
+ client.resolve(ticker, topic)
238
+ return message
239
+
240
+ async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
241
+ """
242
+
243
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/24-hour-tickers
244
+
245
+ watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
246
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
247
+ :param dict [params]: extra parameters specific to the exchange API endpoint
248
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
249
+ """
250
+ await self.load_markets()
251
+ symbols = self.market_symbols(symbols)
252
+ name = 'tickers'
253
+ topic = name
254
+ request: dict = {
255
+ 'event': 'subscribe',
256
+ 'topic': topic,
257
+ }
258
+ message = self.extend(request, params)
259
+ tickers = await self.watch_public(topic, message)
260
+ return self.filter_by_array(tickers, 'symbol', symbols)
261
+
262
+ def handle_tickers(self, client: Client, message):
263
+ #
264
+ # {
265
+ # "topic":"tickers",
266
+ # "ts":1618820615000,
267
+ # "data":[
268
+ # {
269
+ # "symbol":"PERP_NEAR_USDC",
270
+ # "open":16.297,
271
+ # "close":17.183,
272
+ # "high":24.707,
273
+ # "low":11.997,
274
+ # "volume":0,
275
+ # "amount":0,
276
+ # "count":0
277
+ # },
278
+ # ...
279
+ # ]
280
+ # }
281
+ #
282
+ topic = self.safe_string(message, 'topic')
283
+ data = self.safe_list(message, 'data', [])
284
+ timestamp = self.safe_integer(message, 'ts')
285
+ result = []
286
+ for i in range(0, len(data)):
287
+ marketId = self.safe_string(data[i], 'symbol')
288
+ market = self.safe_market(marketId)
289
+ ticker = self.parse_ws_ticker(self.extend(data[i], {'date': timestamp}), market)
290
+ self.tickers[market['symbol']] = ticker
291
+ result.append(ticker)
292
+ client.resolve(result, topic)
293
+
294
+ async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
295
+ """
296
+
297
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/bbos
298
+
299
+ watches best bid & ask for symbols
300
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
301
+ :param dict [params]: extra parameters specific to the exchange API endpoint
302
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
303
+ """
304
+ await self.load_markets()
305
+ symbols = self.market_symbols(symbols)
306
+ name = 'bbos'
307
+ topic = name
308
+ request: dict = {
309
+ 'event': 'subscribe',
310
+ 'topic': topic,
311
+ }
312
+ message = self.extend(request, params)
313
+ tickers = await self.watch_public(topic, message)
314
+ return self.filter_by_array(tickers, 'symbol', symbols)
315
+
316
+ def handle_bid_ask(self, client: Client, message):
317
+ #
318
+ # {
319
+ # "topic": "bbos",
320
+ # "ts": 1726212495000,
321
+ # "data": [
322
+ # {
323
+ # "symbol": "PERP_BTC_USDC",
324
+ # "ask": 0.16570,
325
+ # "askSize": 4224,
326
+ # "bid": 0.16553,
327
+ # "bidSize": 6645
328
+ # }
329
+ # ]
330
+ # }
331
+ #
332
+ topic = self.safe_string(message, 'topic')
333
+ data = self.safe_list(message, 'data', [])
334
+ timestamp = self.safe_integer(message, 'ts')
335
+ result = []
336
+ for i in range(0, len(data)):
337
+ ticker = self.parse_ws_bid_ask(self.extend(data[i], {'ts': timestamp}))
338
+ self.tickers[ticker['symbol']] = ticker
339
+ result.append(ticker)
340
+ client.resolve(result, topic)
341
+
342
+ def parse_ws_bid_ask(self, ticker, market=None):
343
+ marketId = self.safe_string(ticker, 'symbol')
344
+ market = self.safe_market(marketId, market)
345
+ symbol = self.safe_string(market, 'symbol')
346
+ timestamp = self.safe_integer(ticker, 'ts')
347
+ return self.safe_ticker({
348
+ 'symbol': symbol,
349
+ 'timestamp': timestamp,
350
+ 'datetime': self.iso8601(timestamp),
351
+ 'ask': self.safe_string(ticker, 'ask'),
352
+ 'askVolume': self.safe_string(ticker, 'askSize'),
353
+ 'bid': self.safe_string(ticker, 'bid'),
354
+ 'bidVolume': self.safe_string(ticker, 'bidSize'),
355
+ 'info': ticker,
356
+ }, market)
357
+
358
+ async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
359
+ """
360
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
361
+
362
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/k-line
363
+
364
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
365
+ :param str timeframe: the length of time each candle represents
366
+ :param int [since]: timestamp in ms of the earliest candle to fetch
367
+ :param int [limit]: the maximum amount of candles to fetch
368
+ :param dict [params]: extra parameters specific to the exchange API endpoint
369
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
370
+ """
371
+ await self.load_markets()
372
+ if (timeframe != '1m') and (timeframe != '5m') and (timeframe != '15m') and (timeframe != '30m') and (timeframe != '1h') and (timeframe != '1d') and (timeframe != '1w') and (timeframe != '1M'):
373
+ raise NotSupported(self.id + ' watchOHLCV timeframe argument must be 1m, 5m, 15m, 30m, 1h, 1d, 1w, 1M')
374
+ market = self.market(symbol)
375
+ interval = self.safe_string(self.timeframes, timeframe, timeframe)
376
+ name = 'kline'
377
+ topic = market['id'] + '@' + name + '_' + interval
378
+ request: dict = {
379
+ 'event': 'subscribe',
380
+ 'topic': topic,
381
+ }
382
+ message = self.extend(request, params)
383
+ ohlcv = await self.watch_public(topic, message)
384
+ if self.newUpdates:
385
+ limit = ohlcv.getLimit(market['symbol'], limit)
386
+ return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
387
+
388
+ def handle_ohlcv(self, client: Client, message):
389
+ #
390
+ # {
391
+ # "topic":"PERP_BTC_USDC@kline_1m",
392
+ # "ts":1618822432146,
393
+ # "data":{
394
+ # "symbol":"PERP_BTC_USDC",
395
+ # "type":"1m",
396
+ # "open":56948.97,
397
+ # "close":56891.76,
398
+ # "high":56948.97,
399
+ # "low":56889.06,
400
+ # "volume":44.00947568,
401
+ # "amount":2504584.9,
402
+ # "startTime":1618822380000,
403
+ # "endTime":1618822440000
404
+ # }
405
+ # }
406
+ #
407
+ data = self.safe_dict(message, 'data', {})
408
+ topic = self.safe_string(message, 'topic')
409
+ marketId = self.safe_string(data, 'symbol')
410
+ market = self.safe_market(marketId)
411
+ symbol = market['symbol']
412
+ interval = self.safe_string(data, 'type')
413
+ timeframe = self.find_timeframe(interval)
414
+ parsed = [
415
+ self.safe_integer(data, 'startTime'),
416
+ self.safe_number(data, 'open'),
417
+ self.safe_number(data, 'high'),
418
+ self.safe_number(data, 'low'),
419
+ self.safe_number(data, 'close'),
420
+ self.safe_number(data, 'volume'),
421
+ ]
422
+ self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
423
+ stored = self.safe_value(self.ohlcvs[symbol], timeframe)
424
+ if stored is None:
425
+ limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
426
+ stored = ArrayCacheByTimestamp(limit)
427
+ self.ohlcvs[symbol][timeframe] = stored
428
+ ohlcvCache = self.ohlcvs[symbol][timeframe]
429
+ ohlcvCache.append(parsed)
430
+ client.resolve(ohlcvCache, topic)
431
+
432
+ async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
433
+ """
434
+ watches information on multiple trades made in a market
435
+
436
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/public/trade
437
+
438
+ :param str symbol: unified market symbol of the market trades were made in
439
+ :param int [since]: the earliest time in ms to fetch trades for
440
+ :param int [limit]: the maximum number of trade structures to retrieve
441
+ :param dict [params]: extra parameters specific to the exchange API endpoint
442
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
443
+ """
444
+ await self.load_markets()
445
+ market = self.market(symbol)
446
+ symbol = market['symbol']
447
+ topic = market['id'] + '@trade'
448
+ request: dict = {
449
+ 'event': 'subscribe',
450
+ 'topic': topic,
451
+ }
452
+ message = self.extend(request, params)
453
+ trades = await self.watch_public(topic, message)
454
+ if self.newUpdates:
455
+ limit = trades.getLimit(market['symbol'], limit)
456
+ return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
457
+
458
+ def handle_trade(self, client: Client, message):
459
+ #
460
+ # {
461
+ # "topic":"PERP_ADA_USDC@trade",
462
+ # "ts":1618820361552,
463
+ # "data":{
464
+ # "symbol":"PERP_ADA_USDC",
465
+ # "price":1.27988,
466
+ # "size":300,
467
+ # "side":"BUY",
468
+ # }
469
+ # }
470
+ #
471
+ topic = self.safe_string(message, 'topic')
472
+ timestamp = self.safe_integer(message, 'ts')
473
+ data = self.safe_dict(message, 'data', {})
474
+ marketId = self.safe_string(data, 'symbol')
475
+ market = self.safe_market(marketId)
476
+ symbol = market['symbol']
477
+ trade = self.parse_ws_trade(self.extend(data, {'timestamp': timestamp}), market)
478
+ if not (symbol in self.trades):
479
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
480
+ stored = ArrayCache(limit)
481
+ self.trades[symbol] = stored
482
+ trades = self.trades[symbol]
483
+ trades.append(trade)
484
+ self.trades[symbol] = trades
485
+ client.resolve(trades, topic)
486
+
487
+ def parse_ws_trade(self, trade, market=None):
488
+ #
489
+ # {
490
+ # "symbol":"PERP_ADA_USDC",
491
+ # "timestamp":1618820361552,
492
+ # "price":1.27988,
493
+ # "size":300,
494
+ # "side":"BUY",
495
+ # }
496
+ # private stream
497
+ # {
498
+ # symbol: 'PERP_XRP_USDC',
499
+ # clientOrderId: '',
500
+ # orderId: 1167632251,
501
+ # type: 'MARKET',
502
+ # side: 'BUY',
503
+ # quantity: 20,
504
+ # price: 0,
505
+ # tradeId: '1715179456664012',
506
+ # executedPrice: 0.5276,
507
+ # executedQuantity: 20,
508
+ # fee: 0.006332,
509
+ # feeAsset: 'USDC',
510
+ # totalExecutedQuantity: 20,
511
+ # avgPrice: 0.5276,
512
+ # averageExecutedPrice: 0.5276,
513
+ # status: 'FILLED',
514
+ # reason: '',
515
+ # totalFee: 0.006332,
516
+ # visible: 0,
517
+ # visibleQuantity: 0,
518
+ # timestamp: 1715179456660,
519
+ # orderTag: 'CCXT',
520
+ # createdTime: 1715179456656,
521
+ # maker: False
522
+ # }
523
+ #
524
+ marketId = self.safe_string(trade, 'symbol')
525
+ market = self.safe_market(marketId, market)
526
+ symbol = market['symbol']
527
+ price = self.safe_string_2(trade, 'executedPrice', 'price')
528
+ amount = self.safe_string_2(trade, 'executedQuantity', 'size')
529
+ cost = Precise.string_mul(price, amount)
530
+ side = self.safe_string_lower(trade, 'side')
531
+ timestamp = self.safe_integer(trade, 'timestamp')
532
+ takerOrMaker = None
533
+ maker = self.safe_bool(trade, 'maker')
534
+ if maker is not None:
535
+ takerOrMaker = 'maker' if maker else 'taker'
536
+ fee = None
537
+ feeValue = self.safe_string(trade, 'fee')
538
+ if feeValue is not None:
539
+ fee = {
540
+ 'cost': feeValue,
541
+ 'currency': self.safe_currency_code(self.safe_string(trade, 'feeAsset')),
542
+ }
543
+ return self.safe_trade({
544
+ 'id': self.safe_string(trade, 'tradeId'),
545
+ 'timestamp': timestamp,
546
+ 'datetime': self.iso8601(timestamp),
547
+ 'symbol': symbol,
548
+ 'side': side,
549
+ 'price': price,
550
+ 'amount': amount,
551
+ 'cost': cost,
552
+ 'order': self.safe_string(trade, 'orderId'),
553
+ 'takerOrMaker': takerOrMaker,
554
+ 'type': self.safe_string_lower(trade, 'type'),
555
+ 'fee': fee,
556
+ 'info': trade,
557
+ }, market)
558
+
559
+ def handle_auth(self, client: Client, message):
560
+ #
561
+ # {
562
+ # "event": "auth",
563
+ # "success": True,
564
+ # "ts": 1657463158812
565
+ # }
566
+ #
567
+ messageHash = 'authenticated'
568
+ success = self.safe_value(message, 'success')
569
+ if success:
570
+ # client.resolve(message, messageHash)
571
+ future = self.safe_value(client.futures, 'authenticated')
572
+ future.resolve(True)
573
+ else:
574
+ error = AuthenticationError(self.json(message))
575
+ client.reject(error, messageHash)
576
+ # allows further authentication attempts
577
+ if messageHash in client.subscriptions:
578
+ del client.subscriptions['authenticated']
579
+
580
+ async def authenticate(self, params={}):
581
+ self.check_required_credentials()
582
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
583
+ client = self.client(url)
584
+ messageHash = 'authenticated'
585
+ event = 'auth'
586
+ future = client.future(messageHash)
587
+ authenticated = self.safe_value(client.subscriptions, messageHash)
588
+ if authenticated is None:
589
+ ts = str(self.nonce())
590
+ auth = ts
591
+ secret = self.secret
592
+ if secret.find('ed25519:') >= 0:
593
+ parts = secret.split('ed25519:')
594
+ secret = parts[1]
595
+ signature = self.eddsa(self.encode(auth), self.base58_to_binary(secret), 'ed25519')
596
+ request: dict = {
597
+ 'event': event,
598
+ 'params': {
599
+ 'orderly_key': self.apiKey,
600
+ 'sign': signature,
601
+ 'timestamp': ts,
602
+ },
603
+ }
604
+ message = self.extend(request, params)
605
+ self.watch(url, messageHash, message, messageHash)
606
+ return await future
607
+
608
+ async def watch_private(self, messageHash, message, params={}):
609
+ await self.authenticate(params)
610
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
611
+ requestId = self.request_id(url)
612
+ subscribe: dict = {
613
+ 'id': requestId,
614
+ }
615
+ request = self.extend(subscribe, message)
616
+ return await self.watch(url, messageHash, request, messageHash, subscribe)
617
+
618
+ async def watch_private_multiple(self, messageHashes, message, params={}):
619
+ await self.authenticate(params)
620
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
621
+ requestId = self.request_id(url)
622
+ subscribe: dict = {
623
+ 'id': requestId,
624
+ }
625
+ request = self.extend(subscribe, message)
626
+ return await self.watch_multiple(url, messageHashes, request, messageHashes, subscribe)
627
+
628
+ async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
629
+ """
630
+ watches information on multiple orders made by the user
631
+
632
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/execution-report
633
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/algo-execution-report
634
+
635
+ :param str symbol: unified market symbol of the market orders were made in
636
+ :param int [since]: the earliest time in ms to fetch orders for
637
+ :param int [limit]: the maximum number of order structures to retrieve
638
+ :param dict [params]: extra parameters specific to the exchange API endpoint
639
+ :param bool [params.trigger]: True if trigger order
640
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
641
+ """
642
+ await self.load_markets()
643
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
644
+ topic = 'algoexecutionreport' if (trigger) else 'executionreport'
645
+ params = self.omit(params, ['stop', 'trigger'])
646
+ messageHash = topic
647
+ if symbol is not None:
648
+ market = self.market(symbol)
649
+ symbol = market['symbol']
650
+ messageHash += ':' + symbol
651
+ request: dict = {
652
+ 'event': 'subscribe',
653
+ 'topic': topic,
654
+ }
655
+ message = self.extend(request, params)
656
+ orders = await self.watch_private(messageHash, message)
657
+ if self.newUpdates:
658
+ limit = orders.getLimit(symbol, limit)
659
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
660
+
661
+ async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
662
+ """
663
+ watches information on multiple trades made by the user
664
+
665
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/execution-report
666
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/algo-execution-report
667
+
668
+ :param str symbol: unified market symbol of the market orders were made in
669
+ :param int [since]: the earliest time in ms to fetch orders for
670
+ :param int [limit]: the maximum number of order structures to retrieve
671
+ :param dict [params]: extra parameters specific to the exchange API endpoint
672
+ :param bool [params.trigger]: True if trigger order
673
+ :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
674
+ """
675
+ await self.load_markets()
676
+ trigger = self.safe_bool_2(params, 'stop', 'trigger', False)
677
+ topic = 'algoexecutionreport' if (trigger) else 'executionreport'
678
+ params = self.omit(params, 'stop')
679
+ messageHash = 'myTrades'
680
+ if symbol is not None:
681
+ market = self.market(symbol)
682
+ symbol = market['symbol']
683
+ messageHash += ':' + symbol
684
+ request: dict = {
685
+ 'event': 'subscribe',
686
+ 'topic': topic,
687
+ }
688
+ message = self.extend(request, params)
689
+ orders = await self.watch_private(messageHash, message)
690
+ if self.newUpdates:
691
+ limit = orders.getLimit(symbol, limit)
692
+ return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
693
+
694
+ def parse_ws_order(self, order, market=None):
695
+ #
696
+ # {
697
+ # "symbol": "PERP_BTC_USDT",
698
+ # "clientOrderId": 0,
699
+ # "orderId": 52952826,
700
+ # "type": "LIMIT",
701
+ # "side": "SELL",
702
+ # "quantity": 0.01,
703
+ # "price": 22000,
704
+ # "tradeId": 0,
705
+ # "executedPrice": 0,
706
+ # "executedQuantity": 0,
707
+ # "fee": 0,
708
+ # "feeAsset": "USDT",
709
+ # "totalExecutedQuantity": 0,
710
+ # "status": "NEW",
711
+ # "reason": '',
712
+ # "orderTag": "default",
713
+ # "totalFee": 0,
714
+ # "visible": 0.01,
715
+ # "timestamp": 1657515556799,
716
+ # "reduceOnly": False,
717
+ # "maker": False
718
+ # }
719
+ # algo order
720
+ # {
721
+ # "symbol":"PERP_MATIC_USDC",
722
+ # "rootAlgoOrderId":123,
723
+ # "parentAlgoOrderId":123,
724
+ # "algoOrderId":123,
725
+ # "orderTag":"some tags",
726
+ # "algoType": "STOP",
727
+ # "clientOrderId":"client_id",
728
+ # "type":"LIMIT",
729
+ # "side":"BUY",
730
+ # "quantity":7029.0,
731
+ # "price":0.7699,
732
+ # "tradeId":0,
733
+ # "triggerTradePrice":0,
734
+ # "triggerTime":1234567,
735
+ # "triggered": False,
736
+ # "activated": False,
737
+ # "executedPrice":0.0,
738
+ # "executedQuantity":0.0,
739
+ # "fee":0.0,
740
+ # "feeAsset":"USDC",
741
+ # "totalExecutedQuantity":0.0,
742
+ # "averageExecutedQuantity":0.0,
743
+ # "avgPrice":0,
744
+ # "triggerPrice":0.0,
745
+ # "triggerPriceType":"STOP",
746
+ # "isActivated": False,
747
+ # "status":"NEW",
748
+ # "rootAlgoStatus": "FILLED",
749
+ # "algoStatus": "FILLED",
750
+ # "reason":"",
751
+ # "totalFee":0.0,
752
+ # "visible": 7029.0,
753
+ # "visibleQuantity":7029.0,
754
+ # "timestamp":1704679472448,
755
+ # "maker":false,
756
+ # "isMaker":false,
757
+ # "createdTime":1704679472448
758
+ # }
759
+ #
760
+ orderId = self.safe_string(order, 'orderId')
761
+ marketId = self.safe_string(order, 'symbol')
762
+ market = self.market(marketId)
763
+ symbol = market['symbol']
764
+ timestamp = self.safe_integer(order, 'timestamp')
765
+ fee = {
766
+ 'cost': self.safe_string(order, 'totalFee'),
767
+ 'currency': self.safe_string(order, 'feeAsset'),
768
+ }
769
+ priceString = self.safe_string(order, 'price')
770
+ price = self.safe_number(order, 'price')
771
+ avgPrice = self.safe_number(order, 'avgPrice')
772
+ if Precise.string_eq(priceString, '0') and (avgPrice is not None):
773
+ price = avgPrice
774
+ amount = self.safe_string(order, 'quantity')
775
+ side = self.safe_string_lower(order, 'side')
776
+ type = self.safe_string_lower(order, 'type')
777
+ filled = self.safe_number(order, 'totalExecutedQuantity')
778
+ totalExecQuantity = self.safe_string(order, 'totalExecutedQuantity')
779
+ remaining = amount
780
+ if Precise.string_ge(amount, totalExecQuantity):
781
+ remaining = Precise.string_sub(remaining, totalExecQuantity)
782
+ rawStatus = self.safe_string(order, 'status')
783
+ status = self.parse_order_status(rawStatus)
784
+ trades = None
785
+ clientOrderId = self.safe_string(order, 'clientOrderId')
786
+ triggerPrice = self.safe_number(order, 'triggerPrice')
787
+ return self.safe_order({
788
+ 'info': order,
789
+ 'symbol': symbol,
790
+ 'id': orderId,
791
+ 'clientOrderId': clientOrderId,
792
+ 'timestamp': timestamp,
793
+ 'datetime': self.iso8601(timestamp),
794
+ 'lastTradeTimestamp': timestamp,
795
+ 'type': type,
796
+ 'timeInForce': None,
797
+ 'postOnly': None,
798
+ 'side': side,
799
+ 'price': price,
800
+ 'stopPrice': triggerPrice,
801
+ 'triggerPrice': triggerPrice,
802
+ 'amount': amount,
803
+ 'cost': None,
804
+ 'average': None,
805
+ 'filled': filled,
806
+ 'remaining': remaining,
807
+ 'status': status,
808
+ 'fee': fee,
809
+ 'trades': trades,
810
+ })
811
+
812
+ def handle_order_update(self, client: Client, message):
813
+ #
814
+ # {
815
+ # "topic": "executionreport",
816
+ # "ts": 1657515556799,
817
+ # "data": {
818
+ # "symbol": "PERP_BTC_USDT",
819
+ # "clientOrderId": 0,
820
+ # "orderId": 52952826,
821
+ # "type": "LIMIT",
822
+ # "side": "SELL",
823
+ # "quantity": 0.01,
824
+ # "price": 22000,
825
+ # "tradeId": 0,
826
+ # "executedPrice": 0,
827
+ # "executedQuantity": 0,
828
+ # "fee": 0,
829
+ # "feeAsset": "USDT",
830
+ # "totalExecutedQuantity": 0,
831
+ # "status": "NEW",
832
+ # "reason": '',
833
+ # "orderTag": "default",
834
+ # "totalFee": 0,
835
+ # "visible": 0.01,
836
+ # "timestamp": 1657515556799,
837
+ # "maker": False
838
+ # }
839
+ # }
840
+ #
841
+ topic = self.safe_string(message, 'topic')
842
+ data = self.safe_value(message, 'data')
843
+ if isinstance(data, list):
844
+ # algoexecutionreport
845
+ for i in range(0, len(data)):
846
+ order = data[i]
847
+ tradeId = self.omit_zero(self.safe_string(data, 'tradeId'))
848
+ if tradeId is not None:
849
+ self.handle_my_trade(client, order)
850
+ self.handle_order(client, order, topic)
851
+ else:
852
+ # executionreport
853
+ tradeId = self.omit_zero(self.safe_string(data, 'tradeId'))
854
+ if tradeId is not None:
855
+ self.handle_my_trade(client, data)
856
+ self.handle_order(client, data, topic)
857
+
858
+ def handle_order(self, client: Client, message, topic):
859
+ parsed = self.parse_ws_order(message)
860
+ symbol = self.safe_string(parsed, 'symbol')
861
+ orderId = self.safe_string(parsed, 'id')
862
+ if symbol is not None:
863
+ if self.orders is None:
864
+ limit = self.safe_integer(self.options, 'ordersLimit', 1000)
865
+ self.orders = ArrayCacheBySymbolById(limit)
866
+ cachedOrders = self.orders
867
+ orders = self.safe_dict(cachedOrders.hashmap, symbol, {})
868
+ order = self.safe_dict(orders, orderId)
869
+ if order is not None:
870
+ fee = self.safe_value(order, 'fee')
871
+ if fee is not None:
872
+ parsed['fee'] = fee
873
+ fees = self.safe_list(order, 'fees')
874
+ if fees is not None:
875
+ parsed['fees'] = fees
876
+ parsed['trades'] = self.safe_list(order, 'trades')
877
+ parsed['timestamp'] = self.safe_integer(order, 'timestamp')
878
+ parsed['datetime'] = self.safe_string(order, 'datetime')
879
+ cachedOrders.append(parsed)
880
+ client.resolve(self.orders, topic)
881
+ messageHashSymbol = topic + ':' + symbol
882
+ client.resolve(self.orders, messageHashSymbol)
883
+
884
+ def handle_my_trade(self, client: Client, message):
885
+ #
886
+ # {
887
+ # symbol: 'PERP_XRP_USDC',
888
+ # clientOrderId: '',
889
+ # orderId: 1167632251,
890
+ # type: 'MARKET',
891
+ # side: 'BUY',
892
+ # quantity: 20,
893
+ # price: 0,
894
+ # tradeId: '1715179456664012',
895
+ # executedPrice: 0.5276,
896
+ # executedQuantity: 20,
897
+ # fee: 0.006332,
898
+ # feeAsset: 'USDC',
899
+ # totalExecutedQuantity: 20,
900
+ # avgPrice: 0.5276,
901
+ # averageExecutedPrice: 0.5276,
902
+ # status: 'FILLED',
903
+ # reason: '',
904
+ # totalFee: 0.006332,
905
+ # visible: 0,
906
+ # visibleQuantity: 0,
907
+ # timestamp: 1715179456660,
908
+ # orderTag: 'CCXT',
909
+ # createdTime: 1715179456656,
910
+ # maker: False
911
+ # }
912
+ #
913
+ messageHash = 'myTrades'
914
+ marketId = self.safe_string(message, 'symbol')
915
+ market = self.safe_market(marketId)
916
+ symbol = market['symbol']
917
+ trade = self.parse_ws_trade(message, market)
918
+ trades = self.myTrades
919
+ if trades is None:
920
+ limit = self.safe_integer(self.options, 'tradesLimit', 1000)
921
+ trades = ArrayCacheBySymbolById(limit)
922
+ self.myTrades = trades
923
+ trades.append(trade)
924
+ client.resolve(trades, messageHash)
925
+ symbolSpecificMessageHash = messageHash + ':' + symbol
926
+ client.resolve(trades, symbolSpecificMessageHash)
927
+
928
+ async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
929
+ """
930
+
931
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/position-push
932
+
933
+ watch all open positions
934
+ :param str[] [symbols]: list of unified market symbols
935
+ @param since timestamp in ms of the earliest position to fetch
936
+ @param limit the maximum number of positions to fetch
937
+ :param dict params: extra parameters specific to the exchange API endpoint
938
+ :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
939
+ """
940
+ await self.load_markets()
941
+ messageHashes = []
942
+ symbols = self.market_symbols(symbols)
943
+ if not self.is_empty(symbols):
944
+ for i in range(0, len(symbols)):
945
+ symbol = symbols[i]
946
+ messageHashes.append('positions::' + symbol)
947
+ else:
948
+ messageHashes.append('positions')
949
+ url = self.urls['api']['ws']['private'] + '/' + self.accountId
950
+ client = self.client(url)
951
+ self.set_positions_cache(client, symbols)
952
+ fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
953
+ awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
954
+ if fetchPositionsSnapshot and awaitPositionsSnapshot and self.positions is None:
955
+ snapshot = await client.future('fetchPositionsSnapshot')
956
+ return self.filter_by_symbols_since_limit(snapshot, symbols, since, limit, True)
957
+ request: dict = {
958
+ 'event': 'subscribe',
959
+ 'topic': 'position',
960
+ }
961
+ newPositions = await self.watch_private_multiple(messageHashes, request, params)
962
+ if self.newUpdates:
963
+ return newPositions
964
+ return self.filter_by_symbols_since_limit(self.positions, symbols, since, limit, True)
965
+
966
+ def set_positions_cache(self, client: Client, type, symbols: Strings = None):
967
+ fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', False)
968
+ if fetchPositionsSnapshot:
969
+ messageHash = 'fetchPositionsSnapshot'
970
+ if not (messageHash in client.futures):
971
+ client.future(messageHash)
972
+ self.spawn(self.load_positions_snapshot, client, messageHash)
973
+ else:
974
+ self.positions = ArrayCacheBySymbolBySide()
975
+
976
+ async def load_positions_snapshot(self, client, messageHash):
977
+ positions = await self.fetch_positions()
978
+ self.positions = ArrayCacheBySymbolBySide()
979
+ cache = self.positions
980
+ for i in range(0, len(positions)):
981
+ position = positions[i]
982
+ contracts = self.safe_string(position, 'contracts', '0')
983
+ if Precise.string_gt(contracts, '0'):
984
+ cache.append(position)
985
+ # don't remove the future from the .futures cache
986
+ future = client.futures[messageHash]
987
+ future.resolve(cache)
988
+ client.resolve(cache, 'positions')
989
+
990
+ def handle_positions(self, client, message):
991
+ #
992
+ # {
993
+ # "topic":"position",
994
+ # "ts":1705292345255,
995
+ # "data":{
996
+ # "positions":[
997
+ # {
998
+ # "symbol":"PERP_ETH_USDC",
999
+ # "positionQty":3.1408,
1000
+ # "costPosition":5706.51952,
1001
+ # "lastSumUnitaryFunding":0.804,
1002
+ # "sumUnitaryFundingVersion":0,
1003
+ # "pendingLongQty":0.0,
1004
+ # "pendingShortQty":-1.0,
1005
+ # "settlePrice":1816.9,
1006
+ # "averageOpenPrice":1804.51490427,
1007
+ # "unsettledPnl":-2.79856,
1008
+ # "pnl24H":-338.90179488,
1009
+ # "fee24H":4.242423,
1010
+ # "markPrice":1816.2,
1011
+ # "estLiqPrice":0.0,
1012
+ # "version":179967,
1013
+ # "imrwithOrders":0.1,
1014
+ # "mmrwithOrders":0.05,
1015
+ # "mmr":0.05,
1016
+ # "imr":0.1,
1017
+ # "timestamp":1685154032762
1018
+ # }
1019
+ # ]
1020
+ # }
1021
+ # }
1022
+ #
1023
+ data = self.safe_dict(message, 'data', {})
1024
+ rawPositions = self.safe_list(data, 'positions', [])
1025
+ if self.positions is None:
1026
+ self.positions = ArrayCacheBySymbolBySide()
1027
+ cache = self.positions
1028
+ newPositions = []
1029
+ for i in range(0, len(rawPositions)):
1030
+ rawPosition = rawPositions[i]
1031
+ marketId = self.safe_string(rawPosition, 'symbol')
1032
+ market = self.safe_market(marketId)
1033
+ position = self.parse_ws_position(rawPosition, market)
1034
+ newPositions.append(position)
1035
+ cache.append(position)
1036
+ messageHash = 'positions::' + market['symbol']
1037
+ client.resolve(position, messageHash)
1038
+ client.resolve(newPositions, 'positions')
1039
+
1040
+ def parse_ws_position(self, position, market=None):
1041
+ #
1042
+ # {
1043
+ # "symbol":"PERP_ETH_USDC",
1044
+ # "positionQty":3.1408,
1045
+ # "costPosition":5706.51952,
1046
+ # "lastSumUnitaryFunding":0.804,
1047
+ # "sumUnitaryFundingVersion":0,
1048
+ # "pendingLongQty":0.0,
1049
+ # "pendingShortQty":-1.0,
1050
+ # "settlePrice":1816.9,
1051
+ # "averageOpenPrice":1804.51490427,
1052
+ # "unsettledPnl":-2.79856,
1053
+ # "pnl24H":-338.90179488,
1054
+ # "fee24H":4.242423,
1055
+ # "markPrice":1816.2,
1056
+ # "estLiqPrice":0.0,
1057
+ # "version":179967,
1058
+ # "imrwithOrders":0.1,
1059
+ # "mmrwithOrders":0.05,
1060
+ # "mmr":0.05,
1061
+ # "imr":0.1,
1062
+ # "timestamp":1685154032762
1063
+ # }
1064
+ #
1065
+ contract = self.safe_string(position, 'symbol')
1066
+ market = self.safe_market(contract, market)
1067
+ size = self.safe_string(position, 'positionQty')
1068
+ side: Str = None
1069
+ if Precise.string_gt(size, '0'):
1070
+ side = 'long'
1071
+ else:
1072
+ side = 'short'
1073
+ contractSize = self.safe_string(market, 'contractSize')
1074
+ markPrice = self.safe_string(position, 'markPrice')
1075
+ timestamp = self.safe_integer(position, 'timestamp')
1076
+ entryPrice = self.safe_string(position, 'averageOpenPrice')
1077
+ unrealisedPnl = self.safe_string(position, 'unsettledPnl')
1078
+ size = Precise.string_abs(size)
1079
+ notional = Precise.string_mul(size, markPrice)
1080
+ return self.safe_position({
1081
+ 'info': position,
1082
+ 'id': None,
1083
+ 'symbol': self.safe_string(market, 'symbol'),
1084
+ 'timestamp': timestamp,
1085
+ 'datetime': self.iso8601(timestamp),
1086
+ 'lastUpdateTimestamp': None,
1087
+ 'initialMargin': None,
1088
+ 'initialMarginPercentage': None,
1089
+ 'maintenanceMargin': None,
1090
+ 'maintenanceMarginPercentage': None,
1091
+ 'entryPrice': self.parse_number(entryPrice),
1092
+ 'notional': self.parse_number(notional),
1093
+ 'leverage': None,
1094
+ 'unrealizedPnl': self.parse_number(unrealisedPnl),
1095
+ 'contracts': self.parse_number(size),
1096
+ 'contractSize': self.parse_number(contractSize),
1097
+ 'marginRatio': None,
1098
+ 'liquidationPrice': self.safe_number(position, 'estLiqPrice'),
1099
+ 'markPrice': self.parse_number(markPrice),
1100
+ 'lastPrice': None,
1101
+ 'collateral': None,
1102
+ 'marginMode': 'cross',
1103
+ 'marginType': None,
1104
+ 'side': side,
1105
+ 'percentage': None,
1106
+ 'hedged': None,
1107
+ 'stopLossPrice': None,
1108
+ 'takeProfitPrice': None,
1109
+ })
1110
+
1111
+ async def watch_balance(self, params={}) -> Balances:
1112
+ """
1113
+ watch balance and get the amount of funds available for trading or funds locked in orders
1114
+
1115
+ https://orderly.network/docs/build-on-evm/evm-api/websocket-api/private/balance
1116
+
1117
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1118
+ :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1119
+ """
1120
+ await self.load_markets()
1121
+ topic = 'balance'
1122
+ messageHash = topic
1123
+ request: dict = {
1124
+ 'event': 'subscribe',
1125
+ 'topic': topic,
1126
+ }
1127
+ message = self.extend(request, params)
1128
+ return await self.watch_private(messageHash, message)
1129
+
1130
+ def handle_balance(self, client, message):
1131
+ #
1132
+ # {
1133
+ # "topic":"balance",
1134
+ # "ts":1651836695254,
1135
+ # "data":{
1136
+ # "balances":{
1137
+ # "USDC":{
1138
+ # "holding":5555815.47398272,
1139
+ # "frozen":0,
1140
+ # "interest":0,
1141
+ # "pendingShortQty":0,
1142
+ # "pendingExposure":0,
1143
+ # "pendingLongQty":0,
1144
+ # "pendingLongExposure":0,
1145
+ # "version":894,
1146
+ # "staked":51370692,
1147
+ # "unbonding":0,
1148
+ # "vault":0,
1149
+ # "averageOpenPrice":0.00000574,
1150
+ # "pnl24H":0,
1151
+ # "fee24H":0.01914,
1152
+ # "markPrice":0.31885
1153
+ # }
1154
+ # }
1155
+ # }
1156
+ # }
1157
+ #
1158
+ data = self.safe_dict(message, 'data', {})
1159
+ balances = self.safe_dict(data, 'balances', {})
1160
+ keys = list(balances.keys())
1161
+ ts = self.safe_integer(message, 'ts')
1162
+ self.balance['info'] = data
1163
+ self.balance['timestamp'] = ts
1164
+ self.balance['datetime'] = self.iso8601(ts)
1165
+ for i in range(0, len(keys)):
1166
+ key = keys[i]
1167
+ value = balances[key]
1168
+ code = self.safe_currency_code(key)
1169
+ account = self.balance[code] if (code in self.balance) else self.account()
1170
+ total = self.safe_string(value, 'holding')
1171
+ used = self.safe_string(value, 'frozen')
1172
+ account['total'] = total
1173
+ account['used'] = used
1174
+ account['free'] = Precise.string_sub(total, used)
1175
+ self.balance[code] = account
1176
+ self.balance = self.safe_balance(self.balance)
1177
+ client.resolve(self.balance, 'balance')
1178
+
1179
+ def handle_error_message(self, client: Client, message) -> Bool:
1180
+ #
1181
+ # {"id":"1","event":"subscribe","success":false,"ts":1710780997216,"errorMsg":"Auth is needed."}
1182
+ #
1183
+ if not ('success' in message):
1184
+ return False
1185
+ success = self.safe_bool(message, 'success')
1186
+ if success:
1187
+ return False
1188
+ errorMessage = self.safe_string(message, 'errorMsg')
1189
+ try:
1190
+ if errorMessage is not None:
1191
+ feedback = self.id + ' ' + self.json(message)
1192
+ self.throw_exactly_matched_exception(self.exceptions['exact'], errorMessage, feedback)
1193
+ return False
1194
+ except Exception as error:
1195
+ if isinstance(error, AuthenticationError):
1196
+ messageHash = 'authenticated'
1197
+ client.reject(error, messageHash)
1198
+ if messageHash in client.subscriptions:
1199
+ del client.subscriptions[messageHash]
1200
+ else:
1201
+ client.reject(error)
1202
+ return True
1203
+
1204
+ def handle_message(self, client: Client, message):
1205
+ if self.handle_error_message(client, message):
1206
+ return
1207
+ methods: dict = {
1208
+ 'ping': self.handle_ping,
1209
+ 'pong': self.handle_pong,
1210
+ 'subscribe': self.handle_subscribe,
1211
+ 'orderbook': self.handle_order_book,
1212
+ 'ticker': self.handle_ticker,
1213
+ 'tickers': self.handle_tickers,
1214
+ 'kline': self.handle_ohlcv,
1215
+ 'trade': self.handle_trade,
1216
+ 'auth': self.handle_auth,
1217
+ 'executionreport': self.handle_order_update,
1218
+ 'algoexecutionreport': self.handle_order_update,
1219
+ 'position': self.handle_positions,
1220
+ 'balance': self.handle_balance,
1221
+ 'bbos': self.handle_bid_ask,
1222
+ }
1223
+ event = self.safe_string(message, 'event')
1224
+ method = self.safe_value(methods, event)
1225
+ if method is not None:
1226
+ method(client, message)
1227
+ return
1228
+ topic = self.safe_string(message, 'topic')
1229
+ if topic is not None:
1230
+ method = self.safe_value(methods, topic)
1231
+ if method is not None:
1232
+ method(client, message)
1233
+ return
1234
+ splitTopic = topic.split('@')
1235
+ splitLength = len(splitTopic)
1236
+ if splitLength == 2:
1237
+ name = self.safe_string(splitTopic, 1)
1238
+ method = self.safe_value(methods, name)
1239
+ if method is not None:
1240
+ method(client, message)
1241
+ return
1242
+ splitName = name.split('_')
1243
+ splitNameLength = len(splitTopic)
1244
+ if splitNameLength == 2:
1245
+ method = self.safe_value(methods, self.safe_string(splitName, 0))
1246
+ if method is not None:
1247
+ method(client, message)
1248
+
1249
+ def ping(self, client: Client):
1250
+ return {'event': 'ping'}
1251
+
1252
+ def handle_ping(self, client: Client, message):
1253
+ return {'event': 'pong'}
1254
+
1255
+ def handle_pong(self, client: Client, message):
1256
+ #
1257
+ # {event: "pong", ts: 1614667590000}
1258
+ #
1259
+ client.lastPong = self.milliseconds()
1260
+ return message
1261
+
1262
+ def handle_subscribe(self, client: Client, message):
1263
+ #
1264
+ # {
1265
+ # "id": "666888",
1266
+ # "event": "subscribe",
1267
+ # "success": True,
1268
+ # "ts": 1657117712212
1269
+ # }
1270
+ #
1271
+ return message