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/binance.py CHANGED
@@ -6,20 +6,24 @@
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Any, Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ArgumentsRequired
13
13
  from ccxt.base.errors import BadRequest
14
14
  from ccxt.base.errors import NotSupported
15
- from ccxt.base.errors import InvalidNonce
15
+ from ccxt.base.errors import ChecksumError
16
16
  from ccxt.base.precise import Precise
17
17
 
18
18
 
19
19
  class binance(ccxt.async_support.binance):
20
20
 
21
- def describe(self):
22
- return self.deep_extend(super(binance, self).describe(), {
21
+ def describe(self) -> Any:
22
+ superDescribe = super(binance, self).describe()
23
+ return self.deep_extend(superDescribe, self.describe_data())
24
+
25
+ def describe_data(self):
26
+ return {
23
27
  'has': {
24
28
  'ws': True,
25
29
  'watchBalance': True,
@@ -30,7 +34,7 @@ class binance(ccxt.async_support.binance):
30
34
  'watchBidsAsks': True,
31
35
  'watchMyTrades': True,
32
36
  'watchOHLCV': True,
33
- 'watchOHLCVForSymbols': False,
37
+ 'watchOHLCVForSymbols': True,
34
38
  'watchOrderBook': True,
35
39
  'watchOrderBookForSymbols': True,
36
40
  'watchOrders': True,
@@ -38,6 +42,8 @@ class binance(ccxt.async_support.binance):
38
42
  'watchPositions': True,
39
43
  'watchTicker': True,
40
44
  'watchTickers': True,
45
+ 'watchMarkPrices': True,
46
+ 'watchMarkPrice': True,
41
47
  'watchTrades': True,
42
48
  'watchTradesForSymbols': True,
43
49
  'createOrderWs': True,
@@ -65,13 +71,14 @@ class binance(ccxt.async_support.binance):
65
71
  'urls': {
66
72
  'test': {
67
73
  'ws': {
68
- 'spot': 'wss://testnet.binance.vision/ws',
69
- 'margin': 'wss://testnet.binance.vision/ws',
74
+ 'spot': 'wss://stream.testnet.binance.vision/ws',
75
+ 'margin': 'wss://stream.testnet.binance.vision/ws',
70
76
  'future': 'wss://fstream.binancefuture.com/ws',
71
77
  'delivery': 'wss://dstream.binancefuture.com/ws',
72
78
  'ws-api': {
73
- 'spot': 'wss://testnet.binance.vision/ws-api/v3',
79
+ 'spot': 'wss://ws-api.testnet.binance.vision/ws-api/v3',
74
80
  'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
81
+ 'delivery': 'wss://testnet.binancefuture.com/ws-dapi/v1',
75
82
  },
76
83
  },
77
84
  },
@@ -84,10 +91,12 @@ class binance(ccxt.async_support.binance):
84
91
  'ws-api': {
85
92
  'spot': 'wss://ws-api.binance.com:443/ws-api/v3',
86
93
  'future': 'wss://ws-fapi.binance.com/ws-fapi/v1',
94
+ 'delivery': 'wss://ws-dapi.binance.com/ws-dapi/v1',
87
95
  },
88
96
  'papi': 'wss://fstream.binance.com/pm/ws',
89
97
  },
90
98
  },
99
+ 'doc': 'https://developers.binance.com/en',
91
100
  },
92
101
  'streaming': {
93
102
  'keepAlive': 180000,
@@ -132,6 +141,7 @@ class binance(ccxt.async_support.binance):
132
141
  },
133
142
  'watchOrderBook': {
134
143
  'maxRetries': 3,
144
+ 'checksum': True,
135
145
  },
136
146
  'watchBalance': {
137
147
  'fetchBalanceSnapshot': False, # or True
@@ -152,6 +162,7 @@ class binance(ccxt.async_support.binance):
152
162
  'tickerChannelsMap': {
153
163
  '24hrTicker': 'ticker',
154
164
  '24hrMiniTicker': 'miniTicker',
165
+ 'markPriceUpdate': 'markPrice',
155
166
  # rolling window tickers
156
167
  '1hTicker': 'ticker_1h',
157
168
  '4hTicker': 'ticker_4h',
@@ -159,7 +170,7 @@ class binance(ccxt.async_support.binance):
159
170
  'bookTicker': 'bookTicker',
160
171
  },
161
172
  },
162
- })
173
+ }
163
174
 
164
175
  def request_id(self, url):
165
176
  options = self.safe_dict(self.options, 'requestId', self.create_safe_dictionary())
@@ -194,22 +205,26 @@ class binance(ccxt.async_support.binance):
194
205
  async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
195
206
  """
196
207
  watch the public liquidations of a trading pair
197
- :see: https://binance-docs.github.io/apidocs/futures/en/#liquidation-order-streams
198
- :see: https://binance-docs.github.io/apidocs/delivery/en/#liquidation-order-streams
208
+
209
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Liquidation-Order-Streams
210
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Liquidation-Order-Streams
211
+
199
212
  :param str symbol: unified CCXT market symbol
200
213
  :param int [since]: the earliest time in ms to fetch liquidations for
201
214
  :param int [limit]: the maximum number of liquidation structures to retrieve
202
215
  :param dict [params]: exchange specific parameters for the bitmex api endpoint
203
216
  :returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
204
217
  """
205
- return self.watch_liquidations_for_symbols([symbol], since, limit, params)
218
+ return await self.watch_liquidations_for_symbols([symbol], since, limit, params)
206
219
 
207
- async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
220
+ async def watch_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
208
221
  """
209
222
  watch the public liquidations of a trading pair
210
- :see: https://binance-docs.github.io/apidocs/futures/en/#all-market-liquidation-order-streams
211
- :see: https://binance-docs.github.io/apidocs/delivery/en/#all-market-liquidation-order-streams
212
- :param str symbol: unified CCXT market symbol
223
+
224
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Liquidation-Order-Streams
225
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Market-Liquidation-Order-Streams
226
+
227
+ :param str[] symbols: list of unified market symbols
213
228
  :param int [since]: the earliest time in ms to fetch liquidations for
214
229
  :param int [limit]: the maximum number of liquidation structures to retrieve
215
230
  :param dict [params]: exchange specific parameters for the bitmex api endpoint
@@ -226,14 +241,14 @@ class binance(ccxt.async_support.binance):
226
241
  else:
227
242
  for i in range(0, len(symbols)):
228
243
  market = self.market(symbols[i])
229
- subscriptionHashes.append(market['id'] + '@forceOrder')
244
+ subscriptionHashes.append(market['lowercaseId'] + '@forceOrder')
230
245
  messageHashes.append('liquidations::' + symbols[i])
231
246
  streamHash += '::' + ','.join(symbols)
232
247
  firstMarket = self.get_market_from_symbols(symbols)
233
248
  type = None
234
249
  type, params = self.handle_market_type_and_params('watchLiquidationsForSymbols', firstMarket, params)
235
250
  if type == 'spot':
236
- raise BadRequest(self.id + 'watchLiquidationsForSymbols is not supported for swap symbols')
251
+ raise BadRequest(self.id + ' watchLiquidationsForSymbols is not supported for spot symbols')
237
252
  subType = None
238
253
  subType, params = self.handle_sub_type_and_params('watchLiquidationsForSymbols', firstMarket, params)
239
254
  if self.isLinear(type, subType):
@@ -394,6 +409,7 @@ class binance(ccxt.async_support.binance):
394
409
  'contracts': self.safe_number(liquidation, 'l'),
395
410
  'contractSize': self.safe_number(market, 'contractSize'),
396
411
  'price': self.safe_number(liquidation, 'ap'),
412
+ 'side': self.safe_string_lower(liquidation, 'S'),
397
413
  'baseValue': None,
398
414
  'quoteValue': None,
399
415
  'timestamp': timestamp,
@@ -403,8 +419,10 @@ class binance(ccxt.async_support.binance):
403
419
  async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
404
420
  """
405
421
  watch the private liquidations of a trading pair
406
- :see: https://binance-docs.github.io/apidocs/futures/en/#event-order-update
407
- :see: https://binance-docs.github.io/apidocs/delivery/en/#event-order-update
422
+
423
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Order-Update
424
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/user-data-streams/Event-Order-Update
425
+
408
426
  :param str symbol: unified CCXT market symbol
409
427
  :param int [since]: the earliest time in ms to fetch liquidations for
410
428
  :param int [limit]: the maximum number of liquidation structures to retrieve
@@ -416,9 +434,11 @@ class binance(ccxt.async_support.binance):
416
434
  async def watch_my_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
417
435
  """
418
436
  watch the private liquidations of a trading pair
419
- :see: https://binance-docs.github.io/apidocs/futures/en/#event-order-update
420
- :see: https://binance-docs.github.io/apidocs/delivery/en/#event-order-update
421
- :param str symbol: unified CCXT market symbol
437
+
438
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Order-Update
439
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/user-data-streams/Event-Order-Update
440
+
441
+ :param str[] symbols: list of unified market symbols
422
442
  :param int [since]: the earliest time in ms to fetch liquidations for
423
443
  :param int [limit]: the maximum number of liquidation structures to retrieve
424
444
  :param dict [params]: exchange specific parameters for the bitmex api endpoint
@@ -512,6 +532,14 @@ class binance(ccxt.async_support.binance):
512
532
  async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
513
533
  """
514
534
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
535
+
536
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#partial-book-depth-streams
537
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#diff-depth-stream
538
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
539
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
540
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
541
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
542
+
515
543
  :param str symbol: unified symbol of the market to fetch the order book for
516
544
  :param int [limit]: the maximum amount of order book entries to return
517
545
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -559,6 +587,14 @@ class binance(ccxt.async_support.binance):
559
587
  async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
560
588
  """
561
589
  watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
590
+
591
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#partial-book-depth-streams
592
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#diff-depth-stream
593
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
594
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
595
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
596
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
597
+
562
598
  :param str[] symbols: unified array of symbols
563
599
  :param int [limit]: the maximum amount of order book entries to return
564
600
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -583,9 +619,9 @@ class binance(ccxt.async_support.binance):
583
619
  for i in range(0, len(symbols)):
584
620
  symbol = symbols[i]
585
621
  market = self.market(symbol)
586
- messageHash = market['lowercaseId'] + '@' + name
587
- messageHashes.append(messageHash)
588
- symbolHash = messageHash + '@' + watchOrderBookRate + 'ms'
622
+ messageHashes.append('orderbook::' + symbol)
623
+ subscriptionHash = market['lowercaseId'] + '@' + name
624
+ symbolHash = subscriptionHash + '@' + watchOrderBookRate + 'ms'
589
625
  subParams.append(symbolHash)
590
626
  messageHashesLength = len(messageHashes)
591
627
  url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, messageHashesLength)
@@ -604,14 +640,88 @@ class binance(ccxt.async_support.binance):
604
640
  'type': type,
605
641
  'params': params,
606
642
  }
607
- message = self.extend(request, params)
608
- orderbook = await self.watch_multiple(url, messageHashes, message, messageHashes, subscription)
643
+ orderbook = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscription)
609
644
  return orderbook.limit()
610
645
 
646
+ async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}) -> Any:
647
+ """
648
+ unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
649
+
650
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#partial-book-depth-streams
651
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#diff-depth-stream
652
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
653
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
654
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
655
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
656
+
657
+ :param str[] symbols: unified array of symbols
658
+ :param dict [params]: extra parameters specific to the exchange API endpoint
659
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
660
+ """
661
+ await self.load_markets()
662
+ symbols = self.market_symbols(symbols, None, False, True, True)
663
+ firstMarket = self.market(symbols[0])
664
+ type = firstMarket['type']
665
+ if firstMarket['contract']:
666
+ type = 'future' if firstMarket['linear'] else 'delivery'
667
+ name = 'depth'
668
+ streamHash = 'multipleOrderbook'
669
+ if symbols is not None:
670
+ streamHash += '::' + ','.join(symbols)
671
+ watchOrderBookRate = self.safe_string(self.options, 'watchOrderBookRate', '100')
672
+ subParams = []
673
+ subMessageHashes = []
674
+ messageHashes = []
675
+ for i in range(0, len(symbols)):
676
+ symbol = symbols[i]
677
+ market = self.market(symbol)
678
+ subMessageHashes.append('orderbook::' + symbol)
679
+ messageHashes.append('unsubscribe:orderbook:' + symbol)
680
+ subscriptionHash = market['lowercaseId'] + '@' + name
681
+ symbolHash = subscriptionHash + '@' + watchOrderBookRate + 'ms'
682
+ subParams.append(symbolHash)
683
+ messageHashesLength = len(subMessageHashes)
684
+ url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, messageHashesLength)
685
+ requestId = self.request_id(url)
686
+ request: dict = {
687
+ 'method': 'UNSUBSCRIBE',
688
+ 'params': subParams,
689
+ 'id': requestId,
690
+ }
691
+ subscription: dict = {
692
+ 'unsubscribe': True,
693
+ 'id': str(requestId),
694
+ 'symbols': symbols,
695
+ 'subMessageHashes': subMessageHashes,
696
+ 'messageHashes': messageHashes,
697
+ 'topic': 'orderbook',
698
+ }
699
+ return await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscription)
700
+
701
+ async def un_watch_order_book(self, symbol: str, params={}) -> Any:
702
+ """
703
+ unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
704
+
705
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#partial-book-depth-streams
706
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#diff-depth-stream
707
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
708
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
709
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams
710
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams
711
+
712
+ :param str symbol: unified array of symbols
713
+ :param dict [params]: extra parameters specific to the exchange API endpoint
714
+ :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
715
+ """
716
+ return await self.un_watch_order_book_for_symbols([symbol], params)
717
+
611
718
  async def fetch_order_book_ws(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
612
719
  """
613
720
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
614
- :see: https://binance-docs.github.io/apidocs/futures/en/#order-book-2
721
+
722
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#order-book
723
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/websocket-api/Order-Book
724
+
615
725
  :param str symbol: unified symbol of the market to fetch the order book for
616
726
  :param int [limit]: the maximum amount of order book entries to return
617
727
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -678,10 +788,8 @@ class binance(ccxt.async_support.binance):
678
788
  client.resolve(orderbook, messageHash)
679
789
 
680
790
  async def fetch_order_book_snapshot(self, client, message, subscription):
681
- name = self.safe_string(subscription, 'name')
682
791
  symbol = self.safe_string(subscription, 'symbol')
683
- market = self.market(symbol)
684
- messageHash = market['lowercaseId'] + '@' + name
792
+ messageHash = 'orderbook::' + symbol
685
793
  try:
686
794
  defaultLimit = self.safe_integer(self.options, 'watchOrderBookLimit', 1000)
687
795
  type = self.safe_value(subscription, 'type')
@@ -698,6 +806,7 @@ class binance(ccxt.async_support.binance):
698
806
  orderbook.reset(snapshot)
699
807
  # unroll the accumulated deltas
700
808
  messages = orderbook.cache
809
+ orderbook.cache = []
701
810
  for i in range(0, len(messages)):
702
811
  messageItem = messages[i]
703
812
  U = self.safe_integer(messageItem, 'U')
@@ -761,15 +870,12 @@ class binance(ccxt.async_support.binance):
761
870
  # ]
762
871
  # }
763
872
  #
764
- isTestnetSpot = client.url.find('testnet') > 0
765
- isSpotMainNet = client.url.find('/stream.binance.') > 0
766
- isSpot = isTestnetSpot or isSpotMainNet
767
- marketType = 'spot' if isSpot else 'contract'
873
+ isSpot = (client.url.find('/stream') > -1)
874
+ marketType = 'spot' if (isSpot) else 'contract'
768
875
  marketId = self.safe_string(message, 's')
769
876
  market = self.safe_market(marketId, None, None, marketType)
770
877
  symbol = market['symbol']
771
- name = 'depth'
772
- messageHash = market['lowercaseId'] + '@' + name
878
+ messageHash = 'orderbook::' + symbol
773
879
  if not (symbol in self.orderbooks):
774
880
  #
775
881
  # https://github.com/ccxt/ccxt/issues/6672
@@ -807,10 +913,10 @@ class binance(ccxt.async_support.binance):
807
913
  if nonce < orderbook['nonce']:
808
914
  client.resolve(orderbook, messageHash)
809
915
  else:
810
- checksum = self.safe_bool(self.options, 'checksum', True)
916
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
811
917
  if checksum:
812
918
  # todo: client.reject from handleOrderBookMessage properly
813
- raise InvalidNonce(self.id + ' handleOrderBook received an out-of-order nonce')
919
+ raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
814
920
  else:
815
921
  # future
816
922
  # 4. Drop any event where u is < lastUpdateId in the snapshot
@@ -822,10 +928,10 @@ class binance(ccxt.async_support.binance):
822
928
  if nonce <= orderbook['nonce']:
823
929
  client.resolve(orderbook, messageHash)
824
930
  else:
825
- checksum = self.safe_bool(self.options, 'checksum', True)
931
+ checksum = self.handle_option('watchOrderBook', 'checksum', True)
826
932
  if checksum:
827
933
  # todo: client.reject from handleOrderBookMessage properly
828
- raise InvalidNonce(self.id + ' handleOrderBook received an out-of-order nonce')
934
+ raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
829
935
  except Exception as e:
830
936
  del self.orderbooks[symbol]
831
937
  del client.subscriptions[messageHash]
@@ -860,15 +966,34 @@ class binance(ccxt.async_support.binance):
860
966
  method = self.safe_value(subscription, 'method')
861
967
  if method is not None:
862
968
  method(client, message, subscription)
969
+ isUnSubMessage = self.safe_bool(subscription, 'unsubscribe', False)
970
+ if isUnSubMessage:
971
+ self.handle_un_subscription(client, subscription)
863
972
  return message
864
973
 
974
+ def handle_un_subscription(self, client: Client, subscription: dict):
975
+ messageHashes = self.safe_list(subscription, 'messageHashes', [])
976
+ subMessageHashes = self.safe_list(subscription, 'subMessageHashes', [])
977
+ for j in range(0, len(messageHashes)):
978
+ unsubHash = messageHashes[j]
979
+ subHash = subMessageHashes[j]
980
+ self.clean_unsubscription(client, subHash, unsubHash)
981
+ self.clean_cache(subscription)
982
+
865
983
  async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
866
984
  """
867
985
  get the list of most recent trades for a list of symbols
986
+
987
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#aggregate-trades
988
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#recent-trades
989
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
990
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
991
+
868
992
  :param str[] symbols: unified symbol of the market to fetch trades for
869
993
  :param int [since]: timestamp in ms of the earliest trade to fetch
870
994
  :param int [limit]: the maximum amount of trades to fetch
871
995
  :param dict [params]: extra parameters specific to the exchange API endpoint
996
+ :param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
872
997
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
873
998
  """
874
999
  await self.load_markets()
@@ -879,18 +1004,21 @@ class binance(ccxt.async_support.binance):
879
1004
  if symbolsLength > 200:
880
1005
  raise BadRequest(self.id + ' watchTradesForSymbols() accepts 200 symbols at most. To watch more symbols call watchTradesForSymbols() multiple times')
881
1006
  streamHash += '::' + ','.join(symbols)
882
- options = self.safe_value(self.options, 'watchTradesForSymbols', {})
883
- name = self.safe_string(options, 'name', 'trade')
1007
+ name = None
1008
+ name, params = self.handle_option_and_params(params, 'watchTradesForSymbols', 'name', 'trade')
1009
+ params = self.omit(params, 'callerMethodName')
884
1010
  firstMarket = self.market(symbols[0])
885
1011
  type = firstMarket['type']
886
1012
  if firstMarket['contract']:
887
1013
  type = 'future' if firstMarket['linear'] else 'delivery'
1014
+ messageHashes = []
888
1015
  subParams = []
889
1016
  for i in range(0, len(symbols)):
890
1017
  symbol = symbols[i]
891
1018
  market = self.market(symbol)
892
- currentMessageHash = market['lowercaseId'] + '@' + name
893
- subParams.append(currentMessageHash)
1019
+ messageHashes.append('trade::' + symbol)
1020
+ rawHash = market['lowercaseId'] + '@' + name
1021
+ subParams.append(rawHash)
894
1022
  query = self.omit(params, 'type')
895
1023
  subParamsLength = len(subParams)
896
1024
  url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, subParamsLength)
@@ -903,22 +1031,105 @@ class binance(ccxt.async_support.binance):
903
1031
  subscribe: dict = {
904
1032
  'id': requestId,
905
1033
  }
906
- trades = await self.watch_multiple(url, subParams, self.extend(request, query), subParams, subscribe)
1034
+ trades = await self.watch_multiple(url, messageHashes, self.extend(request, query), messageHashes, subscribe)
907
1035
  if self.newUpdates:
908
1036
  first = self.safe_value(trades, 0)
909
1037
  tradeSymbol = self.safe_string(first, 'symbol')
910
1038
  limit = trades.getLimit(tradeSymbol, limit)
911
1039
  return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
912
1040
 
1041
+ async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
1042
+ """
1043
+ unsubscribes from the trades channel
1044
+
1045
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#aggregate-trades
1046
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#recent-trades
1047
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
1048
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
1049
+
1050
+ :param str[] symbols: unified symbol of the market to fetch trades for
1051
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1052
+ :param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
1053
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1054
+ """
1055
+ await self.load_markets()
1056
+ symbols = self.market_symbols(symbols, None, False, True, True)
1057
+ streamHash = 'multipleTrades'
1058
+ if symbols is not None:
1059
+ symbolsLength = len(symbols)
1060
+ if symbolsLength > 200:
1061
+ raise BadRequest(self.id + ' watchTradesForSymbols() accepts 200 symbols at most. To watch more symbols call watchTradesForSymbols() multiple times')
1062
+ streamHash += '::' + ','.join(symbols)
1063
+ name = None
1064
+ name, params = self.handle_option_and_params(params, 'watchTradesForSymbols', 'name', 'trade')
1065
+ params = self.omit(params, 'callerMethodName')
1066
+ firstMarket = self.market(symbols[0])
1067
+ type = firstMarket['type']
1068
+ if firstMarket['contract']:
1069
+ type = 'future' if firstMarket['linear'] else 'delivery'
1070
+ subMessageHashes = []
1071
+ subParams = []
1072
+ messageHashes = []
1073
+ for i in range(0, len(symbols)):
1074
+ symbol = symbols[i]
1075
+ market = self.market(symbol)
1076
+ subMessageHashes.append('trade::' + symbol)
1077
+ messageHashes.append('unsubscribe:trade:' + symbol)
1078
+ rawHash = market['lowercaseId'] + '@' + name
1079
+ subParams.append(rawHash)
1080
+ query = self.omit(params, 'type')
1081
+ subParamsLength = len(subParams)
1082
+ url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, subParamsLength)
1083
+ requestId = self.request_id(url)
1084
+ request: dict = {
1085
+ 'method': 'UNSUBSCRIBE',
1086
+ 'params': subParams,
1087
+ 'id': requestId,
1088
+ }
1089
+ subscription: dict = {
1090
+ 'unsubscribe': True,
1091
+ 'id': str(requestId),
1092
+ 'subMessageHashes': subMessageHashes,
1093
+ 'messageHashes': messageHashes,
1094
+ 'symbols': symbols,
1095
+ 'topic': 'trades',
1096
+ }
1097
+ return await self.watch_multiple(url, messageHashes, self.extend(request, query), messageHashes, subscription)
1098
+
1099
+ async def un_watch_trades(self, symbol: str, params={}) -> Any:
1100
+ """
1101
+ unsubscribes from the trades channel
1102
+
1103
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#aggregate-trades
1104
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#recent-trades
1105
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
1106
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
1107
+
1108
+ :param str symbol: unified symbol of the market to fetch trades for
1109
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1110
+ :param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
1111
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
1112
+ """
1113
+ await self.load_markets()
1114
+ return await self.un_watch_trades_for_symbols([symbol], params)
1115
+
913
1116
  async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
914
1117
  """
915
1118
  get the list of most recent trades for a particular symbol
1119
+
1120
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#aggregate-trades
1121
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#recent-trades
1122
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
1123
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Aggregate-Trade-Streams
1124
+
916
1125
  :param str symbol: unified symbol of the market to fetch trades for
917
1126
  :param int [since]: timestamp in ms of the earliest trade to fetch
918
1127
  :param int [limit]: the maximum amount of trades to fetch
919
1128
  :param dict [params]: extra parameters specific to the exchange API endpoint
1129
+ :param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
920
1130
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
921
1131
  """
1132
+ params['callerMethodName'] = 'watchTrades'
922
1133
  return await self.watch_trades_for_symbols([symbol], since, limit, params)
923
1134
 
924
1135
  def parse_ws_trade(self, trade, market=None) -> Trade:
@@ -1079,14 +1290,12 @@ class binance(ccxt.async_support.binance):
1079
1290
  def handle_trade(self, client: Client, message):
1080
1291
  # the trade streams push raw trade information in real-time
1081
1292
  # each trade has a unique buyer and seller
1082
- isSpot = ((client.url.find('wss://stream.binance.com') > -1) or (client.url.find('/testnet.binance') > -1))
1293
+ isSpot = (client.url.find('/stream') > -1)
1083
1294
  marketType = 'spot' if (isSpot) else 'contract'
1084
1295
  marketId = self.safe_string(message, 's')
1085
1296
  market = self.safe_market(marketId, None, None, marketType)
1086
1297
  symbol = market['symbol']
1087
- lowerCaseId = self.safe_string_lower(message, 's')
1088
- event = self.safe_string(message, 'e')
1089
- messageHash = lowerCaseId + '@' + event
1298
+ messageHash = 'trade::' + symbol
1090
1299
  trade = self.parse_ws_trade(message, market)
1091
1300
  tradesArray = self.safe_value(self.trades, symbol)
1092
1301
  if tradesArray is None:
@@ -1099,44 +1308,171 @@ class binance(ccxt.async_support.binance):
1099
1308
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1100
1309
  """
1101
1310
  watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1311
+
1312
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#klines
1313
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1314
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1315
+
1102
1316
  :param str symbol: unified symbol of the market to fetch OHLCV data for
1103
1317
  :param str timeframe: the length of time each candle represents
1104
1318
  :param int [since]: timestamp in ms of the earliest candle to fetch
1105
1319
  :param int [limit]: the maximum amount of candles to fetch
1106
1320
  :param dict [params]: extra parameters specific to the exchange API endpoint
1321
+ :param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1107
1322
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1108
1323
  """
1109
1324
  await self.load_markets()
1110
1325
  market = self.market(symbol)
1111
- marketId = market['lowercaseId']
1112
- interval = self.safe_string(self.timeframes, timeframe, timeframe)
1113
- options = self.safe_value(self.options, 'watchOHLCV', {})
1114
- nameOption = self.safe_string(options, 'name', 'kline')
1115
- name = self.safe_string(params, 'name', nameOption)
1116
- if name == 'indexPriceKline':
1117
- marketId = marketId.replace('_perp', '')
1118
- # weird behavior for index price kline we can't use the perp suffix
1119
- params = self.omit(params, 'name')
1120
- messageHash = marketId + '@' + name + '_' + interval
1121
- type = market['type']
1122
- if market['contract']:
1123
- type = 'future' if market['linear'] else 'delivery'
1124
- url = self.urls['api']['ws'][type] + '/' + self.stream(type, messageHash)
1326
+ symbol = market['symbol']
1327
+ params['callerMethodName'] = 'watchOHLCV'
1328
+ result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
1329
+ return result[symbol][timeframe]
1330
+
1331
+ async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
1332
+ """
1333
+ watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1334
+
1335
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#klines
1336
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1337
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1338
+
1339
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1340
+ :param int [since]: timestamp in ms of the earliest candle to fetch
1341
+ :param int [limit]: the maximum amount of candles to fetch
1342
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1343
+ :param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1344
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1345
+ """
1346
+ await self.load_markets()
1347
+ klineType = None
1348
+ klineType, params = self.handle_param_string_2(params, 'channel', 'name', 'kline')
1349
+ symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
1350
+ marketSymbols = self.market_symbols(symbols, None, False, False, True)
1351
+ firstMarket = self.market(marketSymbols[0])
1352
+ type = firstMarket['type']
1353
+ if firstMarket['contract']:
1354
+ type = 'future' if firstMarket['linear'] else 'delivery'
1355
+ isSpot = (type == 'spot')
1356
+ timezone = None
1357
+ timezone, params = self.handle_param_string(params, 'timezone', None)
1358
+ isUtc8 = (timezone is not None) and ((timezone == '+08:00') or Precise.string_eq(timezone, '8'))
1359
+ rawHashes = []
1360
+ messageHashes = []
1361
+ for i in range(0, len(symbolsAndTimeframes)):
1362
+ symAndTf = symbolsAndTimeframes[i]
1363
+ symbolString = symAndTf[0]
1364
+ timeframeString = symAndTf[1]
1365
+ interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
1366
+ market = self.market(symbolString)
1367
+ marketId = market['lowercaseId']
1368
+ if klineType == 'indexPriceKline':
1369
+ # weird behavior for index price kline we can't use the perp suffix
1370
+ marketId = marketId.replace('_perp', '')
1371
+ shouldUseUTC8 = (isUtc8 and isSpot)
1372
+ suffix = '@+08:00'
1373
+ utcSuffix = suffix if shouldUseUTC8 else ''
1374
+ rawHashes.append(marketId + '@' + klineType + '_' + interval + utcSuffix)
1375
+ messageHashes.append('ohlcv::' + market['symbol'] + '::' + timeframeString)
1376
+ url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
1125
1377
  requestId = self.request_id(url)
1126
- request: dict = {
1378
+ request = {
1127
1379
  'method': 'SUBSCRIBE',
1128
- 'params': [
1129
- messageHash,
1130
- ],
1380
+ 'params': rawHashes,
1131
1381
  'id': requestId,
1132
1382
  }
1133
- subscribe: dict = {
1383
+ subscribe = {
1134
1384
  'id': requestId,
1135
1385
  }
1136
- ohlcv = await self.watch(url, messageHash, self.extend(request, params), messageHash, subscribe)
1386
+ params = self.omit(params, 'callerMethodName')
1387
+ symbol, timeframe, candles = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscribe)
1137
1388
  if self.newUpdates:
1138
- limit = ohlcv.getLimit(symbol, limit)
1139
- return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
1389
+ limit = candles.getLimit(symbol, limit)
1390
+ filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
1391
+ return self.create_ohlcv_object(symbol, timeframe, filtered)
1392
+
1393
+ async def un_watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], params={}) -> Any:
1394
+ """
1395
+ unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1396
+
1397
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#klines
1398
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1399
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1400
+
1401
+ :param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1402
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1403
+ :param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1404
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1405
+ """
1406
+ await self.load_markets()
1407
+ klineType = None
1408
+ klineType, params = self.handle_param_string_2(params, 'channel', 'name', 'kline')
1409
+ symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
1410
+ marketSymbols = self.market_symbols(symbols, None, False, False, True)
1411
+ firstMarket = self.market(marketSymbols[0])
1412
+ type = firstMarket['type']
1413
+ if firstMarket['contract']:
1414
+ type = 'future' if firstMarket['linear'] else 'delivery'
1415
+ isSpot = (type == 'spot')
1416
+ timezone = None
1417
+ timezone, params = self.handle_param_string(params, 'timezone', None)
1418
+ isUtc8 = (timezone is not None) and ((timezone == '+08:00') or Precise.string_eq(timezone, '8'))
1419
+ rawHashes = []
1420
+ subMessageHashes = []
1421
+ messageHashes = []
1422
+ for i in range(0, len(symbolsAndTimeframes)):
1423
+ symAndTf = symbolsAndTimeframes[i]
1424
+ symbolString = symAndTf[0]
1425
+ timeframeString = symAndTf[1]
1426
+ interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
1427
+ market = self.market(symbolString)
1428
+ marketId = market['lowercaseId']
1429
+ if klineType == 'indexPriceKline':
1430
+ # weird behavior for index price kline we can't use the perp suffix
1431
+ marketId = marketId.replace('_perp', '')
1432
+ shouldUseUTC8 = (isUtc8 and isSpot)
1433
+ suffix = '@+08:00'
1434
+ utcSuffix = suffix if shouldUseUTC8 else ''
1435
+ rawHashes.append(marketId + '@' + klineType + '_' + interval + utcSuffix)
1436
+ subMessageHashes.append('ohlcv::' + market['symbol'] + '::' + timeframeString)
1437
+ messageHashes.append('unsubscribe::ohlcv::' + market['symbol'] + '::' + timeframeString)
1438
+ url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
1439
+ requestId = self.request_id(url)
1440
+ request = {
1441
+ 'method': 'UNSUBSCRIBE',
1442
+ 'params': rawHashes,
1443
+ 'id': requestId,
1444
+ }
1445
+ subscribe = {
1446
+ 'unsubscribe': True,
1447
+ 'id': str(requestId),
1448
+ 'symbols': symbols,
1449
+ 'symbolsAndTimeframes': symbolsAndTimeframes,
1450
+ 'subMessageHashes': subMessageHashes,
1451
+ 'messageHashes': messageHashes,
1452
+ 'topic': 'ohlcv',
1453
+ }
1454
+ params = self.omit(params, 'callerMethodName')
1455
+ return await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscribe)
1456
+
1457
+ async def un_watch_ohlcv(self, symbol: str, timeframe='1m', params={}) -> Any:
1458
+ """
1459
+ unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1460
+
1461
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#klines
1462
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1463
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Kline-Candlestick-Streams
1464
+
1465
+ :param str symbol: unified symbol of the market to fetch OHLCV data for
1466
+ :param str timeframe: the length of time each candle represents
1467
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1468
+ :param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
1469
+ :returns int[][]: A list of candles ordered, open, high, low, close, volume
1470
+ """
1471
+ await self.load_markets()
1472
+ market = self.market(symbol)
1473
+ symbol = market['symbol']
1474
+ params['callerMethodName'] = 'watchOHLCV'
1475
+ return await self.un_watch_ohlcv_for_symbols([[symbol, timeframe]], params)
1140
1476
 
1141
1477
  def handle_ohlcv(self, client: Client, message):
1142
1478
  #
@@ -1176,11 +1512,9 @@ class binance(ccxt.async_support.binance):
1176
1512
  if event == 'indexPriceKline':
1177
1513
  # indexPriceKline doesn't have the _PERP suffix
1178
1514
  marketId = self.safe_string(message, 'ps')
1179
- lowercaseMarketId = marketId.lower()
1180
1515
  interval = self.safe_string(kline, 'i')
1181
1516
  # use a reverse lookup in a static map instead
1182
- timeframe = self.find_timeframe(interval)
1183
- messageHash = lowercaseMarketId + '@' + event + '_' + interval
1517
+ unifiedTimeframe = self.find_timeframe(interval)
1184
1518
  parsed = [
1185
1519
  self.safe_integer(kline, 't'),
1186
1520
  self.safe_float(kline, 'o'),
@@ -1189,22 +1523,23 @@ class binance(ccxt.async_support.binance):
1189
1523
  self.safe_float(kline, 'c'),
1190
1524
  self.safe_float(kline, 'v'),
1191
1525
  ]
1192
- isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
1526
+ isSpot = (client.url.find('/stream') > -1)
1193
1527
  marketType = 'spot' if (isSpot) else 'contract'
1194
1528
  symbol = self.safe_symbol(marketId, None, None, marketType)
1529
+ messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe
1195
1530
  self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
1196
- stored = self.safe_value(self.ohlcvs[symbol], timeframe)
1531
+ stored = self.safe_value(self.ohlcvs[symbol], unifiedTimeframe)
1197
1532
  if stored is None:
1198
1533
  limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
1199
1534
  stored = ArrayCacheByTimestamp(limit)
1200
- self.ohlcvs[symbol][timeframe] = stored
1535
+ self.ohlcvs[symbol][unifiedTimeframe] = stored
1201
1536
  stored.append(parsed)
1202
- client.resolve(stored, messageHash)
1537
+ resolveData = [symbol, unifiedTimeframe, stored]
1538
+ client.resolve(resolveData, messageHash)
1203
1539
 
1204
1540
  async def fetch_ticker_ws(self, symbol: str, params={}) -> Ticker:
1205
1541
  """
1206
1542
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1207
- :see: https://binance-docs.github.io/apidocs/voptions/en/#24hr-ticker-price-change-statistics
1208
1543
  :param str symbol: unified symbol of the market to fetch the ticker for
1209
1544
  :param dict [params]: extra parameters specific to the exchange API endpoint
1210
1545
  :param str [params.method]: method to use can be ticker.price or ticker.book
@@ -1241,16 +1576,18 @@ class binance(ccxt.async_support.binance):
1241
1576
 
1242
1577
  async def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
1243
1578
  """
1244
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#klines
1245
1579
  query historical candlestick data containing the open, high, low, and close price, and the volume of a market
1580
+
1581
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#klines
1582
+
1246
1583
  :param str symbol: unified symbol of the market to query OHLCV data for
1247
1584
  :param str timeframe: the length of time each candle represents
1248
1585
  :param int since: timestamp in ms of the earliest candle to fetch
1249
1586
  :param int limit: the maximum amount of candles to fetch
1250
1587
  :param dict params: extra parameters specific to the exchange API endpoint
1251
1588
  :param int params['until']: timestamp in ms of the earliest candle to fetch
1252
- *
1253
- * EXCHANGE SPECIFIC PARAMETERS
1589
+
1590
+ EXCHANGE SPECIFIC PARAMETERS
1254
1591
  :param str params['timeZone']: default=0(UTC)
1255
1592
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1256
1593
  """
@@ -1328,6 +1665,14 @@ class binance(ccxt.async_support.binance):
1328
1665
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
1329
1666
  """
1330
1667
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1668
+
1669
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-mini-ticker-stream
1670
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#all-market-mini-tickers-stream
1671
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1672
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1673
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1674
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1675
+
1331
1676
  :param str symbol: unified symbol of the market to fetch the ticker for
1332
1677
  :param dict [params]: extra parameters specific to the exchange API endpoint
1333
1678
  :param str [params.name]: stream to use can be ticker or miniTicker
@@ -1338,9 +1683,54 @@ class binance(ccxt.async_support.binance):
1338
1683
  tickers = await self.watch_tickers([symbol], self.extend(params, {'callerMethodName': 'watchTicker'}))
1339
1684
  return tickers[symbol]
1340
1685
 
1686
+ async def watch_mark_price(self, symbol: str, params={}) -> Ticker:
1687
+ """
1688
+ watches a mark price for a specific market
1689
+
1690
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream
1691
+
1692
+ :param str symbol: unified symbol of the market to fetch the ticker for
1693
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1694
+ :param boolean [params.use1sFreq]: *default is True* if set to True, the mark price will be updated every second, otherwise every 3 seconds
1695
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1696
+ """
1697
+ await self.load_markets()
1698
+ symbol = self.symbol(symbol)
1699
+ tickers = await self.watch_mark_prices([symbol], self.extend(params, {'callerMethodName': 'watchMarkPrice'}))
1700
+ return tickers[symbol]
1701
+
1702
+ async def watch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
1703
+ """
1704
+ watches the mark price for all markets
1705
+
1706
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream-for-All-market
1707
+
1708
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
1709
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1710
+ :param boolean [params.use1sFreq]: *default is True* if set to True, the mark price will be updated every second, otherwise every 3 seconds
1711
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1712
+ """
1713
+ channelName = None
1714
+ # for now watchmarkPrice uses the same messageHash
1715
+ # so it's impossible to watch both at the same time
1716
+ # refactor self to use different messageHashes
1717
+ channelName, params = self.handle_option_and_params(params, 'watchMarkPrices', 'name', 'markPrice')
1718
+ newTickers = await self.watch_multi_ticker_helper('watchMarkPrices', channelName, symbols, params)
1719
+ if self.newUpdates:
1720
+ return newTickers
1721
+ return self.filter_by_array(self.tickers, 'symbol', symbols)
1722
+
1341
1723
  async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1342
1724
  """
1343
1725
  watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
1726
+
1727
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-mini-ticker-stream
1728
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#all-market-mini-tickers-stream
1729
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1730
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1731
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1732
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1733
+
1344
1734
  :param str[] symbols: unified symbol of the market to fetch the ticker for
1345
1735
  :param dict [params]: extra parameters specific to the exchange API endpoint
1346
1736
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1354,30 +1744,134 @@ class binance(ccxt.async_support.binance):
1354
1744
  return newTickers
1355
1745
  return self.filter_by_array(self.tickers, 'symbol', symbols)
1356
1746
 
1747
+ async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
1748
+ """
1749
+ unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
1750
+
1751
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-mini-ticker-stream
1752
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#all-market-mini-tickers-stream
1753
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1754
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1755
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1756
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1757
+
1758
+ :param str[] symbols: unified symbol of the market to fetch the ticker for
1759
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1760
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1761
+ """
1762
+ channelName = None
1763
+ channelName, params = self.handle_option_and_params(params, 'watchTickers', 'name', 'ticker')
1764
+ if channelName == 'bookTicker':
1765
+ raise BadRequest(self.id + ' deprecation notice - to subscribe for bids-asks, use watch_bids_asks() method instead')
1766
+ await self.load_markets()
1767
+ methodName = 'watchTickers'
1768
+ symbols = self.market_symbols(symbols, None, True, False, True)
1769
+ firstMarket = None
1770
+ marketType = None
1771
+ symbolsDefined = (symbols is not None)
1772
+ if symbolsDefined:
1773
+ firstMarket = self.market(symbols[0])
1774
+ marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params)
1775
+ subType = None
1776
+ subType, params = self.handle_sub_type_and_params(methodName, firstMarket, params)
1777
+ rawMarketType = None
1778
+ if self.isLinear(marketType, subType):
1779
+ rawMarketType = 'future'
1780
+ elif self.isInverse(marketType, subType):
1781
+ rawMarketType = 'delivery'
1782
+ elif marketType == 'spot':
1783
+ rawMarketType = marketType
1784
+ else:
1785
+ raise NotSupported(self.id + ' ' + methodName + '() does not support options markets')
1786
+ isBidAsk = (channelName == 'bookTicker')
1787
+ subscriptionArgs = []
1788
+ subMessageHashes = []
1789
+ messageHashes = []
1790
+ if symbolsDefined:
1791
+ for i in range(0, len(symbols)):
1792
+ symbol = symbols[i]
1793
+ market = self.market(symbol)
1794
+ subscriptionArgs.append(market['lowercaseId'] + '@' + channelName)
1795
+ subMessageHashes.append(self.get_message_hash(channelName, market['symbol'], isBidAsk))
1796
+ messageHashes.append('unsubscribe:ticker:' + symbol)
1797
+ else:
1798
+ if isBidAsk:
1799
+ if marketType == 'spot':
1800
+ raise ArgumentsRequired(self.id + ' ' + methodName + '() requires symbols for self channel for spot markets')
1801
+ subscriptionArgs.append('!' + channelName)
1802
+ else:
1803
+ subscriptionArgs.append('!' + channelName + '@arr')
1804
+ subMessageHashes.append(self.get_message_hash(channelName, None, isBidAsk))
1805
+ messageHashes.append('unsubscribe:ticker')
1806
+ streamHash = channelName
1807
+ if symbolsDefined:
1808
+ streamHash = channelName + '::' + ','.join(symbols)
1809
+ url = self.urls['api']['ws'][rawMarketType] + '/' + self.stream(rawMarketType, streamHash)
1810
+ requestId = self.request_id(url)
1811
+ request: dict = {
1812
+ 'method': 'UNSUBSCRIBE',
1813
+ 'params': subscriptionArgs,
1814
+ 'id': requestId,
1815
+ }
1816
+ subscription: dict = {
1817
+ 'unsubscribe': True,
1818
+ 'id': str(requestId),
1819
+ 'subMessageHashes': subMessageHashes,
1820
+ 'messageHashes': subMessageHashes,
1821
+ 'symbols': symbols,
1822
+ 'topic': 'ticker',
1823
+ }
1824
+ return await self.watch_multiple(url, subMessageHashes, self.extend(request, params), subMessageHashes, subscription)
1825
+
1826
+ async def un_watch_ticker(self, symbol: str, params={}) -> Any:
1827
+ """
1828
+ unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
1829
+
1830
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#individual-symbol-mini-ticker-stream
1831
+ https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams#all-market-mini-tickers-stream
1832
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1833
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1834
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream
1835
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams
1836
+
1837
+ :param str symbol: unified symbol of the market to fetch the ticker for
1838
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1839
+ :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1840
+ """
1841
+ return await self.un_watch_tickers([symbol], params)
1842
+
1357
1843
  async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
1358
1844
  """
1359
- :see: https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-book-ticker-streams
1360
- :see: https://binance-docs.github.io/apidocs/futures/en/#all-book-tickers-stream
1361
- :see: https://binance-docs.github.io/apidocs/delivery/en/#all-book-tickers-stream
1362
1845
  watches best bid & ask for symbols
1846
+
1847
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#symbol-order-book-ticker
1848
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Book-Tickers-Stream
1849
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Book-Tickers-Stream
1850
+
1363
1851
  :param str[] symbols: unified symbol of the market to fetch the ticker for
1364
1852
  :param dict [params]: extra parameters specific to the exchange API endpoint
1365
1853
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
1366
1854
  """
1855
+ await self.load_markets()
1856
+ symbols = self.market_symbols(symbols, None, True, False, True)
1367
1857
  result = await self.watch_multi_ticker_helper('watchBidsAsks', 'bookTicker', symbols, params)
1368
1858
  if self.newUpdates:
1369
1859
  return result
1370
- return self.filter_by_array(self.tickers, 'symbol', symbols)
1860
+ return self.filter_by_array(self.bidsasks, 'symbol', symbols)
1371
1861
 
1372
1862
  async def watch_multi_ticker_helper(self, methodName, channelName: str, symbols: Strings = None, params={}):
1373
1863
  await self.load_markets()
1374
1864
  symbols = self.market_symbols(symbols, None, True, False, True)
1865
+ isBidAsk = (channelName == 'bookTicker')
1866
+ isMarkPrice = (channelName == 'markPrice')
1867
+ use1sFreq = self.safe_bool(params, 'use1sFreq', True)
1375
1868
  firstMarket = None
1376
1869
  marketType = None
1377
1870
  symbolsDefined = (symbols is not None)
1378
1871
  if symbolsDefined:
1379
1872
  firstMarket = self.market(symbols[0])
1380
- marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params)
1873
+ defaultMarket = 'swap' if (isMarkPrice) else None
1874
+ marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params, defaultMarket)
1381
1875
  subType = None
1382
1876
  subType, params = self.handle_sub_type_and_params(methodName, firstMarket, params)
1383
1877
  rawMarketType = None
@@ -1389,20 +1883,24 @@ class binance(ccxt.async_support.binance):
1389
1883
  rawMarketType = marketType
1390
1884
  else:
1391
1885
  raise NotSupported(self.id + ' ' + methodName + '() does not support options markets')
1392
- isBidAsk = (channelName == 'bookTicker')
1393
1886
  subscriptionArgs = []
1394
1887
  messageHashes = []
1888
+ suffix = ''
1889
+ if isMarkPrice:
1890
+ suffix = '@1s' if (use1sFreq) else ''
1395
1891
  if symbolsDefined:
1396
1892
  for i in range(0, len(symbols)):
1397
1893
  symbol = symbols[i]
1398
1894
  market = self.market(symbol)
1399
- subscriptionArgs.append(market['lowercaseId'] + '@' + channelName)
1895
+ subscriptionArgs.append(market['lowercaseId'] + '@' + channelName + suffix)
1400
1896
  messageHashes.append(self.get_message_hash(channelName, market['symbol'], isBidAsk))
1401
1897
  else:
1402
1898
  if isBidAsk:
1403
1899
  if marketType == 'spot':
1404
1900
  raise ArgumentsRequired(self.id + ' ' + methodName + '() requires symbols for self channel for spot markets')
1405
1901
  subscriptionArgs.append('!' + channelName)
1902
+ elif isMarkPrice:
1903
+ subscriptionArgs.append('!' + channelName + '@arr' + suffix)
1406
1904
  else:
1407
1905
  subscriptionArgs.append('!' + channelName + '@arr')
1408
1906
  messageHashes.append(self.get_message_hash(channelName, None, isBidAsk))
@@ -1430,6 +1928,17 @@ class binance(ccxt.async_support.binance):
1430
1928
  return newDict
1431
1929
 
1432
1930
  def parse_ws_ticker(self, message, marketType):
1931
+ # markPrice
1932
+ # {
1933
+ # "e": "markPriceUpdate", # Event type
1934
+ # "E": 1562305380000, # Event time
1935
+ # "s": "BTCUSDT", # Symbol
1936
+ # "p": "11794.15000000", # Mark price
1937
+ # "i": "11784.62659091", # Index price
1938
+ # "P": "11784.25641265", # Estimated Settle Price, only useful in the last hour before the settlement starts
1939
+ # "r": "0.00038167", # Funding rate
1940
+ # "T": 1562306400000 # Next funding time
1941
+ # }
1433
1942
  #
1434
1943
  # ticker
1435
1944
  # {
@@ -1487,9 +1996,21 @@ class binance(ccxt.async_support.binance):
1487
1996
  # "time":1589437530011,
1488
1997
  # }
1489
1998
  #
1999
+ marketId = self.safe_string_2(message, 's', 'symbol')
2000
+ symbol = self.safe_symbol(marketId, None, None, marketType)
1490
2001
  event = self.safe_string(message, 'e', 'bookTicker')
1491
2002
  if event == '24hrTicker':
1492
2003
  event = 'ticker'
2004
+ if event == 'markPriceUpdate':
2005
+ # handle self separately because some fields clash with the ticker fields
2006
+ return self.safe_ticker({
2007
+ 'symbol': symbol,
2008
+ 'timestamp': self.safe_integer(message, 'E'),
2009
+ 'datetime': self.iso8601(self.safe_integer(message, 'E')),
2010
+ 'info': message,
2011
+ 'markPrice': self.safe_string(message, 'p'),
2012
+ 'indexPrice': self.safe_string(message, 'i'),
2013
+ })
1493
2014
  timestamp = None
1494
2015
  if event == 'bookTicker':
1495
2016
  # take the event timestamp, if available, for spot tickers it is not
@@ -1497,8 +2018,6 @@ class binance(ccxt.async_support.binance):
1497
2018
  else:
1498
2019
  # take the timestamp of the closing price for candlestick streams
1499
2020
  timestamp = self.safe_integer_n(message, ['C', 'E', 'time'])
1500
- marketId = self.safe_string_2(message, 's', 'symbol')
1501
- symbol = self.safe_symbol(marketId, None, None, marketType)
1502
2021
  market = self.safe_market(marketId, None, None, marketType)
1503
2022
  last = self.safe_string_2(message, 'c', 'price')
1504
2023
  return self.safe_ticker({
@@ -1604,7 +2123,7 @@ class binance(ccxt.async_support.binance):
1604
2123
  self.handle_tickers_and_bids_asks(client, message, 'tickers')
1605
2124
 
1606
2125
  def handle_tickers_and_bids_asks(self, client: Client, message, methodType):
1607
- isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
2126
+ isSpot = (client.url.find('/stream') > -1)
1608
2127
  marketType = 'spot' if (isSpot) else 'contract'
1609
2128
  isBidAsk = (methodType == 'bidasks')
1610
2129
  channelName = None
@@ -1697,6 +2216,7 @@ class binance(ccxt.async_support.binance):
1697
2216
  response = None
1698
2217
  if isPortfolioMargin:
1699
2218
  response = await self.papiPostListenKey(params)
2219
+ params = self.extend(params, {'portfolioMargin': True})
1700
2220
  elif type == 'future':
1701
2221
  response = await self.fapiPrivatePostListenKey(params)
1702
2222
  elif type == 'delivery':
@@ -1741,6 +2261,7 @@ class binance(ccxt.async_support.binance):
1741
2261
  try:
1742
2262
  if isPortfolioMargin:
1743
2263
  await self.papiPutListenKey(self.extend(request, params))
2264
+ params = self.extend(params, {'portfolioMargin': True})
1744
2265
  elif type == 'future':
1745
2266
  await self.fapiPrivatePutListenKey(self.extend(request, params))
1746
2267
  elif type == 'delivery':
@@ -1812,19 +2333,21 @@ class binance(ccxt.async_support.binance):
1812
2333
  async def fetch_balance_ws(self, params={}) -> Balances:
1813
2334
  """
1814
2335
  fetch balance and get the amount of funds available for trading or funds locked in orders
1815
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-information-user_data
1816
- :see: https://binance-docs.github.io/apidocs/futures/en/#account-information-user_data
1817
- :see: https://binance-docs.github.io/apidocs/futures/en/#futures-account-balance-user_data
2336
+
2337
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/account/websocket-api/Futures-Account-Balance
2338
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/account-requests#account-information-user_data
2339
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/account/websocket-api
2340
+
1818
2341
  :param dict [params]: extra parameters specific to the exchange API endpoint
1819
2342
  :param str|None [params.type]: 'future', 'delivery', 'savings', 'funding', or 'spot'
1820
2343
  :param str|None [params.marginMode]: 'cross' or 'isolated', for margin trading, uses self.options.defaultMarginMode if not passed, defaults to None/None/None
1821
2344
  :param str[]|None [params.symbols]: unified market symbols, only used in isolated margin mode
1822
- :param str|None [params.method]: method to use. Can be account.balance or account.status
2345
+ :param str|None [params.method]: method to use. Can be account.balance, account.status, v2/account.balance or v2/account.status
1823
2346
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
1824
2347
  """
1825
2348
  await self.load_markets()
1826
2349
  type = self.get_market_type('fetchBalanceWs', None, params)
1827
- if type != 'spot' and type != 'future':
2350
+ if type != 'spot' and type != 'future' and type != 'delivery':
1828
2351
  raise BadRequest(self.id + ' fetchBalanceWs only supports spot or swap markets')
1829
2352
  url = self.urls['api']['ws']['ws-api'][type]
1830
2353
  requestId = self.request_id(url)
@@ -1850,8 +2373,14 @@ class binance(ccxt.async_support.binance):
1850
2373
  #
1851
2374
  #
1852
2375
  messageHash = self.safe_string(message, 'id')
1853
- result = self.safe_dict(message, 'result', {})
1854
- rawBalance = self.safe_list(result, 0, [])
2376
+ rawBalance = None
2377
+ if isinstance(message['result'], list):
2378
+ # account.balance
2379
+ rawBalance = self.safe_list(message, 'result', [])
2380
+ else:
2381
+ # account.status
2382
+ result = self.safe_dict(message, 'result', {})
2383
+ rawBalance = self.safe_list(result, 'assets', [])
1855
2384
  parsedBalances = self.parseBalanceCustom(rawBalance)
1856
2385
  client.resolve(parsedBalances, messageHash)
1857
2386
 
@@ -1909,8 +2438,10 @@ class binance(ccxt.async_support.binance):
1909
2438
 
1910
2439
  async def fetch_position_ws(self, symbol: str, params={}) -> List[Position]:
1911
2440
  """
1912
- :see: https://binance-docs.github.io/apidocs/futures/en/#position-information-user_data
1913
2441
  fetch data on an open position
2442
+
2443
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Position-Information
2444
+
1914
2445
  :param str symbol: unified market symbol of the market the position is held in
1915
2446
  :param dict [params]: extra parameters specific to the exchange API endpoint
1916
2447
  :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
@@ -1920,28 +2451,39 @@ class binance(ccxt.async_support.binance):
1920
2451
  async def fetch_positions_ws(self, symbols: Strings = None, params={}) -> List[Position]:
1921
2452
  """
1922
2453
  fetch all open positions
1923
- :see: https://binance-docs.github.io/apidocs/futures/en/#position-information-user_data
2454
+
2455
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Position-Information
2456
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Position-Information
2457
+
1924
2458
  :param str[] [symbols]: list of unified market symbols
1925
2459
  :param dict [params]: extra parameters specific to the exchange API endpoint
1926
2460
  :param boolean [params.returnRateLimits]: set to True to return rate limit informations, defaults to False.
2461
+ :param str|None [params.method]: method to use. Can be account.position or v2/account.position
1927
2462
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
1928
2463
  """
1929
2464
  await self.load_markets()
1930
- symbols = self.market_symbols(symbols, 'swap', True, True, True)
1931
- url = self.urls['api']['ws']['ws-api']['future']
1932
- requestId = self.request_id(url)
1933
- messageHash = str(requestId)
1934
2465
  payload: dict = {}
2466
+ market = None
2467
+ symbols = self.market_symbols(symbols, 'swap', True, True, True)
1935
2468
  if symbols is not None:
1936
2469
  symbolsLength = len(symbols)
1937
2470
  if symbolsLength == 1:
1938
- payload['symbol'] = self.market_id(symbols[0])
2471
+ market = self.market(symbols[0])
2472
+ payload['symbol'] = market['id']
2473
+ type = self.get_market_type('fetchPositionsWs', market, params)
2474
+ if type != 'future' and type != 'delivery':
2475
+ raise BadRequest(self.id + ' fetchPositionsWs only supports swap markets')
2476
+ url = self.urls['api']['ws']['ws-api'][type]
2477
+ requestId = self.request_id(url)
2478
+ messageHash = str(requestId)
1939
2479
  returnRateLimits = False
1940
2480
  returnRateLimits, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'returnRateLimits', False)
1941
2481
  payload['returnRateLimits'] = returnRateLimits
2482
+ method = None
2483
+ method, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'method', 'account.position')
1942
2484
  message: dict = {
1943
2485
  'id': messageHash,
1944
- 'method': 'account.position',
2486
+ 'method': method,
1945
2487
  'params': self.sign_params(self.extend(payload, params)),
1946
2488
  }
1947
2489
  subscription: dict = {
@@ -2006,13 +2548,13 @@ class binance(ccxt.async_support.binance):
2006
2548
  subType, params = self.handle_sub_type_and_params('watchBalance', None, params)
2007
2549
  isPortfolioMargin = None
2008
2550
  isPortfolioMargin, params = self.handle_option_and_params_2(params, 'watchBalance', 'papi', 'portfolioMargin', False)
2009
- urlType = type
2010
- if isPortfolioMargin:
2011
- urlType = 'papi'
2012
2551
  if self.isLinear(type, subType):
2013
2552
  type = 'future'
2014
2553
  elif self.isInverse(type, subType):
2015
2554
  type = 'delivery'
2555
+ urlType = type
2556
+ if isPortfolioMargin:
2557
+ urlType = 'papi'
2016
2558
  url = self.urls['api']['ws'][urlType] + '/' + self.options[type]['listenKey']
2017
2559
  client = self.client(url)
2018
2560
  self.set_balance_cache(client, type, isPortfolioMargin)
@@ -2138,14 +2680,17 @@ class binance(ccxt.async_support.binance):
2138
2680
 
2139
2681
  async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
2140
2682
  """
2141
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#place-new-order-trade
2142
- :see: https://binance-docs.github.io/apidocs/futures/en/#new-order-trade-2
2143
2683
  create a trade order
2684
+
2685
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#place-new-order-trade
2686
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/New-Order
2687
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api
2688
+
2144
2689
  :param str symbol: unified symbol of the market to create an order in
2145
2690
  :param str type: 'market' or 'limit'
2146
2691
  :param str side: 'buy' or 'sell'
2147
2692
  :param float amount: how much of currency you want to trade in units of base currency
2148
- :param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2693
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2149
2694
  :param dict [params]: extra parameters specific to the exchange API endpoint
2150
2695
  :param boolean params['test']: test order, default False
2151
2696
  :param boolean params['returnRateLimits']: set to True to return rate limit information, default False
@@ -2154,7 +2699,7 @@ class binance(ccxt.async_support.binance):
2154
2699
  await self.load_markets()
2155
2700
  market = self.market(symbol)
2156
2701
  marketType = self.get_market_type('createOrderWs', market, params)
2157
- if marketType != 'spot' and marketType != 'future':
2702
+ if marketType != 'spot' and marketType != 'future' and marketType != 'delivery':
2158
2703
  raise BadRequest(self.id + ' createOrderWs only supports spot or swap markets')
2159
2704
  url = self.urls['api']['ws']['ws-api'][marketType]
2160
2705
  requestId = self.request_id(url)
@@ -2281,36 +2826,40 @@ class binance(ccxt.async_support.binance):
2281
2826
  async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
2282
2827
  """
2283
2828
  edit a trade order
2284
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-and-replace-order-trade
2285
- :see: https://binance-docs.github.io/apidocs/futures/en/#modify-order-trade-2
2829
+
2830
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#cancel-and-replace-order-trade
2831
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Modify-Order
2832
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Modify-Order
2833
+
2286
2834
  :param str id: order id
2287
2835
  :param str symbol: unified symbol of the market to create an order in
2288
2836
  :param str type: 'market' or 'limit'
2289
2837
  :param str side: 'buy' or 'sell'
2290
2838
  :param float amount: how much of the currency you want to trade in units of the base currency
2291
- :param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2839
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
2292
2840
  :param dict [params]: extra parameters specific to the exchange API endpoint
2293
2841
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2294
2842
  """
2295
2843
  await self.load_markets()
2296
2844
  market = self.market(symbol)
2297
2845
  marketType = self.get_market_type('editOrderWs', market, params)
2298
- if marketType != 'spot' and marketType != 'future':
2846
+ if marketType != 'spot' and marketType != 'future' and marketType != 'delivery':
2299
2847
  raise BadRequest(self.id + ' editOrderWs only supports spot or swap markets')
2300
2848
  url = self.urls['api']['ws']['ws-api'][marketType]
2301
2849
  requestId = self.request_id(url)
2302
2850
  messageHash = str(requestId)
2851
+ isSwap = (marketType == 'future' or marketType == 'delivery')
2303
2852
  payload = None
2304
2853
  if marketType == 'spot':
2305
2854
  payload = self.editSpotOrderRequest(id, symbol, type, side, amount, price, params)
2306
- elif marketType == 'future':
2855
+ elif isSwap:
2307
2856
  payload = self.editContractOrderRequest(id, symbol, type, side, amount, price, params)
2308
2857
  returnRateLimits = False
2309
2858
  returnRateLimits, params = self.handle_option_and_params(params, 'editOrderWs', 'returnRateLimits', False)
2310
2859
  payload['returnRateLimits'] = returnRateLimits
2311
2860
  message: dict = {
2312
2861
  'id': messageHash,
2313
- 'method': 'order.modify' if (marketType == 'future') else 'order.cancelReplace',
2862
+ 'method': 'order.modify' if (isSwap) else 'order.cancelReplace',
2314
2863
  'params': self.sign_params(self.extend(payload, params)),
2315
2864
  }
2316
2865
  subscription: dict = {
@@ -2429,11 +2978,14 @@ class binance(ccxt.async_support.binance):
2429
2978
 
2430
2979
  async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
2431
2980
  """
2432
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-order-trade
2433
- :see: https://binance-docs.github.io/apidocs/futures/en/#cancel-order-trade-2
2434
2981
  cancel multiple orders
2982
+
2983
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#cancel-order-trade
2984
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Cancel-Order
2985
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Cancel-Order
2986
+
2435
2987
  :param str id: order id
2436
- :param str symbol: unified market symbol, default is None
2988
+ :param str [symbol]: unified market symbol, default is None
2437
2989
  :param dict [params]: extra parameters specific to the exchange API endpoint
2438
2990
  :param str|None [params.cancelRestrictions]: Supported values: ONLY_NEW - Cancel will succeed if the order status is NEW. ONLY_PARTIALLY_FILLED - Cancel will succeed if order status is PARTIALLY_FILLED.
2439
2991
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
@@ -2470,9 +3022,11 @@ class binance(ccxt.async_support.binance):
2470
3022
 
2471
3023
  async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
2472
3024
  """
2473
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#current-open-orders-user_data
2474
3025
  cancel all open orders in a market
2475
- :param str symbol: unified market symbol of the market to cancel orders in
3026
+
3027
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#cancel-open-orders-trade
3028
+
3029
+ :param str [symbol]: unified market symbol of the market to cancel orders in
2476
3030
  :param dict [params]: extra parameters specific to the exchange API endpoint
2477
3031
  :returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2478
3032
  """
@@ -2502,11 +3056,15 @@ class binance(ccxt.async_support.binance):
2502
3056
 
2503
3057
  async def fetch_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
2504
3058
  """
2505
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#query-order-user_data
2506
- :see: https://binance-docs.github.io/apidocs/futures/en/#query-order-user_data-2
2507
3059
  fetches information on an order made by the user
2508
- :param str symbol: unified symbol of the market the order was made in
2509
- :param dict params: extra parameters specific to the exchange API endpoint
3060
+
3061
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#query-order-user_data
3062
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Query-Order
3063
+ https://developers.binance.com/docs/derivatives/coin-margined-futures/trade/websocket-api/Query-Order
3064
+
3065
+ :param str id: order id
3066
+ :param str [symbol]: unified symbol of the market the order was made in
3067
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2510
3068
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2511
3069
  """
2512
3070
  await self.load_markets()
@@ -2514,7 +3072,7 @@ class binance(ccxt.async_support.binance):
2514
3072
  raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
2515
3073
  market = self.market(symbol)
2516
3074
  type = self.get_market_type('fetchOrderWs', market, params)
2517
- if type != 'spot' and type != 'future':
3075
+ if type != 'spot' and type != 'future' and type != 'delivery':
2518
3076
  raise BadRequest(self.id + ' fetchOrderWs only supports spot or swap markets')
2519
3077
  url = self.urls['api']['ws']['ws-api'][type]
2520
3078
  requestId = self.request_id(url)
@@ -2542,8 +3100,10 @@ class binance(ccxt.async_support.binance):
2542
3100
 
2543
3101
  async def fetch_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2544
3102
  """
2545
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-order-history-user_data
2546
3103
  fetches information on multiple orders made by the user
3104
+
3105
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#order-lists
3106
+
2547
3107
  :param str symbol: unified market symbol of the market orders were made in
2548
3108
  :param int|None [since]: the earliest time in ms to fetch orders for
2549
3109
  :param int|None [limit]: the maximum number of order structures to retrieve
@@ -2583,8 +3143,10 @@ class binance(ccxt.async_support.binance):
2583
3143
 
2584
3144
  async def fetch_closed_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2585
3145
  """
2586
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-order-history-user_data
2587
3146
  fetch closed orders
3147
+
3148
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#order-lists
3149
+
2588
3150
  :param str symbol: unified market symbol
2589
3151
  :param int [since]: the earliest time in ms to fetch open orders for
2590
3152
  :param int [limit]: the maximum number of open orders structures to retrieve
@@ -2601,8 +3163,10 @@ class binance(ccxt.async_support.binance):
2601
3163
 
2602
3164
  async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2603
3165
  """
2604
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#current-open-orders-user_data
2605
3166
  fetch all unfilled currently open orders
3167
+
3168
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/trading-requests#current-open-orders-user_data
3169
+
2606
3170
  :param str symbol: unified market symbol
2607
3171
  :param int|None [since]: the earliest time in ms to fetch open orders for
2608
3172
  :param int|None [limit]: the maximum number of open orders structures to retrieve
@@ -2638,9 +3202,11 @@ class binance(ccxt.async_support.binance):
2638
3202
  async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
2639
3203
  """
2640
3204
  watches information on multiple orders made by the user
2641
- :see: https://binance-docs.github.io/apidocs/spot/en/#payload-order-update
2642
- :see: https://binance-docs.github.io/apidocs/pm/en/#event-futures-order-update
2643
- :see: https://binance-docs.github.io/apidocs/pm/en/#event-margin-order-update
3205
+
3206
+ https://developers.binance.com/docs/binance-spot-api-docs/user-data-stream#order-update
3207
+ https://developers.binance.com/docs/margin_trading/trade-data-stream/Event-Order-Update
3208
+ https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Order-Update
3209
+
2644
3210
  :param str symbol: unified market symbol of the market the orders were made in
2645
3211
  :param int [since]: the earliest time in ms to fetch orders for
2646
3212
  :param int [limit]: the maximum number of order structures to retrieve
@@ -2923,6 +3489,8 @@ class binance(ccxt.async_support.binance):
2923
3489
  """
2924
3490
  watch all open positions
2925
3491
  :param str[]|None symbols: list of unified market symbols
3492
+ :param number [since]: since timestamp
3493
+ :param number [limit]: limit
2926
3494
  :param dict params: extra parameters specific to the exchange API endpoint
2927
3495
  :param boolean [params.portfolioMargin]: set to True if you would like to watch positions in a portfolio margin account
2928
3496
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
@@ -2934,11 +3502,6 @@ class binance(ccxt.async_support.binance):
2934
3502
  if not self.is_empty(symbols):
2935
3503
  market = self.get_market_from_symbols(symbols)
2936
3504
  messageHash = '::' + ','.join(symbols)
2937
- marketTypeObject: dict = {}
2938
- if market is not None:
2939
- marketTypeObject['type'] = market['type']
2940
- marketTypeObject['subType'] = market['subType']
2941
- await self.authenticate(self.extend(marketTypeObject, params))
2942
3505
  type = None
2943
3506
  type, params = self.handle_market_type_and_params('watchPositions', market, params)
2944
3507
  if type == 'spot' or type == 'margin':
@@ -2949,6 +3512,10 @@ class binance(ccxt.async_support.binance):
2949
3512
  type = 'future'
2950
3513
  elif self.isInverse(type, subType):
2951
3514
  type = 'delivery'
3515
+ marketTypeObject: dict = {}
3516
+ marketTypeObject['type'] = type
3517
+ marketTypeObject['subType'] = subType
3518
+ await self.authenticate(self.extend(marketTypeObject, params))
2952
3519
  messageHash = type + ':positions' + messageHash
2953
3520
  isPortfolioMargin = None
2954
3521
  isPortfolioMargin, params = self.handle_option_and_params_2(params, 'watchPositions', 'papi', 'portfolioMargin', False)
@@ -2960,7 +3527,7 @@ class binance(ccxt.async_support.binance):
2960
3527
  self.set_balance_cache(client, type, isPortfolioMargin)
2961
3528
  self.set_positions_cache(client, type, symbols, isPortfolioMargin)
2962
3529
  fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
2963
- awaitPositionsSnapshot = self.safe_bool('watchPositions', 'awaitPositionsSnapshot', True)
3530
+ awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
2964
3531
  cache = self.safe_value(self.positions, type)
2965
3532
  if fetchPositionsSnapshot and awaitPositionsSnapshot and cache is None:
2966
3533
  snapshot = await client.future(type + ':fetchPositionsSnapshot')
@@ -3117,8 +3684,10 @@ class binance(ccxt.async_support.binance):
3117
3684
 
3118
3685
  async def fetch_my_trades_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
3119
3686
  """
3120
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-trade-history-user_data
3121
3687
  fetch all trades made by the user
3688
+
3689
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/account-requests#account-trade-history-user_data
3690
+
3122
3691
  :param str symbol: unified market symbol
3123
3692
  :param int|None [since]: the earliest time in ms to fetch trades for
3124
3693
  :param int|None [limit]: the maximum number of trades structures to retrieve
@@ -3149,7 +3718,7 @@ class binance(ccxt.async_support.binance):
3149
3718
  payload['limit'] = limit
3150
3719
  fromId = self.safe_integer(params, 'fromId')
3151
3720
  if fromId is not None and since is not None:
3152
- raise BadRequest(self.id + 'fetchMyTradesWs does not support fetching by both fromId and since parameters at the same time')
3721
+ raise BadRequest(self.id + ' fetchMyTradesWs does not support fetching by both fromId and since parameters at the same time')
3153
3722
  message: dict = {
3154
3723
  'id': messageHash,
3155
3724
  'method': 'myTrades',
@@ -3161,22 +3730,22 @@ class binance(ccxt.async_support.binance):
3161
3730
  trades = await self.watch(url, messageHash, message, messageHash, subscription)
3162
3731
  return self.filter_by_symbol_since_limit(trades, symbol, since, limit)
3163
3732
 
3164
- async def fetch_trades_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
3733
+ async def fetch_trades_ws(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
3165
3734
  """
3166
- :see: https://binance-docs.github.io/apidocs/websocket_api/en/#recent-trades
3167
3735
  fetch all trades made by the user
3736
+
3737
+ https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/market-data-requests#recent-trades
3738
+
3168
3739
  :param str symbol: unified market symbol
3169
3740
  :param int [since]: the earliest time in ms to fetch trades for
3170
3741
  :param int [limit]: the maximum number of trades structures to retrieve, default=500, max=1000
3171
3742
  :param dict [params]: extra parameters specific to the exchange API endpoint
3172
- *
3173
- * EXCHANGE SPECIFIC PARAMETERS
3743
+
3744
+ EXCHANGE SPECIFIC PARAMETERS
3174
3745
  :param int [params.fromId]: trade ID to begin at
3175
3746
  :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
3176
3747
  """
3177
3748
  await self.load_markets()
3178
- if symbol is None:
3179
- raise BadRequest(self.id + ' fetchTradesWs() requires a symbol argument')
3180
3749
  market = self.market(symbol)
3181
3750
  type = self.get_market_type('fetchTradesWs', market, params)
3182
3751
  if type != 'spot' and type != 'future':
@@ -3262,7 +3831,7 @@ class binance(ccxt.async_support.binance):
3262
3831
  :param int [limit]: the maximum number of order structures to retrieve
3263
3832
  :param dict [params]: extra parameters specific to the exchange API endpoint
3264
3833
  :param boolean [params.portfolioMargin]: set to True if you would like to watch trades in a portfolio margin account
3265
- :returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
3834
+ :returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
3266
3835
  """
3267
3836
  await self.load_markets()
3268
3837
  type = None
@@ -3404,12 +3973,12 @@ class binance(ccxt.async_support.binance):
3404
3973
  code = self.safe_integer(error, 'code')
3405
3974
  msg = self.safe_string(error, 'msg')
3406
3975
  try:
3407
- self.handle_errors(code, msg, client.url, None, None, self.json(error), error, None, None)
3976
+ self.handle_errors(code, msg, client.url, '', {}, self.json(error), error, {}, {})
3408
3977
  except Exception as e:
3409
3978
  rejected = True
3410
3979
  # private endpoint uses id
3411
3980
  client.reject(e, id)
3412
- # public endpoint stores messageHash in subscriptios
3981
+ # public endpoint stores messageHash in subscriptions
3413
3982
  subscriptionKeys = list(client.subscriptions.keys())
3414
3983
  for i in range(0, len(subscriptionKeys)):
3415
3984
  subscriptionHash = subscriptionKeys[i]
@@ -3419,7 +3988,8 @@ class binance(ccxt.async_support.binance):
3419
3988
  if not rejected:
3420
3989
  client.reject(message, id)
3421
3990
  # reset connection if 5xx error
3422
- if self.safe_string(code, 0) == '5':
3991
+ codeString = self.safe_string(error, 'code')
3992
+ if (codeString is not None) and (codeString[0] == '5'):
3423
3993
  client.reset(message)
3424
3994
 
3425
3995
  def handle_message(self, client: Client, message):
@@ -3453,6 +4023,8 @@ class binance(ccxt.async_support.binance):
3453
4023
  '1dTicker': self.handle_tickers,
3454
4024
  '24hrTicker': self.handle_tickers,
3455
4025
  '24hrMiniTicker': self.handle_tickers,
4026
+ 'markPriceUpdate': self.handle_tickers,
4027
+ 'markPriceUpdate@arr': self.handle_tickers,
3456
4028
  'bookTicker': self.handle_bids_asks, # there is no "bookTicker@arr" endpoint
3457
4029
  'outboundAccountPosition': self.handle_balance,
3458
4030
  'balanceUpdate': self.handle_balance,