ccxt-ir 4.3.46.0.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccxt/__init__.py +358 -0
- ccxt/abantether.py +316 -0
- ccxt/abstract/__init__.py +0 -0
- ccxt/abstract/abantether.py +5 -0
- ccxt/abstract/ace.py +15 -0
- ccxt/abstract/afratether.py +6 -0
- ccxt/abstract/alpaca.py +70 -0
- ccxt/abstract/arzinja.py +5 -0
- ccxt/abstract/arzplus.py +7 -0
- ccxt/abstract/ascendex.py +77 -0
- ccxt/abstract/bequant.py +115 -0
- ccxt/abstract/bigone.py +45 -0
- ccxt/abstract/binance.py +712 -0
- ccxt/abstract/binancecoinm.py +712 -0
- ccxt/abstract/binanceus.py +764 -0
- ccxt/abstract/binanceusdm.py +712 -0
- ccxt/abstract/bingx.py +113 -0
- ccxt/abstract/bit2c.py +27 -0
- ccxt/abstract/bitbank.py +27 -0
- ccxt/abstract/bitbay.py +53 -0
- ccxt/abstract/bitbns.py +40 -0
- ccxt/abstract/bitcoincom.py +115 -0
- ccxt/abstract/bitfinex.py +69 -0
- ccxt/abstract/bitfinex2.py +139 -0
- ccxt/abstract/bitflyer.py +38 -0
- ccxt/abstract/bitget.py +508 -0
- ccxt/abstract/bithumb.py +32 -0
- ccxt/abstract/bitimen.py +7 -0
- ccxt/abstract/bitir.py +7 -0
- ccxt/abstract/bitmart.py +99 -0
- ccxt/abstract/bitmex.py +97 -0
- ccxt/abstract/bitopro.py +29 -0
- ccxt/abstract/bitpanda.py +35 -0
- ccxt/abstract/bitpin.py +7 -0
- ccxt/abstract/bitrue.py +72 -0
- ccxt/abstract/bitso.py +43 -0
- ccxt/abstract/bitstamp.py +258 -0
- ccxt/abstract/bitteam.py +29 -0
- ccxt/abstract/bitvavo.py +27 -0
- ccxt/abstract/bl3p.py +19 -0
- ccxt/abstract/blockchaincom.py +28 -0
- ccxt/abstract/blofin.py +37 -0
- ccxt/abstract/btcalpha.py +18 -0
- ccxt/abstract/btcbox.py +13 -0
- ccxt/abstract/btcmarkets.py +39 -0
- ccxt/abstract/btcturk.py +20 -0
- ccxt/abstract/bybit.py +298 -0
- ccxt/abstract/cex.py +33 -0
- ccxt/abstract/coinbase.py +94 -0
- ccxt/abstract/coinbaseadvanced.py +94 -0
- ccxt/abstract/coinbaseexchange.py +67 -0
- ccxt/abstract/coinbaseinternational.py +39 -0
- ccxt/abstract/coincatch.py +94 -0
- ccxt/abstract/coincheck.py +33 -0
- ccxt/abstract/coinex.py +237 -0
- ccxt/abstract/coinlist.py +54 -0
- ccxt/abstract/coinmate.py +62 -0
- ccxt/abstract/coinmetro.py +34 -0
- ccxt/abstract/coinone.py +67 -0
- ccxt/abstract/coinsph.py +54 -0
- ccxt/abstract/coinspot.py +28 -0
- ccxt/abstract/cryptocom.py +107 -0
- ccxt/abstract/currencycom.py +68 -0
- ccxt/abstract/delta.py +50 -0
- ccxt/abstract/deribit.py +125 -0
- ccxt/abstract/digifinex.py +91 -0
- ccxt/abstract/eterex.py +5 -0
- ccxt/abstract/excoino.py +7 -0
- ccxt/abstract/exir.py +8 -0
- ccxt/abstract/exmo.py +55 -0
- ccxt/abstract/exnovin.py +6 -0
- ccxt/abstract/farhadexchange.py +5 -0
- ccxt/abstract/fmfwio.py +115 -0
- ccxt/abstract/gate.py +265 -0
- ccxt/abstract/gateio.py +265 -0
- ccxt/abstract/gemini.py +58 -0
- ccxt/abstract/hashkey.py +67 -0
- ccxt/abstract/hitbtc.py +115 -0
- ccxt/abstract/hitbtc3.py +115 -0
- ccxt/abstract/hitobit.py +8 -0
- ccxt/abstract/hollaex.py +33 -0
- ccxt/abstract/htx.py +548 -0
- ccxt/abstract/huobi.py +548 -0
- ccxt/abstract/huobijp.py +114 -0
- ccxt/abstract/hyperliquid.py +6 -0
- ccxt/abstract/idex.py +26 -0
- ccxt/abstract/independentreserve.py +37 -0
- ccxt/abstract/indodax.py +26 -0
- ccxt/abstract/jibitex.py +7 -0
- ccxt/abstract/kraken.py +57 -0
- ccxt/abstract/krakenfutures.py +38 -0
- ccxt/abstract/kucoin.py +214 -0
- ccxt/abstract/kucoinfutures.py +233 -0
- ccxt/abstract/kuna.py +182 -0
- ccxt/abstract/latoken.py +56 -0
- ccxt/abstract/lbank.py +61 -0
- ccxt/abstract/luno.py +37 -0
- ccxt/abstract/lykke.py +29 -0
- ccxt/abstract/mercado.py +25 -0
- ccxt/abstract/mexc.py +178 -0
- ccxt/abstract/ndax.py +97 -0
- ccxt/abstract/nobitex.py +7 -0
- ccxt/abstract/novadax.py +29 -0
- ccxt/abstract/oceanex.py +22 -0
- ccxt/abstract/okcoin.py +74 -0
- ccxt/abstract/okexchange.py +8 -0
- ccxt/abstract/okx.py +324 -0
- ccxt/abstract/ompfinex.py +7 -0
- ccxt/abstract/onetrading.py +35 -0
- ccxt/abstract/oxfun.py +34 -0
- ccxt/abstract/p2b.py +22 -0
- ccxt/abstract/paradex.py +40 -0
- ccxt/abstract/paymium.py +28 -0
- ccxt/abstract/phemex.py +115 -0
- ccxt/abstract/poloniex.py +69 -0
- ccxt/abstract/poloniexfutures.py +48 -0
- ccxt/abstract/probit.py +23 -0
- ccxt/abstract/ramzinex.py +7 -0
- ccxt/abstract/sarmayex.py +5 -0
- ccxt/abstract/sarrafex.py +7 -0
- ccxt/abstract/tabdeal.py +7 -0
- ccxt/abstract/tetherland.py +5 -0
- ccxt/abstract/timex.py +62 -0
- ccxt/abstract/tokocrypto.py +37 -0
- ccxt/abstract/tradeogre.py +16 -0
- ccxt/abstract/twox.py +5 -0
- ccxt/abstract/ubitex.py +7 -0
- ccxt/abstract/upbit.py +38 -0
- ccxt/abstract/vertex.py +19 -0
- ccxt/abstract/wallex.py +8 -0
- ccxt/abstract/wavesexchange.py +154 -0
- ccxt/abstract/wazirx.py +30 -0
- ccxt/abstract/whitebit.py +98 -0
- ccxt/abstract/woo.py +83 -0
- ccxt/abstract/woofipro.py +119 -0
- ccxt/abstract/xt.py +152 -0
- ccxt/abstract/yobit.py +16 -0
- ccxt/abstract/zaif.py +38 -0
- ccxt/abstract/zonda.py +53 -0
- ccxt/ace.py +1012 -0
- ccxt/afratether.py +293 -0
- ccxt/alpaca.py +1083 -0
- ccxt/arzinja.py +285 -0
- ccxt/arzplus.py +412 -0
- ccxt/ascendex.py +3330 -0
- ccxt/async_support/__init__.py +337 -0
- ccxt/async_support/abantether.py +316 -0
- ccxt/async_support/ace.py +1012 -0
- ccxt/async_support/afratether.py +293 -0
- ccxt/async_support/alpaca.py +1083 -0
- ccxt/async_support/arzinja.py +285 -0
- ccxt/async_support/arzplus.py +412 -0
- ccxt/async_support/ascendex.py +3330 -0
- ccxt/async_support/base/__init__.py +1 -0
- ccxt/async_support/base/exchange.py +1966 -0
- ccxt/async_support/base/throttler.py +50 -0
- ccxt/async_support/base/ws/__init__.py +38 -0
- ccxt/async_support/base/ws/aiohttp_client.py +125 -0
- ccxt/async_support/base/ws/cache.py +212 -0
- ccxt/async_support/base/ws/client.py +193 -0
- ccxt/async_support/base/ws/fast_client.py +96 -0
- ccxt/async_support/base/ws/functions.py +59 -0
- ccxt/async_support/base/ws/future.py +58 -0
- ccxt/async_support/base/ws/order_book.py +78 -0
- ccxt/async_support/base/ws/order_book_side.py +174 -0
- ccxt/async_support/bequant.py +33 -0
- ccxt/async_support/bigone.py +2113 -0
- ccxt/async_support/binance.py +12234 -0
- ccxt/async_support/binancecoinm.py +45 -0
- ccxt/async_support/binanceus.py +211 -0
- ccxt/async_support/binanceusdm.py +58 -0
- ccxt/async_support/bingx.py +4325 -0
- ccxt/async_support/bit2c.py +866 -0
- ccxt/async_support/bitbank.py +1001 -0
- ccxt/async_support/bitbay.py +17 -0
- ccxt/async_support/bitbns.py +1154 -0
- ccxt/async_support/bitcoincom.py +17 -0
- ccxt/async_support/bitfinex.py +1617 -0
- ccxt/async_support/bitfinex2.py +3552 -0
- ccxt/async_support/bitflyer.py +995 -0
- ccxt/async_support/bitget.py +8273 -0
- ccxt/async_support/bithumb.py +1061 -0
- ccxt/async_support/bitimen.py +401 -0
- ccxt/async_support/bitir.py +490 -0
- ccxt/async_support/bitmart.py +4415 -0
- ccxt/async_support/bitmex.py +2756 -0
- ccxt/async_support/bitopro.py +1630 -0
- ccxt/async_support/bitpanda.py +16 -0
- ccxt/async_support/bitpin.py +454 -0
- ccxt/async_support/bitrue.py +3027 -0
- ccxt/async_support/bitso.py +1670 -0
- ccxt/async_support/bitstamp.py +2203 -0
- ccxt/async_support/bitteam.py +2239 -0
- ccxt/async_support/bitvavo.py +1968 -0
- ccxt/async_support/bl3p.py +485 -0
- ccxt/async_support/blockchaincom.py +1104 -0
- ccxt/async_support/blofin.py +2066 -0
- ccxt/async_support/btcalpha.py +891 -0
- ccxt/async_support/btcbox.py +544 -0
- ccxt/async_support/btcmarkets.py +1221 -0
- ccxt/async_support/btcturk.py +911 -0
- ccxt/async_support/bybit.py +8159 -0
- ccxt/async_support/cex.py +1605 -0
- ccxt/async_support/coinbase.py +4475 -0
- ccxt/async_support/coinbaseadvanced.py +17 -0
- ccxt/async_support/coinbaseexchange.py +1734 -0
- ccxt/async_support/coinbaseinternational.py +1899 -0
- ccxt/async_support/coincatch.py +5069 -0
- ccxt/async_support/coincheck.py +815 -0
- ccxt/async_support/coinex.py +5526 -0
- ccxt/async_support/coinlist.py +2243 -0
- ccxt/async_support/coinmate.py +1067 -0
- ccxt/async_support/coinmetro.py +1797 -0
- ccxt/async_support/coinone.py +1127 -0
- ccxt/async_support/coinsph.py +1850 -0
- ccxt/async_support/coinspot.py +534 -0
- ccxt/async_support/cryptocom.py +2822 -0
- ccxt/async_support/currencycom.py +1950 -0
- ccxt/async_support/delta.py +3376 -0
- ccxt/async_support/deribit.py +3437 -0
- ccxt/async_support/digifinex.py +3960 -0
- ccxt/async_support/eterex.py +286 -0
- ccxt/async_support/excoino.py +399 -0
- ccxt/async_support/exir.py +375 -0
- ccxt/async_support/exmo.py +2462 -0
- ccxt/async_support/exnovin.py +360 -0
- ccxt/async_support/farhadexchange.py +266 -0
- ccxt/async_support/fmfwio.py +34 -0
- ccxt/async_support/gate.py +6976 -0
- ccxt/async_support/gateio.py +16 -0
- ccxt/async_support/gemini.py +1825 -0
- ccxt/async_support/hashkey.py +4150 -0
- ccxt/async_support/hitbtc.py +3423 -0
- ccxt/async_support/hitbtc3.py +16 -0
- ccxt/async_support/hitobit.py +391 -0
- ccxt/async_support/hollaex.py +1813 -0
- ccxt/async_support/htx.py +8506 -0
- ccxt/async_support/huobi.py +16 -0
- ccxt/async_support/huobijp.py +1801 -0
- ccxt/async_support/hyperliquid.py +2431 -0
- ccxt/async_support/idex.py +1766 -0
- ccxt/async_support/independentreserve.py +784 -0
- ccxt/async_support/indodax.py +1247 -0
- ccxt/async_support/jibitex.py +395 -0
- ccxt/async_support/kraken.py +2894 -0
- ccxt/async_support/krakenfutures.py +2601 -0
- ccxt/async_support/kucoin.py +4602 -0
- ccxt/async_support/kucoinfutures.py +2698 -0
- ccxt/async_support/kuna.py +1841 -0
- ccxt/async_support/latoken.py +1664 -0
- ccxt/async_support/lbank.py +2683 -0
- ccxt/async_support/luno.py +1067 -0
- ccxt/async_support/lykke.py +1270 -0
- ccxt/async_support/mercado.py +842 -0
- ccxt/async_support/mexc.py +5369 -0
- ccxt/async_support/ndax.py +2354 -0
- ccxt/async_support/nobitex.py +419 -0
- ccxt/async_support/novadax.py +1484 -0
- ccxt/async_support/oceanex.py +903 -0
- ccxt/async_support/okcoin.py +2936 -0
- ccxt/async_support/okexchange.py +349 -0
- ccxt/async_support/okx.py +7827 -0
- ccxt/async_support/ompfinex.py +472 -0
- ccxt/async_support/onetrading.py +1911 -0
- ccxt/async_support/oxfun.py +2773 -0
- ccxt/async_support/p2b.py +1194 -0
- ccxt/async_support/paradex.py +2015 -0
- ccxt/async_support/paymium.py +564 -0
- ccxt/async_support/phemex.py +4473 -0
- ccxt/async_support/poloniex.py +2232 -0
- ccxt/async_support/poloniexfutures.py +1717 -0
- ccxt/async_support/probit.py +1734 -0
- ccxt/async_support/ramzinex.py +476 -0
- ccxt/async_support/sarmayex.py +357 -0
- ccxt/async_support/sarrafex.py +478 -0
- ccxt/async_support/tabdeal.py +364 -0
- ccxt/async_support/tetherland.py +349 -0
- ccxt/async_support/timex.py +1593 -0
- ccxt/async_support/tokocrypto.py +2405 -0
- ccxt/async_support/tradeogre.py +608 -0
- ccxt/async_support/twox.py +326 -0
- ccxt/async_support/ubitex.py +409 -0
- ccxt/async_support/upbit.py +1833 -0
- ccxt/async_support/vertex.py +2922 -0
- ccxt/async_support/wallex.py +445 -0
- ccxt/async_support/wavesexchange.py +2473 -0
- ccxt/async_support/wazirx.py +1224 -0
- ccxt/async_support/whitebit.py +2469 -0
- ccxt/async_support/woo.py +3114 -0
- ccxt/async_support/woofipro.py +2533 -0
- ccxt/async_support/xt.py +4454 -0
- ccxt/async_support/yobit.py +1283 -0
- ccxt/async_support/zaif.py +725 -0
- ccxt/async_support/zonda.py +1828 -0
- ccxt/base/__init__.py +27 -0
- ccxt/base/decimal_to_precision.py +174 -0
- ccxt/base/errors.py +242 -0
- ccxt/base/exchange.py +5941 -0
- ccxt/base/precise.py +287 -0
- ccxt/base/types.py +502 -0
- ccxt/bequant.py +33 -0
- ccxt/bigone.py +2112 -0
- ccxt/binance.py +12233 -0
- ccxt/binancecoinm.py +45 -0
- ccxt/binanceus.py +211 -0
- ccxt/binanceusdm.py +58 -0
- ccxt/bingx.py +4324 -0
- ccxt/bit2c.py +866 -0
- ccxt/bitbank.py +1001 -0
- ccxt/bitbay.py +17 -0
- ccxt/bitbns.py +1154 -0
- ccxt/bitcoincom.py +17 -0
- ccxt/bitfinex.py +1617 -0
- ccxt/bitfinex2.py +3552 -0
- ccxt/bitflyer.py +995 -0
- ccxt/bitget.py +8272 -0
- ccxt/bithumb.py +1061 -0
- ccxt/bitimen.py +401 -0
- ccxt/bitir.py +490 -0
- ccxt/bitmart.py +4415 -0
- ccxt/bitmex.py +2756 -0
- ccxt/bitopro.py +1630 -0
- ccxt/bitpanda.py +16 -0
- ccxt/bitpin.py +454 -0
- ccxt/bitrue.py +3026 -0
- ccxt/bitso.py +1670 -0
- ccxt/bitstamp.py +2203 -0
- ccxt/bitteam.py +2239 -0
- ccxt/bitvavo.py +1968 -0
- ccxt/bl3p.py +485 -0
- ccxt/blockchaincom.py +1104 -0
- ccxt/blofin.py +2066 -0
- ccxt/btcalpha.py +891 -0
- ccxt/btcbox.py +544 -0
- ccxt/btcmarkets.py +1221 -0
- ccxt/btcturk.py +911 -0
- ccxt/bybit.py +8158 -0
- ccxt/cex.py +1605 -0
- ccxt/coinbase.py +4474 -0
- ccxt/coinbaseadvanced.py +17 -0
- ccxt/coinbaseexchange.py +1734 -0
- ccxt/coinbaseinternational.py +1899 -0
- ccxt/coincatch.py +5069 -0
- ccxt/coincheck.py +815 -0
- ccxt/coinex.py +5525 -0
- ccxt/coinlist.py +2243 -0
- ccxt/coinmate.py +1067 -0
- ccxt/coinmetro.py +1797 -0
- ccxt/coinone.py +1127 -0
- ccxt/coinsph.py +1850 -0
- ccxt/coinspot.py +534 -0
- ccxt/cryptocom.py +2822 -0
- ccxt/currencycom.py +1950 -0
- ccxt/delta.py +3376 -0
- ccxt/deribit.py +3437 -0
- ccxt/digifinex.py +3959 -0
- ccxt/eterex.py +286 -0
- ccxt/excoino.py +399 -0
- ccxt/exir.py +375 -0
- ccxt/exmo.py +2462 -0
- ccxt/exnovin.py +360 -0
- ccxt/farhadexchange.py +266 -0
- ccxt/fmfwio.py +34 -0
- ccxt/gate.py +6975 -0
- ccxt/gateio.py +16 -0
- ccxt/gemini.py +1824 -0
- ccxt/hashkey.py +4150 -0
- ccxt/hitbtc.py +3423 -0
- ccxt/hitbtc3.py +16 -0
- ccxt/hitobit.py +391 -0
- ccxt/hollaex.py +1813 -0
- ccxt/htx.py +8505 -0
- ccxt/huobi.py +16 -0
- ccxt/huobijp.py +1801 -0
- ccxt/hyperliquid.py +2430 -0
- ccxt/idex.py +1766 -0
- ccxt/independentreserve.py +784 -0
- ccxt/indodax.py +1247 -0
- ccxt/jibitex.py +395 -0
- ccxt/kraken.py +2894 -0
- ccxt/krakenfutures.py +2601 -0
- ccxt/kucoin.py +4601 -0
- ccxt/kucoinfutures.py +2698 -0
- ccxt/kuna.py +1841 -0
- ccxt/latoken.py +1664 -0
- ccxt/lbank.py +2682 -0
- ccxt/luno.py +1067 -0
- ccxt/lykke.py +1270 -0
- ccxt/mercado.py +842 -0
- ccxt/mexc.py +5369 -0
- ccxt/ndax.py +2354 -0
- ccxt/nobitex.py +419 -0
- ccxt/novadax.py +1484 -0
- ccxt/oceanex.py +903 -0
- ccxt/okcoin.py +2936 -0
- ccxt/okexchange.py +349 -0
- ccxt/okx.py +7826 -0
- ccxt/ompfinex.py +472 -0
- ccxt/onetrading.py +1911 -0
- ccxt/oxfun.py +2772 -0
- ccxt/p2b.py +1194 -0
- ccxt/paradex.py +2015 -0
- ccxt/paymium.py +564 -0
- ccxt/phemex.py +4473 -0
- ccxt/poloniex.py +2232 -0
- ccxt/poloniexfutures.py +1717 -0
- ccxt/pro/__init__.py +149 -0
- ccxt/pro/alpaca.py +685 -0
- ccxt/pro/ascendex.py +916 -0
- ccxt/pro/bequant.py +38 -0
- ccxt/pro/binance.py +3488 -0
- ccxt/pro/binancecoinm.py +28 -0
- ccxt/pro/binanceus.py +48 -0
- ccxt/pro/binanceusdm.py +31 -0
- ccxt/pro/bingx.py +1264 -0
- ccxt/pro/bitcoincom.py +34 -0
- ccxt/pro/bitfinex.py +621 -0
- ccxt/pro/bitfinex2.py +1083 -0
- ccxt/pro/bitget.py +1692 -0
- ccxt/pro/bithumb.py +368 -0
- ccxt/pro/bitmart.py +1449 -0
- ccxt/pro/bitmex.py +1656 -0
- ccxt/pro/bitopro.py +445 -0
- ccxt/pro/bitpanda.py +15 -0
- ccxt/pro/bitrue.py +447 -0
- ccxt/pro/bitstamp.py +522 -0
- ccxt/pro/bitvavo.py +1270 -0
- ccxt/pro/blockchaincom.py +738 -0
- ccxt/pro/blofin.py +692 -0
- ccxt/pro/bybit.py +2000 -0
- ccxt/pro/cex.py +1440 -0
- ccxt/pro/coinbase.py +678 -0
- ccxt/pro/coinbaseadvanced.py +16 -0
- ccxt/pro/coinbaseexchange.py +895 -0
- ccxt/pro/coinbaseinternational.py +620 -0
- ccxt/pro/coincatch.py +1464 -0
- ccxt/pro/coincheck.py +199 -0
- ccxt/pro/coinex.py +1061 -0
- ccxt/pro/coinone.py +395 -0
- ccxt/pro/cryptocom.py +947 -0
- ccxt/pro/currencycom.py +536 -0
- ccxt/pro/deribit.py +892 -0
- ccxt/pro/exmo.py +629 -0
- ccxt/pro/gate.py +1416 -0
- ccxt/pro/gateio.py +15 -0
- ccxt/pro/gemini.py +865 -0
- ccxt/pro/hashkey.py +802 -0
- ccxt/pro/hitbtc.py +1216 -0
- ccxt/pro/hollaex.py +563 -0
- ccxt/pro/htx.py +2215 -0
- ccxt/pro/huobi.py +15 -0
- ccxt/pro/huobijp.py +570 -0
- ccxt/pro/hyperliquid.py +525 -0
- ccxt/pro/idex.py +672 -0
- ccxt/pro/independentreserve.py +270 -0
- ccxt/pro/kraken.py +1356 -0
- ccxt/pro/krakenfutures.py +1492 -0
- ccxt/pro/kucoin.py +1133 -0
- ccxt/pro/kucoinfutures.py +1081 -0
- ccxt/pro/lbank.py +843 -0
- ccxt/pro/luno.py +303 -0
- ccxt/pro/mexc.py +1122 -0
- ccxt/pro/ndax.py +506 -0
- ccxt/pro/okcoin.py +698 -0
- ccxt/pro/okx.py +1851 -0
- ccxt/pro/onetrading.py +1275 -0
- ccxt/pro/oxfun.py +950 -0
- ccxt/pro/p2b.py +419 -0
- ccxt/pro/paradex.py +352 -0
- ccxt/pro/phemex.py +1441 -0
- ccxt/pro/poloniex.py +1166 -0
- ccxt/pro/poloniexfutures.py +990 -0
- ccxt/pro/probit.py +551 -0
- ccxt/pro/upbit.py +520 -0
- ccxt/pro/vertex.py +943 -0
- ccxt/pro/wazirx.py +749 -0
- ccxt/pro/whitebit.py +864 -0
- ccxt/pro/woo.py +1078 -0
- ccxt/pro/woofipro.py +1183 -0
- ccxt/pro/xt.py +1067 -0
- ccxt/probit.py +1734 -0
- ccxt/ramzinex.py +476 -0
- ccxt/sarmayex.py +357 -0
- ccxt/sarrafex.py +478 -0
- ccxt/static_dependencies/__init__.py +1 -0
- ccxt/static_dependencies/ecdsa/__init__.py +14 -0
- ccxt/static_dependencies/ecdsa/_version.py +520 -0
- ccxt/static_dependencies/ecdsa/curves.py +56 -0
- ccxt/static_dependencies/ecdsa/der.py +221 -0
- ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
- ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
- ccxt/static_dependencies/ecdsa/keys.py +332 -0
- ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
- ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
- ccxt/static_dependencies/ecdsa/util.py +266 -0
- ccxt/static_dependencies/ethereum/__init__.py +7 -0
- ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
- ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
- ccxt/static_dependencies/ethereum/abi/base.py +152 -0
- ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
- ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
- ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
- ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
- ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
- ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
- ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
- ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
- ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
- ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
- ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
- ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
- ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
- ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
- ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
- ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
- ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
- ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
- ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
- ccxt/static_dependencies/ethereum/account/messages.py +263 -0
- ccxt/static_dependencies/ethereum/account/py.typed +0 -0
- ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
- ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
- ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
- ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
- ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
- ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
- ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
- ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
- ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
- ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
- ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
- ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
- ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
- ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
- ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
- ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
- ccxt/static_dependencies/ethereum/utils/address.py +171 -0
- ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
- ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
- ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
- ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
- ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
- ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
- ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
- ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
- ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
- ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
- ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
- ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
- ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
- ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
- ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
- ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
- ccxt/static_dependencies/ethereum/utils/types.py +54 -0
- ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
- ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
- ccxt/static_dependencies/ethereum/utils/units.py +31 -0
- ccxt/static_dependencies/keccak/__init__.py +3 -0
- ccxt/static_dependencies/keccak/keccak.py +197 -0
- ccxt/static_dependencies/lark/__init__.py +38 -0
- ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- ccxt/static_dependencies/lark/ast_utils.py +59 -0
- ccxt/static_dependencies/lark/common.py +86 -0
- ccxt/static_dependencies/lark/exceptions.py +292 -0
- ccxt/static_dependencies/lark/grammar.py +130 -0
- ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- ccxt/static_dependencies/lark/indenter.py +143 -0
- ccxt/static_dependencies/lark/lark.py +658 -0
- ccxt/static_dependencies/lark/lexer.py +678 -0
- ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- ccxt/static_dependencies/lark/reconstruct.py +107 -0
- ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- ccxt/static_dependencies/lark/tree.py +267 -0
- ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- ccxt/static_dependencies/lark/tree_templates.py +180 -0
- ccxt/static_dependencies/lark/utils.py +343 -0
- ccxt/static_dependencies/lark/visitors.py +596 -0
- ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- ccxt/static_dependencies/marshmallow/base.py +65 -0
- ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- ccxt/static_dependencies/marshmallow/types.py +12 -0
- ccxt/static_dependencies/marshmallow/utils.py +378 -0
- ccxt/static_dependencies/marshmallow/validate.py +678 -0
- ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- ccxt/static_dependencies/msgpack/__init__.py +55 -0
- ccxt/static_dependencies/msgpack/exceptions.py +48 -0
- ccxt/static_dependencies/msgpack/ext.py +168 -0
- ccxt/static_dependencies/msgpack/fallback.py +951 -0
- ccxt/static_dependencies/parsimonious/__init__.py +10 -0
- ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
- ccxt/static_dependencies/parsimonious/expressions.py +479 -0
- ccxt/static_dependencies/parsimonious/grammar.py +487 -0
- ccxt/static_dependencies/parsimonious/nodes.py +325 -0
- ccxt/static_dependencies/parsimonious/utils.py +40 -0
- ccxt/static_dependencies/starknet/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- ccxt/static_dependencies/starknet/common.py +15 -0
- ccxt/static_dependencies/starknet/constants.py +39 -0
- ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- ccxt/static_dependencies/starknet/hash/address.py +79 -0
- ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- ccxt/static_dependencies/starkware/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- ccxt/static_dependencies/sympy/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- ccxt/static_dependencies/toolz/__init__.py +26 -0
- ccxt/static_dependencies/toolz/_signatures.py +784 -0
- ccxt/static_dependencies/toolz/_version.py +520 -0
- ccxt/static_dependencies/toolz/compatibility.py +30 -0
- ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
- ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
- ccxt/static_dependencies/toolz/curried/operator.py +22 -0
- ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
- ccxt/static_dependencies/toolz/functoolz.py +1049 -0
- ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
- ccxt/static_dependencies/toolz/recipes.py +46 -0
- ccxt/static_dependencies/toolz/utils.py +9 -0
- ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/tabdeal.py +364 -0
- ccxt/test/__init__.py +3 -0
- ccxt/test/base/__init__.py +29 -0
- ccxt/test/base/test_account.py +26 -0
- ccxt/test/base/test_balance.py +56 -0
- ccxt/test/base/test_borrow_interest.py +35 -0
- ccxt/test/base/test_borrow_rate.py +32 -0
- ccxt/test/base/test_calculate_fee.py +51 -0
- ccxt/test/base/test_crypto.py +127 -0
- ccxt/test/base/test_currency.py +76 -0
- ccxt/test/base/test_datetime.py +109 -0
- ccxt/test/base/test_decimal_to_precision.py +392 -0
- ccxt/test/base/test_deep_extend.py +68 -0
- ccxt/test/base/test_deposit_withdrawal.py +50 -0
- ccxt/test/base/test_exchange_datetime_functions.py +76 -0
- ccxt/test/base/test_funding_rate_history.py +29 -0
- ccxt/test/base/test_last_price.py +31 -0
- ccxt/test/base/test_ledger_entry.py +45 -0
- ccxt/test/base/test_ledger_item.py +48 -0
- ccxt/test/base/test_leverage_tier.py +33 -0
- ccxt/test/base/test_liquidation.py +50 -0
- ccxt/test/base/test_margin_mode.py +24 -0
- ccxt/test/base/test_margin_modification.py +35 -0
- ccxt/test/base/test_market.py +193 -0
- ccxt/test/base/test_number.py +411 -0
- ccxt/test/base/test_ohlcv.py +33 -0
- ccxt/test/base/test_open_interest.py +32 -0
- ccxt/test/base/test_order.py +64 -0
- ccxt/test/base/test_order_book.py +69 -0
- ccxt/test/base/test_position.py +60 -0
- ccxt/test/base/test_shared_methods.py +353 -0
- ccxt/test/base/test_status.py +24 -0
- ccxt/test/base/test_throttle.py +126 -0
- ccxt/test/base/test_ticker.py +92 -0
- ccxt/test/base/test_trade.py +47 -0
- ccxt/test/base/test_trading_fee.py +26 -0
- ccxt/test/base/test_transaction.py +39 -0
- ccxt/test/test_async.py +1649 -0
- ccxt/test/test_sync.py +1648 -0
- ccxt/test/tests_async.py +1558 -0
- ccxt/test/tests_helpers.py +287 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/tests_sync.py +1555 -0
- ccxt/tetherland.py +349 -0
- ccxt/timex.py +1593 -0
- ccxt/tokocrypto.py +2405 -0
- ccxt/tradeogre.py +608 -0
- ccxt/twox.py +326 -0
- ccxt/ubitex.py +409 -0
- ccxt/upbit.py +1833 -0
- ccxt/vertex.py +2922 -0
- ccxt/wallex.py +445 -0
- ccxt/wavesexchange.py +2472 -0
- ccxt/wazirx.py +1224 -0
- ccxt/whitebit.py +2469 -0
- ccxt/woo.py +3114 -0
- ccxt/woofipro.py +2533 -0
- ccxt/xt.py +4453 -0
- ccxt/yobit.py +1283 -0
- ccxt/zaif.py +725 -0
- ccxt/zonda.py +1828 -0
- ccxt_ir-4.3.46.0.1.dist-info/LICENSE.txt +21 -0
- ccxt_ir-4.3.46.0.1.dist-info/METADATA +655 -0
- ccxt_ir-4.3.46.0.1.dist-info/RECORD +772 -0
- ccxt_ir-4.3.46.0.1.dist-info/WHEEL +6 -0
- ccxt_ir-4.3.46.0.1.dist-info/top_level.txt +1 -0
ccxt/pro/kraken.py
ADDED
|
@@ -0,0 +1,1356 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
|
4
|
+
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
5
|
+
|
|
6
|
+
import ccxt.async_support
|
|
7
|
+
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp
|
|
8
|
+
from ccxt.base.types import Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
|
|
9
|
+
from ccxt.async_support.base.ws.client import Client
|
|
10
|
+
from typing import List
|
|
11
|
+
from ccxt.base.errors import ExchangeError
|
|
12
|
+
from ccxt.base.errors import AuthenticationError
|
|
13
|
+
from ccxt.base.errors import PermissionDenied
|
|
14
|
+
from ccxt.base.errors import AccountSuspended
|
|
15
|
+
from ccxt.base.errors import BadRequest
|
|
16
|
+
from ccxt.base.errors import BadSymbol
|
|
17
|
+
from ccxt.base.errors import InsufficientFunds
|
|
18
|
+
from ccxt.base.errors import InvalidOrder
|
|
19
|
+
from ccxt.base.errors import OrderNotFound
|
|
20
|
+
from ccxt.base.errors import NotSupported
|
|
21
|
+
from ccxt.base.errors import RateLimitExceeded
|
|
22
|
+
from ccxt.base.errors import ExchangeNotAvailable
|
|
23
|
+
from ccxt.base.errors import InvalidNonce
|
|
24
|
+
from ccxt.base.precise import Precise
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class kraken(ccxt.async_support.kraken):
|
|
28
|
+
|
|
29
|
+
def describe(self):
|
|
30
|
+
return self.deep_extend(super(kraken, self).describe(), {
|
|
31
|
+
'has': {
|
|
32
|
+
'ws': True,
|
|
33
|
+
'watchBalance': False, # no such type of subscription 2021-01-05
|
|
34
|
+
'watchMyTrades': True,
|
|
35
|
+
'watchOHLCV': True,
|
|
36
|
+
'watchOrderBook': True,
|
|
37
|
+
'watchOrderBookForSymbols': True,
|
|
38
|
+
'watchOrders': True,
|
|
39
|
+
'watchTicker': True,
|
|
40
|
+
'watchTickers': True,
|
|
41
|
+
'watchTrades': True,
|
|
42
|
+
'watchTradesForSymbols': True,
|
|
43
|
+
'createOrderWs': True,
|
|
44
|
+
'editOrderWs': True,
|
|
45
|
+
'cancelOrderWs': True,
|
|
46
|
+
'cancelOrdersWs': True,
|
|
47
|
+
'cancelAllOrdersWs': True,
|
|
48
|
+
# 'watchHeartbeat': True,
|
|
49
|
+
# 'watchStatus': True,
|
|
50
|
+
},
|
|
51
|
+
'urls': {
|
|
52
|
+
'api': {
|
|
53
|
+
'ws': {
|
|
54
|
+
'public': 'wss://ws.kraken.com',
|
|
55
|
+
'private': 'wss://ws-auth.kraken.com',
|
|
56
|
+
'beta': 'wss://beta-ws.kraken.com',
|
|
57
|
+
'beta-private': 'wss://beta-ws-auth.kraken.com',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
# 'versions': {
|
|
62
|
+
# 'ws': '0.2.0',
|
|
63
|
+
# },
|
|
64
|
+
'options': {
|
|
65
|
+
'tradesLimit': 1000,
|
|
66
|
+
'OHLCVLimit': 1000,
|
|
67
|
+
'ordersLimit': 1000,
|
|
68
|
+
'symbolsByOrderId': {},
|
|
69
|
+
'checksum': True,
|
|
70
|
+
},
|
|
71
|
+
'exceptions': {
|
|
72
|
+
'ws': {
|
|
73
|
+
'exact': {
|
|
74
|
+
'Event(s) not found': BadRequest,
|
|
75
|
+
},
|
|
76
|
+
'broad': {
|
|
77
|
+
'Already subscribed': BadRequest,
|
|
78
|
+
'Currency pair not in ISO 4217-A3 format': BadSymbol,
|
|
79
|
+
'Malformed request': BadRequest,
|
|
80
|
+
'Pair field must be an array': BadRequest,
|
|
81
|
+
'Pair field unsupported for self subscription type': BadRequest,
|
|
82
|
+
'Pair(s) not found': BadSymbol,
|
|
83
|
+
'Subscription book depth must be an integer': BadRequest,
|
|
84
|
+
'Subscription depth not supported': BadRequest,
|
|
85
|
+
'Subscription field must be an object': BadRequest,
|
|
86
|
+
'Subscription name invalid': BadRequest,
|
|
87
|
+
'Subscription object unsupported field': BadRequest,
|
|
88
|
+
'Subscription ohlc interval must be an integer': BadRequest,
|
|
89
|
+
'Subscription ohlc interval not supported': BadRequest,
|
|
90
|
+
'Subscription ohlc requires interval': BadRequest,
|
|
91
|
+
'EAccount:Invalid permissions': PermissionDenied,
|
|
92
|
+
'EAuth:Account temporary disabled': AccountSuspended,
|
|
93
|
+
'EAuth:Account unconfirmed': AuthenticationError,
|
|
94
|
+
'EAuth:Rate limit exceeded': RateLimitExceeded,
|
|
95
|
+
'EAuth:Too many requests': RateLimitExceeded,
|
|
96
|
+
'EDatabase: Internal error(to be deprecated)': ExchangeError,
|
|
97
|
+
'EGeneral:Internal error[:<code>]': ExchangeError,
|
|
98
|
+
'EGeneral:Invalid arguments': BadRequest,
|
|
99
|
+
'EOrder:Cannot open opposing position': InvalidOrder,
|
|
100
|
+
'EOrder:Cannot open position': InvalidOrder,
|
|
101
|
+
'EOrder:Insufficient funds(insufficient user funds)': InsufficientFunds,
|
|
102
|
+
'EOrder:Insufficient margin(exchange does not have sufficient funds to allow margin trading)': InsufficientFunds,
|
|
103
|
+
'EOrder:Invalid price': InvalidOrder,
|
|
104
|
+
'EOrder:Margin allowance exceeded': InvalidOrder,
|
|
105
|
+
'EOrder:Margin level too low': InvalidOrder,
|
|
106
|
+
'EOrder:Margin position size exceeded(client would exceed the maximum position size for self pair)': InvalidOrder,
|
|
107
|
+
'EOrder:Order minimum not met(volume too low)': InvalidOrder,
|
|
108
|
+
'EOrder:Orders limit exceeded': InvalidOrder,
|
|
109
|
+
'EOrder:Positions limit exceeded': InvalidOrder,
|
|
110
|
+
'EOrder:Rate limit exceeded': RateLimitExceeded,
|
|
111
|
+
'EOrder:Scheduled orders limit exceeded': InvalidOrder,
|
|
112
|
+
'EOrder:Unknown position': OrderNotFound,
|
|
113
|
+
'EOrder:Unknown order': OrderNotFound,
|
|
114
|
+
'EOrder:Invalid order': InvalidOrder,
|
|
115
|
+
'EService:Deadline elapsed': ExchangeNotAvailable,
|
|
116
|
+
'EService:Market in cancel_only mode': NotSupported,
|
|
117
|
+
'EService:Market in limit_only mode': NotSupported,
|
|
118
|
+
'EService:Market in post_only mode': NotSupported,
|
|
119
|
+
'EService:Unavailable': ExchangeNotAvailable,
|
|
120
|
+
'ETrade:Invalid request': BadRequest,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
|
127
|
+
"""
|
|
128
|
+
:see: https://docs.kraken.com/websockets/#message-addOrder
|
|
129
|
+
create a trade order
|
|
130
|
+
:param str symbol: unified symbol of the market to create an order in
|
|
131
|
+
:param str type: 'market' or 'limit'
|
|
132
|
+
:param str side: 'buy' or 'sell'
|
|
133
|
+
:param float amount: how much of currency you want to trade in units of base currency
|
|
134
|
+
:param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
135
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
136
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
137
|
+
"""
|
|
138
|
+
await self.load_markets()
|
|
139
|
+
token = await self.authenticate()
|
|
140
|
+
market = self.market(symbol)
|
|
141
|
+
url = self.urls['api']['ws']['private']
|
|
142
|
+
requestId = self.request_id()
|
|
143
|
+
messageHash = requestId
|
|
144
|
+
request: dict = {
|
|
145
|
+
'event': 'addOrder',
|
|
146
|
+
'token': token,
|
|
147
|
+
'reqid': requestId,
|
|
148
|
+
'ordertype': type,
|
|
149
|
+
'type': side,
|
|
150
|
+
'pair': market['wsId'],
|
|
151
|
+
'volume': self.amount_to_precision(symbol, amount),
|
|
152
|
+
}
|
|
153
|
+
request, params = self.orderRequest('createOrderWs', symbol, type, request, amount, price, params)
|
|
154
|
+
return await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
155
|
+
|
|
156
|
+
def handle_create_edit_order(self, client, message):
|
|
157
|
+
#
|
|
158
|
+
# createOrder
|
|
159
|
+
# {
|
|
160
|
+
# "descr": "sell 0.00010000 XBTUSDT @ market",
|
|
161
|
+
# "event": "addOrderStatus",
|
|
162
|
+
# "reqid": 1,
|
|
163
|
+
# "status": "ok",
|
|
164
|
+
# "txid": "OAVXZH-XIE54-JCYYDG"
|
|
165
|
+
# }
|
|
166
|
+
# editOrder
|
|
167
|
+
# {
|
|
168
|
+
# "descr": "order edited price = 9000.00000000",
|
|
169
|
+
# "event": "editOrderStatus",
|
|
170
|
+
# "originaltxid": "O65KZW-J4AW3-VFS74A",
|
|
171
|
+
# "reqid": 3,
|
|
172
|
+
# "status": "ok",
|
|
173
|
+
# "txid": "OTI672-HJFAO-XOIPPK"
|
|
174
|
+
# }
|
|
175
|
+
#
|
|
176
|
+
order = self.parse_order(message)
|
|
177
|
+
messageHash = self.safe_value(message, 'reqid')
|
|
178
|
+
client.resolve(order, messageHash)
|
|
179
|
+
|
|
180
|
+
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
|
|
181
|
+
"""
|
|
182
|
+
edit a trade order
|
|
183
|
+
:see: https://docs.kraken.com/websockets/#message-editOrder
|
|
184
|
+
:param str id: order id
|
|
185
|
+
:param str symbol: unified symbol of the market to create an order in
|
|
186
|
+
:param str type: 'market' or 'limit'
|
|
187
|
+
:param str side: 'buy' or 'sell'
|
|
188
|
+
:param float amount: how much of the currency you want to trade in units of the base currency
|
|
189
|
+
:param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
190
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
191
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
192
|
+
"""
|
|
193
|
+
await self.load_markets()
|
|
194
|
+
token = await self.authenticate()
|
|
195
|
+
market = self.market(symbol)
|
|
196
|
+
url = self.urls['api']['ws']['private']
|
|
197
|
+
requestId = self.request_id()
|
|
198
|
+
messageHash = requestId
|
|
199
|
+
request: dict = {
|
|
200
|
+
'event': 'editOrder',
|
|
201
|
+
'token': token,
|
|
202
|
+
'reqid': requestId,
|
|
203
|
+
'orderid': id,
|
|
204
|
+
'pair': market['wsId'],
|
|
205
|
+
}
|
|
206
|
+
if amount is not None:
|
|
207
|
+
request['volume'] = self.amount_to_precision(symbol, amount)
|
|
208
|
+
request, params = self.orderRequest('editOrderWs', symbol, type, request, amount, price, params)
|
|
209
|
+
return await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
210
|
+
|
|
211
|
+
async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
|
|
212
|
+
"""
|
|
213
|
+
:see: https://docs.kraken.com/websockets/#message-cancelOrder
|
|
214
|
+
cancel multiple orders
|
|
215
|
+
:param str[] ids: order ids
|
|
216
|
+
:param str symbol: unified market symbol, default is None
|
|
217
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
218
|
+
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
219
|
+
"""
|
|
220
|
+
await self.load_markets()
|
|
221
|
+
token = await self.authenticate()
|
|
222
|
+
url = self.urls['api']['ws']['private']
|
|
223
|
+
requestId = self.request_id()
|
|
224
|
+
messageHash = requestId
|
|
225
|
+
request: dict = {
|
|
226
|
+
'event': 'cancelOrder',
|
|
227
|
+
'token': token,
|
|
228
|
+
'reqid': requestId,
|
|
229
|
+
'txid': ids,
|
|
230
|
+
}
|
|
231
|
+
return await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
232
|
+
|
|
233
|
+
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
234
|
+
"""
|
|
235
|
+
:see: https://docs.kraken.com/websockets/#message-cancelOrder
|
|
236
|
+
cancels an open order
|
|
237
|
+
:param str id: order id
|
|
238
|
+
:param str symbol: unified symbol of the market the order was made in
|
|
239
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
240
|
+
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
241
|
+
"""
|
|
242
|
+
await self.load_markets()
|
|
243
|
+
token = await self.authenticate()
|
|
244
|
+
url = self.urls['api']['ws']['private']
|
|
245
|
+
requestId = self.request_id()
|
|
246
|
+
messageHash = requestId
|
|
247
|
+
clientOrderId = self.safe_value_2(params, 'userref', 'clientOrderId', id)
|
|
248
|
+
params = self.omit(params, ['userref', 'clientOrderId'])
|
|
249
|
+
request: dict = {
|
|
250
|
+
'event': 'cancelOrder',
|
|
251
|
+
'token': token,
|
|
252
|
+
'reqid': requestId,
|
|
253
|
+
'txid': [clientOrderId],
|
|
254
|
+
}
|
|
255
|
+
return await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
256
|
+
|
|
257
|
+
def handle_cancel_order(self, client, message):
|
|
258
|
+
#
|
|
259
|
+
# success
|
|
260
|
+
# {
|
|
261
|
+
# "event": "cancelOrderStatus",
|
|
262
|
+
# "status": "ok"
|
|
263
|
+
# "reqid": 1,
|
|
264
|
+
# }
|
|
265
|
+
#
|
|
266
|
+
reqId = self.safe_value(message, 'reqid')
|
|
267
|
+
client.resolve(message, reqId)
|
|
268
|
+
|
|
269
|
+
async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
|
|
270
|
+
"""
|
|
271
|
+
:see: https://docs.kraken.com/websockets/#message-cancelAll
|
|
272
|
+
cancel all open orders
|
|
273
|
+
:param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
|
|
274
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
275
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
276
|
+
"""
|
|
277
|
+
if symbol is not None:
|
|
278
|
+
raise NotSupported(self.id + ' cancelAllOrdersWs() does not support cancelling orders in a specific market.')
|
|
279
|
+
await self.load_markets()
|
|
280
|
+
token = await self.authenticate()
|
|
281
|
+
url = self.urls['api']['ws']['private']
|
|
282
|
+
requestId = self.request_id()
|
|
283
|
+
messageHash = requestId
|
|
284
|
+
request: dict = {
|
|
285
|
+
'event': 'cancelAll',
|
|
286
|
+
'token': token,
|
|
287
|
+
'reqid': requestId,
|
|
288
|
+
}
|
|
289
|
+
return await self.watch(url, messageHash, self.extend(request, params), messageHash)
|
|
290
|
+
|
|
291
|
+
def handle_cancel_all_orders(self, client, message):
|
|
292
|
+
#
|
|
293
|
+
# {
|
|
294
|
+
# "count": 2,
|
|
295
|
+
# "event": "cancelAllStatus",
|
|
296
|
+
# "status": "ok",
|
|
297
|
+
# "reqId": 1
|
|
298
|
+
# }
|
|
299
|
+
#
|
|
300
|
+
reqId = self.safe_value(message, 'reqid')
|
|
301
|
+
client.resolve(message, reqId)
|
|
302
|
+
|
|
303
|
+
def handle_ticker(self, client, message, subscription):
|
|
304
|
+
#
|
|
305
|
+
# [
|
|
306
|
+
# 0, # channelID
|
|
307
|
+
# {
|
|
308
|
+
# "a": ["5525.40000", 1, "1.000"], # ask, wholeAskVolume, askVolume
|
|
309
|
+
# "b": ["5525.10000", 1, "1.000"], # bid, wholeBidVolume, bidVolume
|
|
310
|
+
# "c": ["5525.10000", "0.00398963"], # closing price, volume
|
|
311
|
+
# "h": ["5783.00000", "5783.00000"], # high price today, high price 24h ago
|
|
312
|
+
# "l": ["5505.00000", "5505.00000"], # low price today, low price 24h ago
|
|
313
|
+
# "o": ["5760.70000", "5763.40000"], # open price today, open price 24h ago
|
|
314
|
+
# "p": ["5631.44067", "5653.78939"], # vwap today, vwap 24h ago
|
|
315
|
+
# "t": [11493, 16267], # number of trades today, 24 hours ago
|
|
316
|
+
# "v": ["2634.11501494", "3591.17907851"], # volume today, volume 24 hours ago
|
|
317
|
+
# },
|
|
318
|
+
# "ticker",
|
|
319
|
+
# "XBT/USD"
|
|
320
|
+
# ]
|
|
321
|
+
#
|
|
322
|
+
wsName = message[3]
|
|
323
|
+
market = self.safe_value(self.options['marketsByWsName'], wsName)
|
|
324
|
+
symbol = market['symbol']
|
|
325
|
+
messageHash = self.get_message_hash('ticker', None, symbol)
|
|
326
|
+
ticker = message[1]
|
|
327
|
+
vwap = self.safe_string(ticker['p'], 0)
|
|
328
|
+
quoteVolume = None
|
|
329
|
+
baseVolume = self.safe_string(ticker['v'], 0)
|
|
330
|
+
if baseVolume is not None and vwap is not None:
|
|
331
|
+
quoteVolume = Precise.string_mul(baseVolume, vwap)
|
|
332
|
+
last = self.safe_string(ticker['c'], 0)
|
|
333
|
+
result = self.safe_ticker({
|
|
334
|
+
'symbol': symbol,
|
|
335
|
+
'timestamp': None,
|
|
336
|
+
'datetime': None,
|
|
337
|
+
'high': self.safe_string(ticker['h'], 0),
|
|
338
|
+
'low': self.safe_string(ticker['l'], 0),
|
|
339
|
+
'bid': self.safe_string(ticker['b'], 0),
|
|
340
|
+
'bidVolume': self.safe_string(ticker['b'], 2),
|
|
341
|
+
'ask': self.safe_string(ticker['a'], 0),
|
|
342
|
+
'askVolume': self.safe_string(ticker['a'], 2),
|
|
343
|
+
'vwap': vwap,
|
|
344
|
+
'open': self.safe_string(ticker['o'], 0),
|
|
345
|
+
'close': last,
|
|
346
|
+
'last': last,
|
|
347
|
+
'previousClose': None,
|
|
348
|
+
'change': None,
|
|
349
|
+
'percentage': None,
|
|
350
|
+
'average': None,
|
|
351
|
+
'baseVolume': baseVolume,
|
|
352
|
+
'quoteVolume': quoteVolume,
|
|
353
|
+
'info': ticker,
|
|
354
|
+
})
|
|
355
|
+
self.tickers[symbol] = result
|
|
356
|
+
client.resolve(result, messageHash)
|
|
357
|
+
|
|
358
|
+
def handle_trades(self, client: Client, message, subscription):
|
|
359
|
+
#
|
|
360
|
+
# [
|
|
361
|
+
# 0, # channelID
|
|
362
|
+
# [ # price volume time side type misc
|
|
363
|
+
# ["5541.20000", "0.15850568", "1534614057.321596", "s", "l", ""],
|
|
364
|
+
# ["6060.00000", "0.02455000", "1534614057.324998", "b", "l", ""],
|
|
365
|
+
# ],
|
|
366
|
+
# "trade",
|
|
367
|
+
# "XBT/USD"
|
|
368
|
+
# ]
|
|
369
|
+
#
|
|
370
|
+
wsName = self.safe_string(message, 3)
|
|
371
|
+
name = self.safe_string(message, 2)
|
|
372
|
+
market = self.safe_value(self.options['marketsByWsName'], wsName)
|
|
373
|
+
symbol = market['symbol']
|
|
374
|
+
messageHash = self.get_message_hash(name, None, symbol)
|
|
375
|
+
stored = self.safe_value(self.trades, symbol)
|
|
376
|
+
if stored is None:
|
|
377
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
378
|
+
stored = ArrayCache(limit)
|
|
379
|
+
self.trades[symbol] = stored
|
|
380
|
+
trades = self.safe_value(message, 1, [])
|
|
381
|
+
parsed = self.parse_trades(trades, market)
|
|
382
|
+
for i in range(0, len(parsed)):
|
|
383
|
+
stored.append(parsed[i])
|
|
384
|
+
client.resolve(stored, messageHash)
|
|
385
|
+
|
|
386
|
+
def handle_ohlcv(self, client: Client, message, subscription):
|
|
387
|
+
#
|
|
388
|
+
# [
|
|
389
|
+
# 216, # channelID
|
|
390
|
+
# [
|
|
391
|
+
# "1574454214.962096", # Time, seconds since epoch
|
|
392
|
+
# "1574454240.000000", # End timestamp of the interval
|
|
393
|
+
# "0.020970", # Open price at midnight UTC
|
|
394
|
+
# "0.020970", # Intraday high price
|
|
395
|
+
# "0.020970", # Intraday low price
|
|
396
|
+
# "0.020970", # Closing price at midnight UTC
|
|
397
|
+
# "0.020970", # Volume weighted average price
|
|
398
|
+
# "0.08636138", # Accumulated volume today
|
|
399
|
+
# 1, # Number of trades today
|
|
400
|
+
# ],
|
|
401
|
+
# "ohlc-1", # Channel Name of subscription
|
|
402
|
+
# "ETH/XBT", # Asset pair
|
|
403
|
+
# ]
|
|
404
|
+
#
|
|
405
|
+
info = self.safe_value(subscription, 'subscription', {})
|
|
406
|
+
interval = self.safe_integer(info, 'interval')
|
|
407
|
+
name = self.safe_string(info, 'name')
|
|
408
|
+
wsName = self.safe_string(message, 3)
|
|
409
|
+
market = self.safe_value(self.options['marketsByWsName'], wsName)
|
|
410
|
+
symbol = market['symbol']
|
|
411
|
+
timeframe = self.find_timeframe(interval)
|
|
412
|
+
duration = self.parse_timeframe(timeframe)
|
|
413
|
+
if timeframe is not None:
|
|
414
|
+
candle = self.safe_value(message, 1)
|
|
415
|
+
messageHash = name + ':' + timeframe + ':' + wsName
|
|
416
|
+
timestamp = self.safe_float(candle, 1)
|
|
417
|
+
timestamp -= duration
|
|
418
|
+
ts = self.parse_to_int(timestamp * 1000)
|
|
419
|
+
result = [
|
|
420
|
+
ts,
|
|
421
|
+
self.safe_float(candle, 2),
|
|
422
|
+
self.safe_float(candle, 3),
|
|
423
|
+
self.safe_float(candle, 4),
|
|
424
|
+
self.safe_float(candle, 5),
|
|
425
|
+
self.safe_float(candle, 7),
|
|
426
|
+
]
|
|
427
|
+
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
|
428
|
+
stored = self.safe_value(self.ohlcvs[symbol], timeframe)
|
|
429
|
+
if stored is None:
|
|
430
|
+
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
|
431
|
+
stored = ArrayCacheByTimestamp(limit)
|
|
432
|
+
self.ohlcvs[symbol][timeframe] = stored
|
|
433
|
+
stored.append(result)
|
|
434
|
+
client.resolve(stored, messageHash)
|
|
435
|
+
|
|
436
|
+
def request_id(self):
|
|
437
|
+
# their support said that reqid must be an int32, not documented
|
|
438
|
+
reqid = self.sum(self.safe_integer(self.options, 'reqid', 0), 1)
|
|
439
|
+
self.options['reqid'] = reqid
|
|
440
|
+
return reqid
|
|
441
|
+
|
|
442
|
+
async def watch_public(self, name, symbol, params={}):
|
|
443
|
+
await self.load_markets()
|
|
444
|
+
market = self.market(symbol)
|
|
445
|
+
wsName = self.safe_value(market['info'], 'wsname')
|
|
446
|
+
messageHash = name + ':' + wsName
|
|
447
|
+
url = self.urls['api']['ws']['public']
|
|
448
|
+
requestId = self.request_id()
|
|
449
|
+
subscribe: dict = {
|
|
450
|
+
'event': 'subscribe',
|
|
451
|
+
'reqid': requestId,
|
|
452
|
+
'pair': [
|
|
453
|
+
wsName,
|
|
454
|
+
],
|
|
455
|
+
'subscription': {
|
|
456
|
+
'name': name,
|
|
457
|
+
},
|
|
458
|
+
}
|
|
459
|
+
request = self.deep_extend(subscribe, params)
|
|
460
|
+
return await self.watch(url, messageHash, request, messageHash)
|
|
461
|
+
|
|
462
|
+
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
463
|
+
"""
|
|
464
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
465
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
466
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
467
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
468
|
+
"""
|
|
469
|
+
await self.load_markets()
|
|
470
|
+
symbol = self.symbol(symbol)
|
|
471
|
+
tickers = await self.watch_tickers([symbol], params)
|
|
472
|
+
return tickers[symbol]
|
|
473
|
+
|
|
474
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
475
|
+
"""
|
|
476
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
477
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
478
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
479
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
480
|
+
"""
|
|
481
|
+
await self.load_markets()
|
|
482
|
+
symbols = self.market_symbols(symbols, None, False)
|
|
483
|
+
ticker = await self.watch_multi_helper('ticker', 'ticker', symbols, None, params)
|
|
484
|
+
if self.newUpdates:
|
|
485
|
+
result: dict = {}
|
|
486
|
+
result[ticker['symbol']] = ticker
|
|
487
|
+
return result
|
|
488
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
|
489
|
+
|
|
490
|
+
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
491
|
+
"""
|
|
492
|
+
get the list of most recent trades for a particular symbol
|
|
493
|
+
:see: https://docs.kraken.com/websockets/#message-trade
|
|
494
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
|
495
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
496
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
497
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
498
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
499
|
+
"""
|
|
500
|
+
return await self.watch_trades_for_symbols([symbol], since, limit, params)
|
|
501
|
+
|
|
502
|
+
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
503
|
+
"""
|
|
504
|
+
:see: https://docs.kraken.com/websockets/#message-trade
|
|
505
|
+
get the list of most recent trades for a list of symbols
|
|
506
|
+
:param str[] symbols: unified symbol of the market to fetch trades for
|
|
507
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
508
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
509
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
510
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
511
|
+
"""
|
|
512
|
+
trades = await self.watch_multi_helper('trade', 'trade', symbols, None, params)
|
|
513
|
+
if self.newUpdates:
|
|
514
|
+
first = self.safe_list(trades, 0)
|
|
515
|
+
tradeSymbol = self.safe_string(first, 'symbol')
|
|
516
|
+
limit = trades.getLimit(tradeSymbol, limit)
|
|
517
|
+
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
|
518
|
+
|
|
519
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
520
|
+
"""
|
|
521
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
522
|
+
:see: https://docs.kraken.com/websockets/#message-book
|
|
523
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
|
524
|
+
:param int [limit]: the maximum amount of order book entries to return
|
|
525
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
526
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
527
|
+
"""
|
|
528
|
+
return await self.watch_order_book_for_symbols([symbol], limit, params)
|
|
529
|
+
|
|
530
|
+
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
|
531
|
+
"""
|
|
532
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
533
|
+
:see: https://docs.kraken.com/websockets/#message-book
|
|
534
|
+
:param str[] symbols: unified array of symbols
|
|
535
|
+
:param int [limit]: the maximum amount of order book entries to return
|
|
536
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
537
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
538
|
+
"""
|
|
539
|
+
request: dict = {}
|
|
540
|
+
if limit is not None:
|
|
541
|
+
if self.in_array(limit, [10, 25, 100, 500, 1000]):
|
|
542
|
+
request['subscription'] = {
|
|
543
|
+
'depth': limit, # default 10, valid options 10, 25, 100, 500, 1000
|
|
544
|
+
}
|
|
545
|
+
else:
|
|
546
|
+
raise NotSupported(self.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only')
|
|
547
|
+
orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(request, params))
|
|
548
|
+
return orderbook.limit()
|
|
549
|
+
|
|
550
|
+
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
551
|
+
"""
|
|
552
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
553
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
554
|
+
:param str timeframe: the length of time each candle represents
|
|
555
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
|
556
|
+
:param int [limit]: the maximum amount of candles to fetch
|
|
557
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
558
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
559
|
+
"""
|
|
560
|
+
await self.load_markets()
|
|
561
|
+
name = 'ohlc'
|
|
562
|
+
market = self.market(symbol)
|
|
563
|
+
symbol = market['symbol']
|
|
564
|
+
wsName = self.safe_value(market['info'], 'wsname')
|
|
565
|
+
messageHash = name + ':' + timeframe + ':' + wsName
|
|
566
|
+
url = self.urls['api']['ws']['public']
|
|
567
|
+
requestId = self.request_id()
|
|
568
|
+
subscribe: dict = {
|
|
569
|
+
'event': 'subscribe',
|
|
570
|
+
'reqid': requestId,
|
|
571
|
+
'pair': [
|
|
572
|
+
wsName,
|
|
573
|
+
],
|
|
574
|
+
'subscription': {
|
|
575
|
+
'name': name,
|
|
576
|
+
'interval': self.safe_value(self.timeframes, timeframe, timeframe),
|
|
577
|
+
},
|
|
578
|
+
}
|
|
579
|
+
request = self.deep_extend(subscribe, params)
|
|
580
|
+
ohlcv = await self.watch(url, messageHash, request, messageHash)
|
|
581
|
+
if self.newUpdates:
|
|
582
|
+
limit = ohlcv.getLimit(symbol, limit)
|
|
583
|
+
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
|
584
|
+
|
|
585
|
+
async def load_markets(self, reload=False, params={}):
|
|
586
|
+
markets = await super(kraken, self).load_markets(reload, params)
|
|
587
|
+
marketsByWsName = self.safe_value(self.options, 'marketsByWsName')
|
|
588
|
+
if (marketsByWsName is None) or reload:
|
|
589
|
+
marketsByWsName = {}
|
|
590
|
+
for i in range(0, len(self.symbols)):
|
|
591
|
+
symbol = self.symbols[i]
|
|
592
|
+
market = self.markets[symbol]
|
|
593
|
+
if market['darkpool']:
|
|
594
|
+
info = self.safe_value(market, 'info', {})
|
|
595
|
+
altname = self.safe_string(info, 'altname')
|
|
596
|
+
wsName = altname[0:3] + '/' + altname[3:]
|
|
597
|
+
marketsByWsName[wsName] = market
|
|
598
|
+
else:
|
|
599
|
+
info = self.safe_value(market, 'info', {})
|
|
600
|
+
wsName = self.safe_string(info, 'wsname')
|
|
601
|
+
marketsByWsName[wsName] = market
|
|
602
|
+
self.options['marketsByWsName'] = marketsByWsName
|
|
603
|
+
return markets
|
|
604
|
+
|
|
605
|
+
async def watch_heartbeat(self, params={}):
|
|
606
|
+
await self.load_markets()
|
|
607
|
+
event = 'heartbeat'
|
|
608
|
+
url = self.urls['api']['ws']['public']
|
|
609
|
+
return await self.watch(url, event)
|
|
610
|
+
|
|
611
|
+
def handle_heartbeat(self, client: Client, message):
|
|
612
|
+
#
|
|
613
|
+
# every second(approx) if no other updates are sent
|
|
614
|
+
#
|
|
615
|
+
# {"event": "heartbeat"}
|
|
616
|
+
#
|
|
617
|
+
event = self.safe_string(message, 'event')
|
|
618
|
+
client.resolve(message, event)
|
|
619
|
+
|
|
620
|
+
def handle_order_book(self, client: Client, message, subscription):
|
|
621
|
+
#
|
|
622
|
+
# first message(snapshot)
|
|
623
|
+
#
|
|
624
|
+
# [
|
|
625
|
+
# 1234, # channelID
|
|
626
|
+
# {
|
|
627
|
+
# "as": [
|
|
628
|
+
# ["5541.30000", "2.50700000", "1534614248.123678"],
|
|
629
|
+
# ["5541.80000", "0.33000000", "1534614098.345543"],
|
|
630
|
+
# ["5542.70000", "0.64700000", "1534614244.654432"]
|
|
631
|
+
# ],
|
|
632
|
+
# "bs": [
|
|
633
|
+
# ["5541.20000", "1.52900000", "1534614248.765567"],
|
|
634
|
+
# ["5539.90000", "0.30000000", "1534614241.769870"],
|
|
635
|
+
# ["5539.50000", "5.00000000", "1534613831.243486"]
|
|
636
|
+
# ]
|
|
637
|
+
# },
|
|
638
|
+
# "book-10",
|
|
639
|
+
# "XBT/USD"
|
|
640
|
+
# ]
|
|
641
|
+
#
|
|
642
|
+
# subsequent updates
|
|
643
|
+
#
|
|
644
|
+
# [
|
|
645
|
+
# 1234,
|
|
646
|
+
# { # optional
|
|
647
|
+
# "a": [
|
|
648
|
+
# ["5541.30000", "2.50700000", "1534614248.456738"],
|
|
649
|
+
# ["5542.50000", "0.40100000", "1534614248.456738"]
|
|
650
|
+
# ]
|
|
651
|
+
# },
|
|
652
|
+
# { # optional
|
|
653
|
+
# "b": [
|
|
654
|
+
# ["5541.30000", "0.00000000", "1534614335.345903"]
|
|
655
|
+
# ]
|
|
656
|
+
# },
|
|
657
|
+
# "book-10",
|
|
658
|
+
# "XBT/USD"
|
|
659
|
+
# ]
|
|
660
|
+
#
|
|
661
|
+
messageLength = len(message)
|
|
662
|
+
wsName = message[messageLength - 1]
|
|
663
|
+
bookDepthString = message[messageLength - 2]
|
|
664
|
+
parts = bookDepthString.split('-')
|
|
665
|
+
depth = self.safe_integer(parts, 1, 10)
|
|
666
|
+
market = self.safe_value(self.options['marketsByWsName'], wsName)
|
|
667
|
+
symbol = market['symbol']
|
|
668
|
+
timestamp = None
|
|
669
|
+
messageHash = self.get_message_hash('orderbook', None, symbol)
|
|
670
|
+
# if self is a snapshot
|
|
671
|
+
if 'as' in message[1]:
|
|
672
|
+
# todo get depth from marketsByWsName
|
|
673
|
+
self.orderbooks[symbol] = self.order_book({}, depth)
|
|
674
|
+
orderbook = self.orderbooks[symbol]
|
|
675
|
+
sides: dict = {
|
|
676
|
+
'as': 'asks',
|
|
677
|
+
'bs': 'bids',
|
|
678
|
+
}
|
|
679
|
+
keys = list(sides.keys())
|
|
680
|
+
for i in range(0, len(keys)):
|
|
681
|
+
key = keys[i]
|
|
682
|
+
side = sides[key]
|
|
683
|
+
bookside = orderbook[side]
|
|
684
|
+
deltas = self.safe_value(message[1], key, [])
|
|
685
|
+
timestamp = self.custom_handle_deltas(bookside, deltas, timestamp)
|
|
686
|
+
orderbook['symbol'] = symbol
|
|
687
|
+
orderbook['timestamp'] = timestamp
|
|
688
|
+
orderbook['datetime'] = self.iso8601(timestamp)
|
|
689
|
+
client.resolve(orderbook, messageHash)
|
|
690
|
+
else:
|
|
691
|
+
orderbook = self.orderbooks[symbol]
|
|
692
|
+
# else, if self is an orderbook update
|
|
693
|
+
a = None
|
|
694
|
+
b = None
|
|
695
|
+
c = None
|
|
696
|
+
if messageLength == 5:
|
|
697
|
+
a = self.safe_value(message[1], 'a', [])
|
|
698
|
+
b = self.safe_value(message[2], 'b', [])
|
|
699
|
+
c = self.safe_integer(message[1], 'c')
|
|
700
|
+
c = self.safe_integer(message[2], 'c', c)
|
|
701
|
+
else:
|
|
702
|
+
c = self.safe_integer(message[1], 'c')
|
|
703
|
+
if 'a' in message[1]:
|
|
704
|
+
a = self.safe_value(message[1], 'a', [])
|
|
705
|
+
else:
|
|
706
|
+
b = self.safe_value(message[1], 'b', [])
|
|
707
|
+
storedAsks = orderbook['asks']
|
|
708
|
+
storedBids = orderbook['bids']
|
|
709
|
+
example = None
|
|
710
|
+
if a is not None:
|
|
711
|
+
timestamp = self.custom_handle_deltas(storedAsks, a, timestamp)
|
|
712
|
+
example = self.safe_value(a, 0)
|
|
713
|
+
if b is not None:
|
|
714
|
+
timestamp = self.custom_handle_deltas(storedBids, b, timestamp)
|
|
715
|
+
example = self.safe_value(b, 0)
|
|
716
|
+
# don't remove self line or I will poop on your face
|
|
717
|
+
orderbook.limit()
|
|
718
|
+
checksum = self.safe_bool(self.options, 'checksum', True)
|
|
719
|
+
if checksum:
|
|
720
|
+
priceString = self.safe_string(example, 0)
|
|
721
|
+
amountString = self.safe_string(example, 1)
|
|
722
|
+
priceParts = priceString.split('.')
|
|
723
|
+
amountParts = amountString.split('.')
|
|
724
|
+
priceLength = len(priceParts[1]) - 0
|
|
725
|
+
amountLength = len(amountParts[1]) - 0
|
|
726
|
+
payloadArray = []
|
|
727
|
+
if c is not None:
|
|
728
|
+
for i in range(0, 10):
|
|
729
|
+
formatted = self.format_number(storedAsks[i][0], priceLength) + self.format_number(storedAsks[i][1], amountLength)
|
|
730
|
+
payloadArray.append(formatted)
|
|
731
|
+
for i in range(0, 10):
|
|
732
|
+
formatted = self.format_number(storedBids[i][0], priceLength) + self.format_number(storedBids[i][1], amountLength)
|
|
733
|
+
payloadArray.append(formatted)
|
|
734
|
+
payload = ''.join(payloadArray)
|
|
735
|
+
localChecksum = self.crc32(payload, False)
|
|
736
|
+
if localChecksum != c:
|
|
737
|
+
error = InvalidNonce(self.id + ' invalid checksum')
|
|
738
|
+
del client.subscriptions[messageHash]
|
|
739
|
+
del self.orderbooks[symbol]
|
|
740
|
+
client.reject(error, messageHash)
|
|
741
|
+
return
|
|
742
|
+
orderbook['symbol'] = symbol
|
|
743
|
+
orderbook['timestamp'] = timestamp
|
|
744
|
+
orderbook['datetime'] = self.iso8601(timestamp)
|
|
745
|
+
client.resolve(orderbook, messageHash)
|
|
746
|
+
|
|
747
|
+
def format_number(self, n, length):
|
|
748
|
+
stringNumber = self.number_to_string(n)
|
|
749
|
+
parts = stringNumber.split('.')
|
|
750
|
+
integer = self.safe_string(parts, 0)
|
|
751
|
+
decimals = self.safe_string(parts, 1, '')
|
|
752
|
+
paddedDecimals = decimals.ljust(length, '0')
|
|
753
|
+
joined = integer + paddedDecimals
|
|
754
|
+
i = 0
|
|
755
|
+
while(joined[i] == '0'):
|
|
756
|
+
i += 1
|
|
757
|
+
if i > 0:
|
|
758
|
+
return joined[i:]
|
|
759
|
+
else:
|
|
760
|
+
return joined
|
|
761
|
+
|
|
762
|
+
def custom_handle_deltas(self, bookside, deltas, timestamp=None):
|
|
763
|
+
for j in range(0, len(deltas)):
|
|
764
|
+
delta = deltas[j]
|
|
765
|
+
price = self.parse_number(delta[0])
|
|
766
|
+
amount = self.parse_number(delta[1])
|
|
767
|
+
oldTimestamp = timestamp if timestamp else 0
|
|
768
|
+
timestamp = max(oldTimestamp, self.parse_to_int(float(delta[2]) * 1000))
|
|
769
|
+
bookside.store(price, amount)
|
|
770
|
+
return timestamp
|
|
771
|
+
|
|
772
|
+
def handle_system_status(self, client: Client, message):
|
|
773
|
+
#
|
|
774
|
+
# todo: answer the question whether handleSystemStatus should be renamed
|
|
775
|
+
# and unified for any usage pattern that
|
|
776
|
+
# involves system status and maintenance updates
|
|
777
|
+
#
|
|
778
|
+
# {
|
|
779
|
+
# "connectionID": 15527282728335292000,
|
|
780
|
+
# "event": "systemStatus",
|
|
781
|
+
# "status": "online", # online|maintenance|(custom status tbd)
|
|
782
|
+
# "version": "0.2.0"
|
|
783
|
+
# }
|
|
784
|
+
#
|
|
785
|
+
return message
|
|
786
|
+
|
|
787
|
+
async def authenticate(self, params={}):
|
|
788
|
+
url = self.urls['api']['ws']['private']
|
|
789
|
+
client = self.client(url)
|
|
790
|
+
authenticated = 'authenticated'
|
|
791
|
+
subscription = self.safe_value(client.subscriptions, authenticated)
|
|
792
|
+
if subscription is None:
|
|
793
|
+
response = await self.privatePostGetWebSocketsToken(params)
|
|
794
|
+
#
|
|
795
|
+
# {
|
|
796
|
+
# "error":[],
|
|
797
|
+
# "result":{
|
|
798
|
+
# "token":"xeAQ\/RCChBYNVh53sTv1yZ5H4wIbwDF20PiHtTF+4UI",
|
|
799
|
+
# "expires":900
|
|
800
|
+
# }
|
|
801
|
+
# }
|
|
802
|
+
#
|
|
803
|
+
subscription = self.safe_value(response, 'result')
|
|
804
|
+
client.subscriptions[authenticated] = subscription
|
|
805
|
+
return self.safe_string(subscription, 'token')
|
|
806
|
+
|
|
807
|
+
async def watch_private(self, name, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
808
|
+
await self.load_markets()
|
|
809
|
+
token = await self.authenticate()
|
|
810
|
+
subscriptionHash = name
|
|
811
|
+
messageHash = name
|
|
812
|
+
if symbol is not None:
|
|
813
|
+
symbol = self.symbol(symbol)
|
|
814
|
+
messageHash += ':' + symbol
|
|
815
|
+
url = self.urls['api']['ws']['private']
|
|
816
|
+
requestId = self.request_id()
|
|
817
|
+
subscribe: dict = {
|
|
818
|
+
'event': 'subscribe',
|
|
819
|
+
'reqid': requestId,
|
|
820
|
+
'subscription': {
|
|
821
|
+
'name': name,
|
|
822
|
+
'token': token,
|
|
823
|
+
},
|
|
824
|
+
}
|
|
825
|
+
request = self.deep_extend(subscribe, params)
|
|
826
|
+
result = await self.watch(url, messageHash, request, subscriptionHash)
|
|
827
|
+
if self.newUpdates:
|
|
828
|
+
limit = result.getLimit(symbol, limit)
|
|
829
|
+
return self.filter_by_symbol_since_limit(result, symbol, since, limit)
|
|
830
|
+
|
|
831
|
+
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
832
|
+
"""
|
|
833
|
+
watches information on multiple trades made by the user
|
|
834
|
+
:param str symbol: unified market symbol of the market trades were made in
|
|
835
|
+
:param int [since]: the earliest time in ms to fetch trades for
|
|
836
|
+
:param int [limit]: the maximum number of trade structures to retrieve
|
|
837
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
838
|
+
:returns dict[]: a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure
|
|
839
|
+
"""
|
|
840
|
+
return await self.watch_private('ownTrades', symbol, since, limit, params)
|
|
841
|
+
|
|
842
|
+
def handle_my_trades(self, client: Client, message, subscription=None):
|
|
843
|
+
#
|
|
844
|
+
# [
|
|
845
|
+
# [
|
|
846
|
+
# {
|
|
847
|
+
# "TT5UC3-GOIRW-6AZZ6R": {
|
|
848
|
+
# "cost": "1493.90107",
|
|
849
|
+
# "fee": "3.88415",
|
|
850
|
+
# "margin": "0.00000",
|
|
851
|
+
# "ordertxid": "OTLAS3-RRHUF-NDWH5A",
|
|
852
|
+
# "ordertype": "market",
|
|
853
|
+
# "pair": "XBT/USDT",
|
|
854
|
+
# "postxid": "TKH2SE-M7IF5-CFI7LT",
|
|
855
|
+
# "price": "6851.50005",
|
|
856
|
+
# "time": "1586822919.335498",
|
|
857
|
+
# "type": "sell",
|
|
858
|
+
# "vol": "0.21804000"
|
|
859
|
+
# }
|
|
860
|
+
# },
|
|
861
|
+
# {
|
|
862
|
+
# "TIY6G4-LKLAI-Y3GD4A": {
|
|
863
|
+
# "cost": "22.17134",
|
|
864
|
+
# "fee": "0.05765",
|
|
865
|
+
# "margin": "0.00000",
|
|
866
|
+
# "ordertxid": "ODQXS7-MOLK6-ICXKAA",
|
|
867
|
+
# "ordertype": "market",
|
|
868
|
+
# "pair": "ETH/USD",
|
|
869
|
+
# "postxid": "TKH2SE-M7IF5-CFI7LT",
|
|
870
|
+
# "price": "169.97999",
|
|
871
|
+
# "time": "1586340530.895739",
|
|
872
|
+
# "type": "buy",
|
|
873
|
+
# "vol": "0.13043500"
|
|
874
|
+
# }
|
|
875
|
+
# },
|
|
876
|
+
# ],
|
|
877
|
+
# "ownTrades",
|
|
878
|
+
# {sequence: 1}
|
|
879
|
+
# ]
|
|
880
|
+
#
|
|
881
|
+
allTrades = self.safe_value(message, 0, [])
|
|
882
|
+
allTradesLength = len(allTrades)
|
|
883
|
+
if allTradesLength > 0:
|
|
884
|
+
if self.myTrades is None:
|
|
885
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
886
|
+
self.myTrades = ArrayCache(limit)
|
|
887
|
+
stored = self.myTrades
|
|
888
|
+
symbols: dict = {}
|
|
889
|
+
for i in range(0, len(allTrades)):
|
|
890
|
+
trades = self.safe_value(allTrades, i, {})
|
|
891
|
+
ids = list(trades.keys())
|
|
892
|
+
for j in range(0, len(ids)):
|
|
893
|
+
id = ids[j]
|
|
894
|
+
trade = trades[id]
|
|
895
|
+
parsed = self.parse_ws_trade(self.extend({'id': id}, trade))
|
|
896
|
+
stored.append(parsed)
|
|
897
|
+
symbol = parsed['symbol']
|
|
898
|
+
symbols[symbol] = True
|
|
899
|
+
name = 'ownTrades'
|
|
900
|
+
client.resolve(self.myTrades, name)
|
|
901
|
+
keys = list(symbols.keys())
|
|
902
|
+
for i in range(0, len(keys)):
|
|
903
|
+
messageHash = name + ':' + keys[i]
|
|
904
|
+
client.resolve(self.myTrades, messageHash)
|
|
905
|
+
|
|
906
|
+
def parse_ws_trade(self, trade, market=None):
|
|
907
|
+
#
|
|
908
|
+
# {
|
|
909
|
+
# "id": "TIMIRG-WUNNE-RRJ6GT", # injected from outside
|
|
910
|
+
# "ordertxid": "OQRPN2-LRHFY-HIFA7D",
|
|
911
|
+
# "postxid": "TKH2SE-M7IF5-CFI7LT",
|
|
912
|
+
# "pair": "USDCUSDT",
|
|
913
|
+
# "time": 1586340086.457,
|
|
914
|
+
# "type": "sell",
|
|
915
|
+
# "ordertype": "market",
|
|
916
|
+
# "price": "0.99860000",
|
|
917
|
+
# "cost": "22.16892001",
|
|
918
|
+
# "fee": "0.04433784",
|
|
919
|
+
# "vol": "22.20000000",
|
|
920
|
+
# "margin": "0.00000000",
|
|
921
|
+
# "misc": ''
|
|
922
|
+
# }
|
|
923
|
+
#
|
|
924
|
+
# {
|
|
925
|
+
# "id": "TIY6G4-LKLAI-Y3GD4A",
|
|
926
|
+
# "cost": "22.17134",
|
|
927
|
+
# "fee": "0.05765",
|
|
928
|
+
# "margin": "0.00000",
|
|
929
|
+
# "ordertxid": "ODQXS7-MOLK6-ICXKAA",
|
|
930
|
+
# "ordertype": "market",
|
|
931
|
+
# "pair": "ETH/USD",
|
|
932
|
+
# "postxid": "TKH2SE-M7IF5-CFI7LT",
|
|
933
|
+
# "price": "169.97999",
|
|
934
|
+
# "time": "1586340530.895739",
|
|
935
|
+
# "type": "buy",
|
|
936
|
+
# "vol": "0.13043500"
|
|
937
|
+
# }
|
|
938
|
+
#
|
|
939
|
+
wsName = self.safe_string(trade, 'pair')
|
|
940
|
+
market = self.safe_value(self.options['marketsByWsName'], wsName, market)
|
|
941
|
+
symbol = None
|
|
942
|
+
orderId = self.safe_string(trade, 'ordertxid')
|
|
943
|
+
id = self.safe_string_2(trade, 'id', 'postxid')
|
|
944
|
+
timestamp = self.safe_timestamp(trade, 'time')
|
|
945
|
+
side = self.safe_string(trade, 'type')
|
|
946
|
+
type = self.safe_string(trade, 'ordertype')
|
|
947
|
+
price = self.safe_float(trade, 'price')
|
|
948
|
+
amount = self.safe_float(trade, 'vol')
|
|
949
|
+
cost = None
|
|
950
|
+
fee = None
|
|
951
|
+
if 'fee' in trade:
|
|
952
|
+
currency = None
|
|
953
|
+
if market is not None:
|
|
954
|
+
currency = market['quote']
|
|
955
|
+
fee = {
|
|
956
|
+
'cost': self.safe_float(trade, 'fee'),
|
|
957
|
+
'currency': currency,
|
|
958
|
+
}
|
|
959
|
+
if market is not None:
|
|
960
|
+
symbol = market['symbol']
|
|
961
|
+
if price is not None:
|
|
962
|
+
if amount is not None:
|
|
963
|
+
cost = price * amount
|
|
964
|
+
return {
|
|
965
|
+
'id': id,
|
|
966
|
+
'order': orderId,
|
|
967
|
+
'info': trade,
|
|
968
|
+
'timestamp': timestamp,
|
|
969
|
+
'datetime': self.iso8601(timestamp),
|
|
970
|
+
'symbol': symbol,
|
|
971
|
+
'type': type,
|
|
972
|
+
'side': side,
|
|
973
|
+
'takerOrMaker': None,
|
|
974
|
+
'price': price,
|
|
975
|
+
'amount': amount,
|
|
976
|
+
'cost': cost,
|
|
977
|
+
'fee': fee,
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
981
|
+
"""
|
|
982
|
+
:see: https://docs.kraken.com/websockets/#message-openOrders
|
|
983
|
+
watches information on multiple orders made by the user
|
|
984
|
+
:param str symbol: unified market symbol of the market orders were made in
|
|
985
|
+
:param int [since]: the earliest time in ms to fetch orders for
|
|
986
|
+
:param int [limit]: the maximum number of orde structures to retrieve
|
|
987
|
+
:param dict [params]: maximum number of orderic to the exchange API endpoint
|
|
988
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
989
|
+
"""
|
|
990
|
+
return await self.watch_private('openOrders', symbol, since, limit, params)
|
|
991
|
+
|
|
992
|
+
def handle_orders(self, client: Client, message, subscription=None):
|
|
993
|
+
#
|
|
994
|
+
# [
|
|
995
|
+
# [
|
|
996
|
+
# {
|
|
997
|
+
# "OGTT3Y-C6I3P-XRI6HX": {
|
|
998
|
+
# "cost": "0.00000",
|
|
999
|
+
# "descr": {
|
|
1000
|
+
# "close": "",
|
|
1001
|
+
# "leverage": "0:1",
|
|
1002
|
+
# "order": "sell 10.00345345 XBT/EUR @ limit 34.50000 with 0:1 leverage",
|
|
1003
|
+
# "ordertype": "limit",
|
|
1004
|
+
# "pair": "XBT/EUR",
|
|
1005
|
+
# "price": "34.50000",
|
|
1006
|
+
# "price2": "0.00000",
|
|
1007
|
+
# "type": "sell"
|
|
1008
|
+
# },
|
|
1009
|
+
# "expiretm": "0.000000",
|
|
1010
|
+
# "fee": "0.00000",
|
|
1011
|
+
# "limitprice": "34.50000",
|
|
1012
|
+
# "misc": "",
|
|
1013
|
+
# "oflags": "fcib",
|
|
1014
|
+
# "opentm": "0.000000",
|
|
1015
|
+
# "price": "34.50000",
|
|
1016
|
+
# "refid": "OKIVMP-5GVZN-Z2D2UA",
|
|
1017
|
+
# "starttm": "0.000000",
|
|
1018
|
+
# "status": "open",
|
|
1019
|
+
# "stopprice": "0.000000",
|
|
1020
|
+
# "userref": 0,
|
|
1021
|
+
# "vol": "10.00345345",
|
|
1022
|
+
# "vol_exec": "0.00000000"
|
|
1023
|
+
# }
|
|
1024
|
+
# },
|
|
1025
|
+
# {
|
|
1026
|
+
# "OGTT3Y-C6I3P-XRI6HX": {
|
|
1027
|
+
# "cost": "0.00000",
|
|
1028
|
+
# "descr": {
|
|
1029
|
+
# "close": "",
|
|
1030
|
+
# "leverage": "0:1",
|
|
1031
|
+
# "order": "sell 0.00000010 XBT/EUR @ limit 5334.60000 with 0:1 leverage",
|
|
1032
|
+
# "ordertype": "limit",
|
|
1033
|
+
# "pair": "XBT/EUR",
|
|
1034
|
+
# "price": "5334.60000",
|
|
1035
|
+
# "price2": "0.00000",
|
|
1036
|
+
# "type": "sell"
|
|
1037
|
+
# },
|
|
1038
|
+
# "expiretm": "0.000000",
|
|
1039
|
+
# "fee": "0.00000",
|
|
1040
|
+
# "limitprice": "5334.60000",
|
|
1041
|
+
# "misc": "",
|
|
1042
|
+
# "oflags": "fcib",
|
|
1043
|
+
# "opentm": "0.000000",
|
|
1044
|
+
# "price": "5334.60000",
|
|
1045
|
+
# "refid": "OKIVMP-5GVZN-Z2D2UA",
|
|
1046
|
+
# "starttm": "0.000000",
|
|
1047
|
+
# "status": "open",
|
|
1048
|
+
# "stopprice": "0.000000",
|
|
1049
|
+
# "userref": 0,
|
|
1050
|
+
# "vol": "0.00000010",
|
|
1051
|
+
# "vol_exec": "0.00000000"
|
|
1052
|
+
# }
|
|
1053
|
+
# },
|
|
1054
|
+
# ],
|
|
1055
|
+
# "openOrders",
|
|
1056
|
+
# {"sequence": 234}
|
|
1057
|
+
# ]
|
|
1058
|
+
#
|
|
1059
|
+
# status-change
|
|
1060
|
+
#
|
|
1061
|
+
# [
|
|
1062
|
+
# [
|
|
1063
|
+
# {"OGTT3Y-C6I3P-XRI6HX": {"status": "closed"}},
|
|
1064
|
+
# {"OGTT3Y-C6I3P-XRI6HX": {"status": "closed"}},
|
|
1065
|
+
# ],
|
|
1066
|
+
# "openOrders",
|
|
1067
|
+
# {"sequence": 59342}
|
|
1068
|
+
# ]
|
|
1069
|
+
#
|
|
1070
|
+
allOrders = self.safe_value(message, 0, [])
|
|
1071
|
+
allOrdersLength = len(allOrders)
|
|
1072
|
+
if allOrdersLength > 0:
|
|
1073
|
+
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
|
|
1074
|
+
if self.orders is None:
|
|
1075
|
+
self.orders = ArrayCacheBySymbolById(limit)
|
|
1076
|
+
stored = self.orders
|
|
1077
|
+
symbols: dict = {}
|
|
1078
|
+
for i in range(0, len(allOrders)):
|
|
1079
|
+
orders = self.safe_value(allOrders, i, {})
|
|
1080
|
+
ids = list(orders.keys())
|
|
1081
|
+
for j in range(0, len(ids)):
|
|
1082
|
+
id = ids[j]
|
|
1083
|
+
order = orders[id]
|
|
1084
|
+
parsed = self.parse_ws_order(order)
|
|
1085
|
+
parsed['id'] = id
|
|
1086
|
+
symbol = None
|
|
1087
|
+
symbolsByOrderId = self.safe_value(self.options, 'symbolsByOrderId', {})
|
|
1088
|
+
if parsed['symbol'] is not None:
|
|
1089
|
+
symbol = parsed['symbol']
|
|
1090
|
+
symbolsByOrderId[id] = symbol
|
|
1091
|
+
self.options['symbolsByOrderId'] = symbolsByOrderId
|
|
1092
|
+
else:
|
|
1093
|
+
symbol = self.safe_string(symbolsByOrderId, id)
|
|
1094
|
+
previousOrders = self.safe_value(stored.hashmap, symbol)
|
|
1095
|
+
previousOrder = self.safe_value(previousOrders, id)
|
|
1096
|
+
newOrder = parsed
|
|
1097
|
+
if previousOrder is not None:
|
|
1098
|
+
newRawOrder = self.extend(previousOrder['info'], newOrder['info'])
|
|
1099
|
+
newOrder = self.parse_ws_order(newRawOrder)
|
|
1100
|
+
newOrder['id'] = id
|
|
1101
|
+
length = len(stored)
|
|
1102
|
+
if length == limit and (previousOrder is None):
|
|
1103
|
+
first = stored[0]
|
|
1104
|
+
if first['id'] in symbolsByOrderId:
|
|
1105
|
+
del symbolsByOrderId[first['id']]
|
|
1106
|
+
stored.append(newOrder)
|
|
1107
|
+
symbols[symbol] = True
|
|
1108
|
+
name = 'openOrders'
|
|
1109
|
+
client.resolve(self.orders, name)
|
|
1110
|
+
keys = list(symbols.keys())
|
|
1111
|
+
for i in range(0, len(keys)):
|
|
1112
|
+
messageHash = name + ':' + keys[i]
|
|
1113
|
+
client.resolve(self.orders, messageHash)
|
|
1114
|
+
|
|
1115
|
+
def parse_ws_order(self, order, market=None):
|
|
1116
|
+
#
|
|
1117
|
+
# createOrder
|
|
1118
|
+
# {
|
|
1119
|
+
# "avg_price": "0.00000",
|
|
1120
|
+
# "cost": "0.00000",
|
|
1121
|
+
# "descr": {
|
|
1122
|
+
# "close": null,
|
|
1123
|
+
# "leverage": null,
|
|
1124
|
+
# "order": "sell 0.01000000 ETH/USDT @ limit 1900.00000",
|
|
1125
|
+
# "ordertype": "limit",
|
|
1126
|
+
# "pair": "ETH/USDT",
|
|
1127
|
+
# "price": "1900.00000",
|
|
1128
|
+
# "price2": "0.00000",
|
|
1129
|
+
# "type": "sell"
|
|
1130
|
+
# },
|
|
1131
|
+
# "expiretm": null,
|
|
1132
|
+
# "fee": "0.00000",
|
|
1133
|
+
# "limitprice": "0.00000",
|
|
1134
|
+
# "misc": '',
|
|
1135
|
+
# "oflags": "fciq",
|
|
1136
|
+
# "opentm": "1667522705.757622",
|
|
1137
|
+
# "refid": null,
|
|
1138
|
+
# "starttm": null,
|
|
1139
|
+
# "status": "open",
|
|
1140
|
+
# "stopprice": "0.00000",
|
|
1141
|
+
# "timeinforce": "GTC",
|
|
1142
|
+
# "userref": 0,
|
|
1143
|
+
# "vol": "0.01000000",
|
|
1144
|
+
# "vol_exec": "0.00000000"
|
|
1145
|
+
# }
|
|
1146
|
+
#
|
|
1147
|
+
description = self.safe_value(order, 'descr', {})
|
|
1148
|
+
orderDescription = self.safe_string(description, 'order')
|
|
1149
|
+
side = None
|
|
1150
|
+
type = None
|
|
1151
|
+
wsName = None
|
|
1152
|
+
price = None
|
|
1153
|
+
amount = None
|
|
1154
|
+
if orderDescription is not None:
|
|
1155
|
+
parts = orderDescription.split(' ')
|
|
1156
|
+
side = self.safe_string(parts, 0)
|
|
1157
|
+
amount = self.safe_string(parts, 1)
|
|
1158
|
+
wsName = self.safe_string(parts, 2)
|
|
1159
|
+
type = self.safe_string(parts, 4)
|
|
1160
|
+
price = self.safe_string(parts, 5)
|
|
1161
|
+
side = self.safe_string(description, 'type', side)
|
|
1162
|
+
type = self.safe_string(description, 'ordertype', type)
|
|
1163
|
+
wsName = self.safe_string(description, 'pair', wsName)
|
|
1164
|
+
market = self.safe_value(self.options['marketsByWsName'], wsName, market)
|
|
1165
|
+
symbol = None
|
|
1166
|
+
timestamp = self.safe_timestamp(order, 'opentm')
|
|
1167
|
+
amount = self.safe_string(order, 'vol', amount)
|
|
1168
|
+
filled = self.safe_string(order, 'vol_exec')
|
|
1169
|
+
fee = None
|
|
1170
|
+
cost = self.safe_string(order, 'cost')
|
|
1171
|
+
price = self.safe_string(description, 'price', price)
|
|
1172
|
+
if (price is None) or (Precise.string_eq(price, '0.0')):
|
|
1173
|
+
price = self.safe_string(description, 'price2')
|
|
1174
|
+
if (price is None) or (Precise.string_eq(price, '0.0')):
|
|
1175
|
+
price = self.safe_string(order, 'price', price)
|
|
1176
|
+
average = self.safe_string_2(order, 'avg_price', 'price')
|
|
1177
|
+
if market is not None:
|
|
1178
|
+
symbol = market['symbol']
|
|
1179
|
+
if 'fee' in order:
|
|
1180
|
+
flags = order['oflags']
|
|
1181
|
+
feeCost = self.safe_string(order, 'fee')
|
|
1182
|
+
fee = {
|
|
1183
|
+
'cost': feeCost,
|
|
1184
|
+
'rate': None,
|
|
1185
|
+
}
|
|
1186
|
+
if flags.find('fciq') >= 0:
|
|
1187
|
+
fee['currency'] = market['quote']
|
|
1188
|
+
elif flags.find('fcib') >= 0:
|
|
1189
|
+
fee['currency'] = market['base']
|
|
1190
|
+
status = self.parse_order_status(self.safe_string(order, 'status'))
|
|
1191
|
+
id = self.safe_string(order, 'id')
|
|
1192
|
+
if id is None:
|
|
1193
|
+
txid = self.safe_value(order, 'txid')
|
|
1194
|
+
id = self.safe_string(txid, 0)
|
|
1195
|
+
clientOrderId = self.safe_string(order, 'userref')
|
|
1196
|
+
rawTrades = self.safe_value(order, 'trades')
|
|
1197
|
+
trades = None
|
|
1198
|
+
if rawTrades is not None:
|
|
1199
|
+
trades = self.parse_trades(rawTrades, market, None, None, {'order': id})
|
|
1200
|
+
stopPrice = self.safe_number(order, 'stopprice')
|
|
1201
|
+
return self.safe_order({
|
|
1202
|
+
'id': id,
|
|
1203
|
+
'clientOrderId': clientOrderId,
|
|
1204
|
+
'info': order,
|
|
1205
|
+
'timestamp': timestamp,
|
|
1206
|
+
'datetime': self.iso8601(timestamp),
|
|
1207
|
+
'lastTradeTimestamp': None,
|
|
1208
|
+
'status': status,
|
|
1209
|
+
'symbol': symbol,
|
|
1210
|
+
'type': type,
|
|
1211
|
+
'timeInForce': None,
|
|
1212
|
+
'postOnly': None,
|
|
1213
|
+
'side': side,
|
|
1214
|
+
'price': price,
|
|
1215
|
+
'stopPrice': stopPrice,
|
|
1216
|
+
'triggerPrice': stopPrice,
|
|
1217
|
+
'cost': cost,
|
|
1218
|
+
'amount': amount,
|
|
1219
|
+
'filled': filled,
|
|
1220
|
+
'average': average,
|
|
1221
|
+
'remaining': None,
|
|
1222
|
+
'fee': fee,
|
|
1223
|
+
'trades': trades,
|
|
1224
|
+
})
|
|
1225
|
+
|
|
1226
|
+
async def watch_multi_helper(self, unifiedName: str, channelName: str, symbols: Strings = None, subscriptionArgs=None, params={}):
|
|
1227
|
+
await self.load_markets()
|
|
1228
|
+
# symbols are required
|
|
1229
|
+
symbols = self.market_symbols(symbols, None, False, True, False)
|
|
1230
|
+
messageHashes = []
|
|
1231
|
+
for i in range(0, len(symbols)):
|
|
1232
|
+
messageHashes.append(self.get_message_hash(unifiedName, None, self.symbol(symbols[i])))
|
|
1233
|
+
# for WS subscriptions, we can't use .marketIds(symbols), instead a custom is field needed
|
|
1234
|
+
markets = self.markets_for_symbols(symbols)
|
|
1235
|
+
wsMarketIds = []
|
|
1236
|
+
for i in range(0, len(markets)):
|
|
1237
|
+
wsMarketId = self.safe_string(markets[i]['info'], 'wsname')
|
|
1238
|
+
wsMarketIds.append(wsMarketId)
|
|
1239
|
+
request: dict = {
|
|
1240
|
+
'event': 'subscribe',
|
|
1241
|
+
'reqid': self.request_id(),
|
|
1242
|
+
'pair': wsMarketIds,
|
|
1243
|
+
'subscription': {
|
|
1244
|
+
'name': channelName,
|
|
1245
|
+
},
|
|
1246
|
+
}
|
|
1247
|
+
url = self.urls['api']['ws']['public']
|
|
1248
|
+
return await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes, subscriptionArgs)
|
|
1249
|
+
|
|
1250
|
+
def get_message_hash(self, unifiedElementName: str, subChannelName: Str = None, symbol: Str = None):
|
|
1251
|
+
# unifiedElementName can be : orderbook, trade, ticker, bidask ...
|
|
1252
|
+
# subChannelName only applies to channel that needs specific variation(i.e. depth_50, depth_100..) to be selected
|
|
1253
|
+
withSymbol = symbol is not None
|
|
1254
|
+
messageHash = unifiedElementName
|
|
1255
|
+
if not withSymbol:
|
|
1256
|
+
messageHash += 's'
|
|
1257
|
+
else:
|
|
1258
|
+
messageHash += '@' + symbol
|
|
1259
|
+
if subChannelName is not None:
|
|
1260
|
+
messageHash += '#' + subChannelName
|
|
1261
|
+
return messageHash
|
|
1262
|
+
|
|
1263
|
+
def handle_subscription_status(self, client: Client, message):
|
|
1264
|
+
#
|
|
1265
|
+
# public
|
|
1266
|
+
#
|
|
1267
|
+
# {
|
|
1268
|
+
# "channelID": 210,
|
|
1269
|
+
# "channelName": "book-10",
|
|
1270
|
+
# "event": "subscriptionStatus",
|
|
1271
|
+
# "reqid": 1574146735269,
|
|
1272
|
+
# "pair": "ETH/XBT",
|
|
1273
|
+
# "status": "subscribed",
|
|
1274
|
+
# "subscription": {depth: 10, name: "book"}
|
|
1275
|
+
# }
|
|
1276
|
+
#
|
|
1277
|
+
# private
|
|
1278
|
+
#
|
|
1279
|
+
# {
|
|
1280
|
+
# "channelName": "openOrders",
|
|
1281
|
+
# "event": "subscriptionStatus",
|
|
1282
|
+
# "reqid": 1,
|
|
1283
|
+
# "status": "subscribed",
|
|
1284
|
+
# "subscription": {maxratecount: 125, name: "openOrders"}
|
|
1285
|
+
# }
|
|
1286
|
+
#
|
|
1287
|
+
channelId = self.safe_string(message, 'channelID')
|
|
1288
|
+
if channelId is not None:
|
|
1289
|
+
client.subscriptions[channelId] = message
|
|
1290
|
+
# requestId = self.safe_string(message, "reqid")
|
|
1291
|
+
# if requestId in client.futures:
|
|
1292
|
+
# del client.futures[requestId]
|
|
1293
|
+
# }
|
|
1294
|
+
|
|
1295
|
+
def handle_error_message(self, client: Client, message):
|
|
1296
|
+
#
|
|
1297
|
+
# {
|
|
1298
|
+
# "errorMessage": "Currency pair not in ISO 4217-A3 format foobar",
|
|
1299
|
+
# "event": "subscriptionStatus",
|
|
1300
|
+
# "pair": "foobar",
|
|
1301
|
+
# "reqid": 1574146735269,
|
|
1302
|
+
# "status": "error",
|
|
1303
|
+
# "subscription": {name: "ticker"}
|
|
1304
|
+
# }
|
|
1305
|
+
#
|
|
1306
|
+
errorMessage = self.safe_string(message, 'errorMessage')
|
|
1307
|
+
if errorMessage is not None:
|
|
1308
|
+
requestId = self.safe_value(message, 'reqid')
|
|
1309
|
+
if requestId is not None:
|
|
1310
|
+
broad = self.exceptions['ws']['broad']
|
|
1311
|
+
broadKey = self.find_broadly_matched_key(broad, errorMessage)
|
|
1312
|
+
exception = None
|
|
1313
|
+
if broadKey is None:
|
|
1314
|
+
exception = ExchangeError(errorMessage) # c# requirement to convert the errorMessage to string
|
|
1315
|
+
else:
|
|
1316
|
+
exception = broad[broadKey](errorMessage)
|
|
1317
|
+
client.reject(exception, requestId)
|
|
1318
|
+
return False
|
|
1319
|
+
return True
|
|
1320
|
+
|
|
1321
|
+
def handle_message(self, client: Client, message):
|
|
1322
|
+
if isinstance(message, list):
|
|
1323
|
+
channelId = self.safe_string(message, 0)
|
|
1324
|
+
subscription = self.safe_value(client.subscriptions, channelId, {})
|
|
1325
|
+
info = self.safe_value(subscription, 'subscription', {})
|
|
1326
|
+
messageLength = len(message)
|
|
1327
|
+
channelName = self.safe_string(message, messageLength - 2)
|
|
1328
|
+
name = self.safe_string(info, 'name')
|
|
1329
|
+
methods: dict = {
|
|
1330
|
+
# public
|
|
1331
|
+
'book': self.handle_order_book,
|
|
1332
|
+
'ohlc': self.handle_ohlcv,
|
|
1333
|
+
'ticker': self.handle_ticker,
|
|
1334
|
+
'trade': self.handle_trades,
|
|
1335
|
+
# private
|
|
1336
|
+
'openOrders': self.handle_orders,
|
|
1337
|
+
'ownTrades': self.handle_my_trades,
|
|
1338
|
+
}
|
|
1339
|
+
method = self.safe_value_2(methods, name, channelName)
|
|
1340
|
+
if method is not None:
|
|
1341
|
+
method(client, message, subscription)
|
|
1342
|
+
else:
|
|
1343
|
+
if self.handle_error_message(client, message):
|
|
1344
|
+
event = self.safe_string(message, 'event')
|
|
1345
|
+
methods: dict = {
|
|
1346
|
+
'heartbeat': self.handle_heartbeat,
|
|
1347
|
+
'systemStatus': self.handle_system_status,
|
|
1348
|
+
'subscriptionStatus': self.handle_subscription_status,
|
|
1349
|
+
'addOrderStatus': self.handle_create_edit_order,
|
|
1350
|
+
'editOrderStatus': self.handle_create_edit_order,
|
|
1351
|
+
'cancelOrderStatus': self.handle_cancel_order,
|
|
1352
|
+
'cancelAllStatus': self.handle_cancel_all_orders,
|
|
1353
|
+
}
|
|
1354
|
+
method = self.safe_value(methods, event)
|
|
1355
|
+
if method is not None:
|
|
1356
|
+
method(client, message)
|