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/hitbtc.py
ADDED
|
@@ -0,0 +1,1216 @@
|
|
|
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
|
+
import hashlib
|
|
9
|
+
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
|
|
10
|
+
from ccxt.async_support.base.ws.client import Client
|
|
11
|
+
from typing import List
|
|
12
|
+
from ccxt.base.errors import ExchangeError
|
|
13
|
+
from ccxt.base.errors import AuthenticationError
|
|
14
|
+
from ccxt.base.errors import NotSupported
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class hitbtc(ccxt.async_support.hitbtc):
|
|
18
|
+
|
|
19
|
+
def describe(self):
|
|
20
|
+
return self.deep_extend(super(hitbtc, self).describe(), {
|
|
21
|
+
'has': {
|
|
22
|
+
'ws': True,
|
|
23
|
+
'watchTicker': True,
|
|
24
|
+
'watchTickers': True,
|
|
25
|
+
'watchTrades': True,
|
|
26
|
+
'watchOrderBook': True,
|
|
27
|
+
'watchBalance': True,
|
|
28
|
+
'watchOrders': True,
|
|
29
|
+
'watchOHLCV': True,
|
|
30
|
+
'watchMyTrades': False,
|
|
31
|
+
'createOrderWs': True,
|
|
32
|
+
'cancelOrderWs': True,
|
|
33
|
+
'fetchOpenOrdersWs': True,
|
|
34
|
+
'cancelAllOrdersWs': True,
|
|
35
|
+
},
|
|
36
|
+
'urls': {
|
|
37
|
+
'api': {
|
|
38
|
+
'ws': {
|
|
39
|
+
'public': 'wss://api.hitbtc.com/api/3/ws/public',
|
|
40
|
+
'private': 'wss://api.hitbtc.com/api/3/ws/trading',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
'test': {
|
|
44
|
+
'ws': {
|
|
45
|
+
'public': 'wss://api.demo.hitbtc.com/api/3/ws/public',
|
|
46
|
+
'private': 'wss://api.demo.hitbtc.com/api/3/ws/trading',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
'options': {
|
|
51
|
+
'tradesLimit': 1000,
|
|
52
|
+
'watchTicker': {
|
|
53
|
+
'method': 'ticker/{speed}', # 'ticker/{speed}' or 'ticker/price/{speed}'
|
|
54
|
+
},
|
|
55
|
+
'watchTickers': {
|
|
56
|
+
'method': 'ticker/{speed}', # 'ticker/{speed}','ticker/price/{speed}', 'ticker/{speed}/batch', or 'ticker/{speed}/price/batch''
|
|
57
|
+
},
|
|
58
|
+
'watchOrderBook': {
|
|
59
|
+
'method': 'orderbook/full', # 'orderbook/full', 'orderbook/{depth}/{speed}', 'orderbook/{depth}/{speed}/batch', 'orderbook/top/{speed}', or 'orderbook/top/{speed}/batch'
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
'timeframes': {
|
|
63
|
+
'1m': 'M1',
|
|
64
|
+
'3m': 'M3',
|
|
65
|
+
'5m': 'M5',
|
|
66
|
+
'15m': 'M15',
|
|
67
|
+
'30m': 'M30',
|
|
68
|
+
'1h': 'H1',
|
|
69
|
+
'4h': 'H4',
|
|
70
|
+
'1d': 'D1',
|
|
71
|
+
'1w': 'D7',
|
|
72
|
+
'1M': '1M',
|
|
73
|
+
},
|
|
74
|
+
'streaming': {
|
|
75
|
+
'keepAlive': 4000,
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
async def authenticate(self):
|
|
80
|
+
"""
|
|
81
|
+
* @ignore
|
|
82
|
+
authenticates the user to access private web socket channels
|
|
83
|
+
:see: https://api.hitbtc.com/#socket-authentication
|
|
84
|
+
:returns dict: response from exchange
|
|
85
|
+
"""
|
|
86
|
+
self.check_required_credentials()
|
|
87
|
+
url = self.urls['api']['ws']['private']
|
|
88
|
+
messageHash = 'authenticated'
|
|
89
|
+
client = self.client(url)
|
|
90
|
+
future = client.future(messageHash)
|
|
91
|
+
authenticated = self.safe_value(client.subscriptions, messageHash)
|
|
92
|
+
if authenticated is None:
|
|
93
|
+
timestamp = self.milliseconds()
|
|
94
|
+
signature = self.hmac(self.encode(self.number_to_string(timestamp)), self.encode(self.secret), hashlib.sha256, 'hex')
|
|
95
|
+
request: dict = {
|
|
96
|
+
'method': 'login',
|
|
97
|
+
'params': {
|
|
98
|
+
'type': 'HS256',
|
|
99
|
+
'api_key': self.apiKey,
|
|
100
|
+
'timestamp': timestamp,
|
|
101
|
+
'signature': signature,
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
self.watch(url, messageHash, request, messageHash)
|
|
105
|
+
#
|
|
106
|
+
# {
|
|
107
|
+
# "jsonrpc": "2.0",
|
|
108
|
+
# "result": True
|
|
109
|
+
# }
|
|
110
|
+
#
|
|
111
|
+
# # Failure to return results
|
|
112
|
+
#
|
|
113
|
+
# {
|
|
114
|
+
# "jsonrpc": "2.0",
|
|
115
|
+
# "error": {
|
|
116
|
+
# "code": 1002,
|
|
117
|
+
# "message": "Authorization is required or has been failed",
|
|
118
|
+
# "description": "invalid signature format"
|
|
119
|
+
# }
|
|
120
|
+
# }
|
|
121
|
+
#
|
|
122
|
+
return await future
|
|
123
|
+
|
|
124
|
+
async def subscribe_public(self, name: str, messageHashPrefix: str, symbols: Strings = None, params={}):
|
|
125
|
+
"""
|
|
126
|
+
* @ignore
|
|
127
|
+
:param str name: websocket endpoint name
|
|
128
|
+
:param str[] [symbols]: unified CCXT symbol(s)
|
|
129
|
+
:param dict [params]: extra parameters specific to the hitbtc api
|
|
130
|
+
"""
|
|
131
|
+
await self.load_markets()
|
|
132
|
+
url = self.urls['api']['ws']['public']
|
|
133
|
+
messageHash = messageHashPrefix
|
|
134
|
+
if symbols is not None:
|
|
135
|
+
messageHash = messageHash + '::' + ','.join(symbols)
|
|
136
|
+
subscribe: dict = {
|
|
137
|
+
'method': 'subscribe',
|
|
138
|
+
'id': self.nonce(),
|
|
139
|
+
'ch': name,
|
|
140
|
+
}
|
|
141
|
+
request = self.extend(subscribe, params)
|
|
142
|
+
return await self.watch(url, messageHash, request, messageHash)
|
|
143
|
+
|
|
144
|
+
async def subscribe_private(self, name: str, symbol: Str = None, params={}):
|
|
145
|
+
"""
|
|
146
|
+
* @ignore
|
|
147
|
+
:param str name: websocket endpoint name
|
|
148
|
+
:param str [symbol]: unified CCXT symbol
|
|
149
|
+
:param dict [params]: extra parameters specific to the hitbtc api
|
|
150
|
+
"""
|
|
151
|
+
await self.load_markets()
|
|
152
|
+
await self.authenticate()
|
|
153
|
+
url = self.urls['api']['ws']['private']
|
|
154
|
+
splitName = name.split('_subscribe')
|
|
155
|
+
messageHash = self.safe_string(splitName, 0)
|
|
156
|
+
if symbol is not None:
|
|
157
|
+
messageHash = messageHash + '::' + symbol
|
|
158
|
+
subscribe: dict = {
|
|
159
|
+
'method': name,
|
|
160
|
+
'params': params,
|
|
161
|
+
'id': self.nonce(),
|
|
162
|
+
}
|
|
163
|
+
return await self.watch(url, messageHash, subscribe, messageHash)
|
|
164
|
+
|
|
165
|
+
async def trade_request(self, name: str, params={}):
|
|
166
|
+
"""
|
|
167
|
+
* @ignore
|
|
168
|
+
:param str name: websocket endpoint name
|
|
169
|
+
:param str [symbol]: unified CCXT symbol
|
|
170
|
+
:param dict [params]: extra parameters specific to the hitbtc api
|
|
171
|
+
"""
|
|
172
|
+
await self.load_markets()
|
|
173
|
+
await self.authenticate()
|
|
174
|
+
url = self.urls['api']['ws']['private']
|
|
175
|
+
messageHash = str(self.nonce())
|
|
176
|
+
subscribe: dict = {
|
|
177
|
+
'method': name,
|
|
178
|
+
'params': params,
|
|
179
|
+
'id': messageHash,
|
|
180
|
+
}
|
|
181
|
+
return await self.watch(url, messageHash, subscribe, messageHash)
|
|
182
|
+
|
|
183
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
184
|
+
"""
|
|
185
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
186
|
+
:see: https://api.hitbtc.com/#subscribe-to-full-order-book
|
|
187
|
+
:see: https://api.hitbtc.com/#subscribe-to-partial-order-book
|
|
188
|
+
:see: https://api.hitbtc.com/#subscribe-to-partial-order-book-in-batches
|
|
189
|
+
:see: https://api.hitbtc.com/#subscribe-to-top-of-book
|
|
190
|
+
:see: https://api.hitbtc.com/#subscribe-to-top-of-book-in-batches
|
|
191
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
|
192
|
+
:param int [limit]: the maximum amount of order book entries to return
|
|
193
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
194
|
+
:param str [params.method]: 'orderbook/full', 'orderbook/{depth}/{speed}', 'orderbook/{depth}/{speed}/batch', 'orderbook/top/{speed}', or 'orderbook/top/{speed}/batch'
|
|
195
|
+
:param int [params.depth]: 5 , 10, or 20(default)
|
|
196
|
+
:param int [params.speed]: 100(default), 500, or 1000
|
|
197
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
|
198
|
+
"""
|
|
199
|
+
options = self.safe_value(self.options, 'watchOrderBook')
|
|
200
|
+
defaultMethod = self.safe_string(options, 'method', 'orderbook/full')
|
|
201
|
+
name = self.safe_string_2(params, 'method', 'defaultMethod', defaultMethod)
|
|
202
|
+
depth = self.safe_string(params, 'depth', '20')
|
|
203
|
+
speed = self.safe_string(params, 'depth', '100')
|
|
204
|
+
if name == 'orderbook/{depth}/{speed}':
|
|
205
|
+
name = 'orderbook/D' + depth + '/' + speed + 'ms'
|
|
206
|
+
elif name == 'orderbook/{depth}/{speed}/batch':
|
|
207
|
+
name = 'orderbook/D' + depth + '/' + speed + 'ms/batch'
|
|
208
|
+
elif name == 'orderbook/top/{speed}':
|
|
209
|
+
name = 'orderbook/top/' + speed + 'ms'
|
|
210
|
+
elif name == 'orderbook/top/{speed}/batch':
|
|
211
|
+
name = 'orderbook/top/' + speed + 'ms/batch'
|
|
212
|
+
market = self.market(symbol)
|
|
213
|
+
request: dict = {
|
|
214
|
+
'params': {
|
|
215
|
+
'symbols': [market['id']],
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
orderbook = await self.subscribe_public(name, 'orderbooks', [symbol], self.deep_extend(request, params))
|
|
219
|
+
return orderbook.limit()
|
|
220
|
+
|
|
221
|
+
def handle_order_book(self, client: Client, message):
|
|
222
|
+
#
|
|
223
|
+
# {
|
|
224
|
+
# "ch": "orderbook/full", # Channel
|
|
225
|
+
# "snapshot": {
|
|
226
|
+
# "ETHBTC": {
|
|
227
|
+
# "t": 1626866578796, # Timestamp in milliseconds
|
|
228
|
+
# "s": 27617207, # Sequence number
|
|
229
|
+
# "a": [ # Asks
|
|
230
|
+
# ["0.060506", "0"],
|
|
231
|
+
# ["0.060549", "12.6431"],
|
|
232
|
+
# ["0.060570", "0"],
|
|
233
|
+
# ["0.060612", "0"]
|
|
234
|
+
# ],
|
|
235
|
+
# "b": [ # Bids
|
|
236
|
+
# ["0.060439", "4.4095"],
|
|
237
|
+
# ["0.060414", "0"],
|
|
238
|
+
# ["0.060407", "7.3349"],
|
|
239
|
+
# ["0.060390", "0"]
|
|
240
|
+
# ]
|
|
241
|
+
# }
|
|
242
|
+
# }
|
|
243
|
+
# }
|
|
244
|
+
#
|
|
245
|
+
snapshot = self.safe_dict(message, 'snapshot')
|
|
246
|
+
update = self.safe_dict(message, 'update')
|
|
247
|
+
data = snapshot if snapshot else update
|
|
248
|
+
type = 'snapshot' if snapshot else 'update'
|
|
249
|
+
marketIds = list(data.keys())
|
|
250
|
+
for i in range(0, len(marketIds)):
|
|
251
|
+
marketId = marketIds[i]
|
|
252
|
+
market = self.safe_market(marketId)
|
|
253
|
+
symbol = market['symbol']
|
|
254
|
+
item = data[marketId]
|
|
255
|
+
messageHash = 'orderbooks::' + symbol
|
|
256
|
+
if not (symbol in self.orderbooks):
|
|
257
|
+
subscription = self.safe_dict(client.subscriptions, messageHash, {})
|
|
258
|
+
limit = self.safe_integer(subscription, 'limit')
|
|
259
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
|
260
|
+
orderbook = self.orderbooks[symbol]
|
|
261
|
+
timestamp = self.safe_integer(item, 't')
|
|
262
|
+
nonce = self.safe_integer(item, 's')
|
|
263
|
+
if type == 'snapshot':
|
|
264
|
+
parsedSnapshot = self.parse_order_book(item, symbol, timestamp, 'b', 'a')
|
|
265
|
+
orderbook.reset(parsedSnapshot)
|
|
266
|
+
else:
|
|
267
|
+
asks = self.safe_list(item, 'a', [])
|
|
268
|
+
bids = self.safe_list(item, 'b', [])
|
|
269
|
+
self.handle_deltas(orderbook['asks'], asks)
|
|
270
|
+
self.handle_deltas(orderbook['bids'], bids)
|
|
271
|
+
orderbook['timestamp'] = timestamp
|
|
272
|
+
orderbook['datetime'] = self.iso8601(timestamp)
|
|
273
|
+
orderbook['nonce'] = nonce
|
|
274
|
+
orderbook['symbol'] = symbol
|
|
275
|
+
self.orderbooks[symbol] = orderbook
|
|
276
|
+
client.resolve(orderbook, messageHash)
|
|
277
|
+
|
|
278
|
+
def handle_delta(self, bookside, delta):
|
|
279
|
+
price = self.safe_number(delta, 0)
|
|
280
|
+
amount = self.safe_number(delta, 1)
|
|
281
|
+
bookside.store(price, amount)
|
|
282
|
+
|
|
283
|
+
def handle_deltas(self, bookside, deltas):
|
|
284
|
+
for i in range(0, len(deltas)):
|
|
285
|
+
self.handle_delta(bookside, deltas[i])
|
|
286
|
+
|
|
287
|
+
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
288
|
+
"""
|
|
289
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
290
|
+
:see: https://api.hitbtc.com/#subscribe-to-ticker
|
|
291
|
+
:see: https://api.hitbtc.com/#subscribe-to-ticker-in-batches
|
|
292
|
+
:see: https://api.hitbtc.com/#subscribe-to-mini-ticker
|
|
293
|
+
:see: https://api.hitbtc.com/#subscribe-to-mini-ticker-in-batches
|
|
294
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
295
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
296
|
+
:param str [params.method]: 'ticker/{speed}'(default), or 'ticker/price/{speed}'
|
|
297
|
+
:param str [params.speed]: '1s'(default), or '3s'
|
|
298
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
299
|
+
"""
|
|
300
|
+
options = self.safe_value(self.options, 'watchTicker')
|
|
301
|
+
defaultMethod = self.safe_string(options, 'method', 'ticker/{speed}')
|
|
302
|
+
method = self.safe_string_2(params, 'method', 'defaultMethod', defaultMethod)
|
|
303
|
+
speed = self.safe_string(params, 'speed', '1s')
|
|
304
|
+
name = self.implode_params(method, {'speed': speed})
|
|
305
|
+
params = self.omit(params, ['method', 'speed'])
|
|
306
|
+
market = self.market(symbol)
|
|
307
|
+
request: dict = {
|
|
308
|
+
'params': {
|
|
309
|
+
'symbols': [market['id']],
|
|
310
|
+
},
|
|
311
|
+
}
|
|
312
|
+
result = await self.subscribe_public(name, 'tickers', [symbol], self.deep_extend(request, params))
|
|
313
|
+
return self.safe_value(result, symbol)
|
|
314
|
+
|
|
315
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
316
|
+
"""
|
|
317
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
318
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
319
|
+
:param dict params: extra parameters specific to the exchange API endpoint
|
|
320
|
+
:param str params['method']: 'ticker/{speed}'(default),'ticker/price/{speed}', 'ticker/{speed}/batch', or 'ticker/{speed}/price/batch''
|
|
321
|
+
:param str params['speed']: '1s'(default), or '3s'
|
|
322
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
|
|
323
|
+
"""
|
|
324
|
+
await self.load_markets()
|
|
325
|
+
options = self.safe_value(self.options, 'watchTicker')
|
|
326
|
+
defaultMethod = self.safe_string(options, 'method', 'ticker/{speed}')
|
|
327
|
+
method = self.safe_string_2(params, 'method', 'defaultMethod', defaultMethod)
|
|
328
|
+
speed = self.safe_string(params, 'speed', '1s')
|
|
329
|
+
name = self.implode_params(method, {'speed': speed})
|
|
330
|
+
params = self.omit(params, ['method', 'speed'])
|
|
331
|
+
marketIds = []
|
|
332
|
+
if symbols is None:
|
|
333
|
+
marketIds.append('*')
|
|
334
|
+
else:
|
|
335
|
+
for i in range(0, len(symbols)):
|
|
336
|
+
marketId = self.market_id(symbols[i])
|
|
337
|
+
marketIds.append(marketId)
|
|
338
|
+
request: dict = {
|
|
339
|
+
'params': {
|
|
340
|
+
'symbols': marketIds,
|
|
341
|
+
},
|
|
342
|
+
}
|
|
343
|
+
tickers = await self.subscribe_public(name, 'tickers', symbols, self.deep_extend(request, params))
|
|
344
|
+
if self.newUpdates:
|
|
345
|
+
return tickers
|
|
346
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
|
347
|
+
|
|
348
|
+
def handle_ticker(self, client: Client, message):
|
|
349
|
+
#
|
|
350
|
+
# {
|
|
351
|
+
# "ch": "ticker/1s",
|
|
352
|
+
# "data": {
|
|
353
|
+
# "ETHBTC": {
|
|
354
|
+
# "t": 1614815872000, # Timestamp in milliseconds
|
|
355
|
+
# "a": "0.031175", # Best ask
|
|
356
|
+
# "A": "0.03329", # Best ask quantity
|
|
357
|
+
# "b": "0.031148", # Best bid
|
|
358
|
+
# "B": "0.10565", # Best bid quantity
|
|
359
|
+
# "c": "0.031210", # Last price
|
|
360
|
+
# "o": "0.030781", # Open price
|
|
361
|
+
# "h": "0.031788", # High price
|
|
362
|
+
# "l": "0.030733", # Low price
|
|
363
|
+
# "v": "62.587", # Base asset volume
|
|
364
|
+
# "q": "1.951420577", # Quote asset volume
|
|
365
|
+
# "p": "0.000429", # Price change
|
|
366
|
+
# "P": "1.39", # Price change percent
|
|
367
|
+
# "L": 1182694927 # Last trade identifier
|
|
368
|
+
# }
|
|
369
|
+
# }
|
|
370
|
+
# }
|
|
371
|
+
#
|
|
372
|
+
# {
|
|
373
|
+
# "ch": "ticker/price/1s",
|
|
374
|
+
# "data": {
|
|
375
|
+
# "BTCUSDT": {
|
|
376
|
+
# "t": 1614815872030,
|
|
377
|
+
# "o": "32636.79",
|
|
378
|
+
# "c": "32085.51",
|
|
379
|
+
# "h": "33379.92",
|
|
380
|
+
# "l": "30683.28",
|
|
381
|
+
# "v": "11.90667",
|
|
382
|
+
# "q": "384081.1955629"
|
|
383
|
+
# }
|
|
384
|
+
# }
|
|
385
|
+
# }
|
|
386
|
+
#
|
|
387
|
+
data = self.safe_value(message, 'data', {})
|
|
388
|
+
marketIds = list(data.keys())
|
|
389
|
+
newTickers: dict = {}
|
|
390
|
+
for i in range(0, len(marketIds)):
|
|
391
|
+
marketId = marketIds[i]
|
|
392
|
+
market = self.safe_market(marketId)
|
|
393
|
+
symbol = market['symbol']
|
|
394
|
+
ticker = self.parse_ws_ticker(data[marketId], market)
|
|
395
|
+
self.tickers[symbol] = ticker
|
|
396
|
+
newTickers[symbol] = ticker
|
|
397
|
+
client.resolve(newTickers, 'tickers')
|
|
398
|
+
messageHashes = self.find_message_hashes(client, 'tickers::')
|
|
399
|
+
for i in range(0, len(messageHashes)):
|
|
400
|
+
messageHash = messageHashes[i]
|
|
401
|
+
parts = messageHash.split('::')
|
|
402
|
+
symbolsString = parts[1]
|
|
403
|
+
symbols = symbolsString.split(',')
|
|
404
|
+
tickers = self.filter_by_array(newTickers, 'symbol', symbols)
|
|
405
|
+
tickersSymbols = list(tickers.keys())
|
|
406
|
+
numTickers = len(tickersSymbols)
|
|
407
|
+
if numTickers > 0:
|
|
408
|
+
client.resolve(tickers, messageHash)
|
|
409
|
+
return message
|
|
410
|
+
|
|
411
|
+
def parse_ws_ticker(self, ticker, market=None):
|
|
412
|
+
#
|
|
413
|
+
# {
|
|
414
|
+
# "t": 1614815872000, # Timestamp in milliseconds
|
|
415
|
+
# "a": "0.031175", # Best ask
|
|
416
|
+
# "A": "0.03329", # Best ask quantity
|
|
417
|
+
# "b": "0.031148", # Best bid
|
|
418
|
+
# "B": "0.10565", # Best bid quantity
|
|
419
|
+
# "c": "0.031210", # Last price
|
|
420
|
+
# "o": "0.030781", # Open price
|
|
421
|
+
# "h": "0.031788", # High price
|
|
422
|
+
# "l": "0.030733", # Low price
|
|
423
|
+
# "v": "62.587", # Base asset volume
|
|
424
|
+
# "q": "1.951420577", # Quote asset volume
|
|
425
|
+
# "p": "0.000429", # Price change
|
|
426
|
+
# "P": "1.39", # Price change percent
|
|
427
|
+
# "L": 1182694927 # Last trade identifier
|
|
428
|
+
# }
|
|
429
|
+
#
|
|
430
|
+
# {
|
|
431
|
+
# "t": 1614815872030,
|
|
432
|
+
# "o": "32636.79",
|
|
433
|
+
# "c": "32085.51",
|
|
434
|
+
# "h": "33379.92",
|
|
435
|
+
# "l": "30683.28",
|
|
436
|
+
# "v": "11.90667",
|
|
437
|
+
# "q": "384081.1955629"
|
|
438
|
+
# }
|
|
439
|
+
#
|
|
440
|
+
timestamp = self.safe_integer(ticker, 't')
|
|
441
|
+
symbol = self.safe_symbol(None, market)
|
|
442
|
+
last = self.safe_string(ticker, 'c')
|
|
443
|
+
return self.safe_ticker({
|
|
444
|
+
'symbol': symbol,
|
|
445
|
+
'timestamp': timestamp,
|
|
446
|
+
'datetime': self.iso8601(timestamp),
|
|
447
|
+
'high': self.safe_string(ticker, 'h'),
|
|
448
|
+
'low': self.safe_string(ticker, 'l'),
|
|
449
|
+
'bid': self.safe_string(ticker, 'b'),
|
|
450
|
+
'bidVolume': self.safe_string(ticker, 'B'),
|
|
451
|
+
'ask': self.safe_string(ticker, 'a'),
|
|
452
|
+
'askVolume': self.safe_string(ticker, 'A'),
|
|
453
|
+
'vwap': None,
|
|
454
|
+
'open': self.safe_string(ticker, 'o'),
|
|
455
|
+
'close': last,
|
|
456
|
+
'last': last,
|
|
457
|
+
'previousClose': None,
|
|
458
|
+
'change': None,
|
|
459
|
+
'percentage': None,
|
|
460
|
+
'average': None,
|
|
461
|
+
'baseVolume': self.safe_string(ticker, 'v'),
|
|
462
|
+
'quoteVolume': self.safe_string(ticker, 'q'),
|
|
463
|
+
'info': ticker,
|
|
464
|
+
}, market)
|
|
465
|
+
|
|
466
|
+
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
467
|
+
"""
|
|
468
|
+
get the list of most recent trades for a particular symbol
|
|
469
|
+
:see: https://api.hitbtc.com/#subscribe-to-trades
|
|
470
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
|
471
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
472
|
+
:param int [limit]: the maximum amount of trades to fetch
|
|
473
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
474
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
|
475
|
+
"""
|
|
476
|
+
await self.load_markets()
|
|
477
|
+
market = self.market(symbol)
|
|
478
|
+
request: dict = {
|
|
479
|
+
'params': {
|
|
480
|
+
'symbols': [market['id']],
|
|
481
|
+
},
|
|
482
|
+
}
|
|
483
|
+
if limit is not None:
|
|
484
|
+
request['limit'] = limit
|
|
485
|
+
name = 'trades'
|
|
486
|
+
trades = await self.subscribe_public(name, 'trades', [symbol], self.deep_extend(request, params))
|
|
487
|
+
if self.newUpdates:
|
|
488
|
+
limit = trades.getLimit(symbol, limit)
|
|
489
|
+
return self.filter_by_since_limit(trades, since, limit, 'timestamp')
|
|
490
|
+
|
|
491
|
+
def handle_trades(self, client: Client, message):
|
|
492
|
+
#
|
|
493
|
+
# {
|
|
494
|
+
# "result": {
|
|
495
|
+
# "ch": "trades", # Channel
|
|
496
|
+
# "subscriptions": ["ETHBTC", "BTCUSDT"]
|
|
497
|
+
# },
|
|
498
|
+
# "id": 123
|
|
499
|
+
# }
|
|
500
|
+
#
|
|
501
|
+
# Notification snapshot
|
|
502
|
+
#
|
|
503
|
+
# {
|
|
504
|
+
# "ch": "trades", # Channel
|
|
505
|
+
# "snapshot": {
|
|
506
|
+
# "BTCUSDT": [{
|
|
507
|
+
# "t": 1626861109494, # Timestamp in milliseconds
|
|
508
|
+
# "i": 1555634969, # Trade identifier
|
|
509
|
+
# "p": "30881.96", # Price
|
|
510
|
+
# "q": "12.66828", # Quantity
|
|
511
|
+
# "s": "buy" # Side
|
|
512
|
+
# }]
|
|
513
|
+
# }
|
|
514
|
+
# }
|
|
515
|
+
#
|
|
516
|
+
# Notification update
|
|
517
|
+
#
|
|
518
|
+
# {
|
|
519
|
+
# "ch": "trades",
|
|
520
|
+
# "update": {
|
|
521
|
+
# "BTCUSDT": [{
|
|
522
|
+
# "t": 1626861123552,
|
|
523
|
+
# "i": 1555634969,
|
|
524
|
+
# "p": "30877.68",
|
|
525
|
+
# "q": "0.00006",
|
|
526
|
+
# "s": "sell"
|
|
527
|
+
# }]
|
|
528
|
+
# }
|
|
529
|
+
# }
|
|
530
|
+
#
|
|
531
|
+
data = self.safe_value_2(message, 'snapshot', 'update', {})
|
|
532
|
+
marketIds = list(data.keys())
|
|
533
|
+
for i in range(0, len(marketIds)):
|
|
534
|
+
marketId = marketIds[i]
|
|
535
|
+
market = self.safe_market(marketId)
|
|
536
|
+
tradesLimit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
|
537
|
+
symbol = market['symbol']
|
|
538
|
+
stored = self.safe_value(self.trades, symbol)
|
|
539
|
+
if stored is None:
|
|
540
|
+
stored = ArrayCache(tradesLimit)
|
|
541
|
+
self.trades[symbol] = stored
|
|
542
|
+
trades = self.parse_ws_trades(data[marketId], market)
|
|
543
|
+
for j in range(0, len(trades)):
|
|
544
|
+
stored.append(trades[j])
|
|
545
|
+
messageHash = 'trades::' + symbol
|
|
546
|
+
client.resolve(stored, messageHash)
|
|
547
|
+
return message
|
|
548
|
+
|
|
549
|
+
def parse_ws_trades(self, trades, market: object = None, since: Int = None, limit: Int = None, params={}):
|
|
550
|
+
trades = self.to_array(trades)
|
|
551
|
+
result = []
|
|
552
|
+
for i in range(0, len(trades)):
|
|
553
|
+
trade = self.extend(self.parse_ws_trade(trades[i], market), params)
|
|
554
|
+
result.append(trade)
|
|
555
|
+
result = self.sort_by_2(result, 'timestamp', 'id')
|
|
556
|
+
symbol = self.safe_string(market, 'symbol')
|
|
557
|
+
return self.filter_by_symbol_since_limit(result, symbol, since, limit)
|
|
558
|
+
|
|
559
|
+
def parse_ws_trade(self, trade, market=None):
|
|
560
|
+
#
|
|
561
|
+
# {
|
|
562
|
+
# "t": 1626861123552, # Timestamp in milliseconds
|
|
563
|
+
# "i": 1555634969, # Trade identifier
|
|
564
|
+
# "p": "30877.68", # Price
|
|
565
|
+
# "q": "0.00006", # Quantity
|
|
566
|
+
# "s": "sell" # Side
|
|
567
|
+
# }
|
|
568
|
+
#
|
|
569
|
+
timestamp = self.safe_integer(trade, 't')
|
|
570
|
+
return self.safe_trade({
|
|
571
|
+
'info': trade,
|
|
572
|
+
'id': self.safe_string(trade, 'i'),
|
|
573
|
+
'order': None,
|
|
574
|
+
'timestamp': timestamp,
|
|
575
|
+
'datetime': self.iso8601(timestamp),
|
|
576
|
+
'symbol': self.safe_string(market, 'symbol'),
|
|
577
|
+
'type': None,
|
|
578
|
+
'side': self.safe_string(trade, 's'),
|
|
579
|
+
'takerOrMaker': None,
|
|
580
|
+
'price': self.safe_string(trade, 'p'),
|
|
581
|
+
'amount': self.safe_string(trade, 'q'),
|
|
582
|
+
'cost': None,
|
|
583
|
+
'fee': None,
|
|
584
|
+
}, market)
|
|
585
|
+
|
|
586
|
+
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
587
|
+
"""
|
|
588
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
589
|
+
:see: https://api.hitbtc.com/#subscribe-to-candles
|
|
590
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
591
|
+
:param str [timeframe]: the length of time each candle represents
|
|
592
|
+
:param int [since]: not used by hitbtc watchOHLCV
|
|
593
|
+
:param int [limit]: 0 – 1000, default value = 0(no history returned)
|
|
594
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
595
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
|
596
|
+
"""
|
|
597
|
+
period = self.safe_string(self.timeframes, timeframe, timeframe)
|
|
598
|
+
name = 'candles/' + period
|
|
599
|
+
market = self.market(symbol)
|
|
600
|
+
request: dict = {
|
|
601
|
+
'params': {
|
|
602
|
+
'symbols': [market['id']],
|
|
603
|
+
},
|
|
604
|
+
}
|
|
605
|
+
if limit is not None:
|
|
606
|
+
request['params']['limit'] = limit
|
|
607
|
+
ohlcv = await self.subscribe_public(name, 'candles', [symbol], self.deep_extend(request, params))
|
|
608
|
+
if self.newUpdates:
|
|
609
|
+
limit = ohlcv.getLimit(symbol, limit)
|
|
610
|
+
return self.filter_by_since_limit(ohlcv, since, limit, 0)
|
|
611
|
+
|
|
612
|
+
def handle_ohlcv(self, client: Client, message):
|
|
613
|
+
#
|
|
614
|
+
# {
|
|
615
|
+
# "ch": "candles/M1", # Channel
|
|
616
|
+
# "snapshot": {
|
|
617
|
+
# "BTCUSDT": [{
|
|
618
|
+
# "t": 1626860340000, # Message timestamp
|
|
619
|
+
# "o": "30881.95", # Open price
|
|
620
|
+
# "c": "30890.96", # Last price
|
|
621
|
+
# "h": "30900.8", # High price
|
|
622
|
+
# "l": "30861.27", # Low price
|
|
623
|
+
# "v": "1.27852", # Base asset volume
|
|
624
|
+
# "q": "39493.9021811" # Quote asset volume
|
|
625
|
+
# }
|
|
626
|
+
# ...
|
|
627
|
+
# ]
|
|
628
|
+
# }
|
|
629
|
+
# }
|
|
630
|
+
#
|
|
631
|
+
# {
|
|
632
|
+
# "ch": "candles/M1",
|
|
633
|
+
# "update": {
|
|
634
|
+
# "ETHBTC": [{
|
|
635
|
+
# "t": 1626860880000,
|
|
636
|
+
# "o": "0.060711",
|
|
637
|
+
# "c": "0.060749",
|
|
638
|
+
# "h": "0.060749",
|
|
639
|
+
# "l": "0.060711",
|
|
640
|
+
# "v": "12.2800",
|
|
641
|
+
# "q": "0.7455339675"
|
|
642
|
+
# }]
|
|
643
|
+
# }
|
|
644
|
+
# }
|
|
645
|
+
#
|
|
646
|
+
data = self.safe_value_2(message, 'snapshot', 'update', {})
|
|
647
|
+
marketIds = list(data.keys())
|
|
648
|
+
channel = self.safe_string(message, 'ch')
|
|
649
|
+
splitChannel = channel.split('/')
|
|
650
|
+
period = self.safe_string(splitChannel, 1)
|
|
651
|
+
timeframe = self.find_timeframe(period)
|
|
652
|
+
for i in range(0, len(marketIds)):
|
|
653
|
+
marketId = marketIds[i]
|
|
654
|
+
market = self.safe_market(marketId)
|
|
655
|
+
symbol = market['symbol']
|
|
656
|
+
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
|
657
|
+
stored = self.safe_value(self.ohlcvs[symbol], timeframe)
|
|
658
|
+
if stored is None:
|
|
659
|
+
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
|
660
|
+
stored = ArrayCacheByTimestamp(limit)
|
|
661
|
+
self.ohlcvs[symbol][timeframe] = stored
|
|
662
|
+
ohlcvs = self.parse_ws_ohlcvs(data[marketId], market)
|
|
663
|
+
for j in range(0, len(ohlcvs)):
|
|
664
|
+
stored.append(ohlcvs[j])
|
|
665
|
+
messageHash = 'candles::' + symbol
|
|
666
|
+
client.resolve(stored, messageHash)
|
|
667
|
+
return message
|
|
668
|
+
|
|
669
|
+
def parse_ws_ohlcv(self, ohlcv, market=None) -> list:
|
|
670
|
+
#
|
|
671
|
+
# {
|
|
672
|
+
# "t": 1626860340000, # Message timestamp
|
|
673
|
+
# "o": "30881.95", # Open price
|
|
674
|
+
# "c": "30890.96", # Last price
|
|
675
|
+
# "h": "30900.8", # High price
|
|
676
|
+
# "l": "30861.27", # Low price
|
|
677
|
+
# "v": "1.27852", # Base asset volume
|
|
678
|
+
# "q": "39493.9021811" # Quote asset volume
|
|
679
|
+
# }
|
|
680
|
+
#
|
|
681
|
+
return [
|
|
682
|
+
self.safe_integer(ohlcv, 't'),
|
|
683
|
+
self.safe_number(ohlcv, 'o'),
|
|
684
|
+
self.safe_number(ohlcv, 'h'),
|
|
685
|
+
self.safe_number(ohlcv, 'l'),
|
|
686
|
+
self.safe_number(ohlcv, 'c'),
|
|
687
|
+
self.safe_number(ohlcv, 'v'),
|
|
688
|
+
]
|
|
689
|
+
|
|
690
|
+
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
691
|
+
"""
|
|
692
|
+
watches information on multiple orders made by the user
|
|
693
|
+
:see: https://api.hitbtc.com/#subscribe-to-reports
|
|
694
|
+
:see: https://api.hitbtc.com/#subscribe-to-reports-2
|
|
695
|
+
:see: https://api.hitbtc.com/#subscribe-to-reports-3
|
|
696
|
+
:param str [symbol]: unified CCXT market symbol
|
|
697
|
+
:param int [since]: timestamp in ms of the earliest order to fetch
|
|
698
|
+
:param int [limit]: the maximum amount of orders to fetch
|
|
699
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
700
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
|
|
701
|
+
"""
|
|
702
|
+
await self.load_markets()
|
|
703
|
+
marketType = None
|
|
704
|
+
market = None
|
|
705
|
+
if symbol is not None:
|
|
706
|
+
market = self.market(symbol)
|
|
707
|
+
marketType, params = self.handle_market_type_and_params('watchOrders', market, params)
|
|
708
|
+
name = self.get_supported_mapping(marketType, {
|
|
709
|
+
'spot': 'spot_subscribe',
|
|
710
|
+
'margin': 'margin_subscribe',
|
|
711
|
+
'swap': 'futures_subscribe',
|
|
712
|
+
'future': 'futures_subscribe',
|
|
713
|
+
})
|
|
714
|
+
orders = await self.subscribe_private(name, symbol, params)
|
|
715
|
+
if self.newUpdates:
|
|
716
|
+
limit = orders.getLimit(symbol, limit)
|
|
717
|
+
return self.filter_by_since_limit(orders, since, limit, 'timestamp')
|
|
718
|
+
|
|
719
|
+
def handle_order(self, client: Client, message):
|
|
720
|
+
#
|
|
721
|
+
# {
|
|
722
|
+
# "jsonrpc": "2.0",
|
|
723
|
+
# "method": "spot_order", # "margin_order", "future_order"
|
|
724
|
+
# "params": {
|
|
725
|
+
# "id": 584244931496,
|
|
726
|
+
# "client_order_id": "b5acd79c0a854b01b558665bcf379456",
|
|
727
|
+
# "symbol": "BTCUSDT",
|
|
728
|
+
# "side": "buy",
|
|
729
|
+
# "status": "new",
|
|
730
|
+
# "type": "limit",
|
|
731
|
+
# "time_in_force": "GTC",
|
|
732
|
+
# "quantity": "0.01000",
|
|
733
|
+
# "quantity_cumulative": "0",
|
|
734
|
+
# "price": "0.01", # only updates and snapshots
|
|
735
|
+
# "post_only": False,
|
|
736
|
+
# "reduce_only": False, # only margin and contract
|
|
737
|
+
# "display_quantity": "0", # only updates and snapshot
|
|
738
|
+
# "created_at": "2021-07-02T22:52:32.864Z",
|
|
739
|
+
# "updated_at": "2021-07-02T22:52:32.864Z",
|
|
740
|
+
# "trade_id": 1361977606, # only trades
|
|
741
|
+
# "trade_quantity": "0.00001", # only trades
|
|
742
|
+
# "trade_price": "49595.04", # only trades
|
|
743
|
+
# "trade_fee": "0.001239876000", # only trades
|
|
744
|
+
# "trade_taker": True, # only trades, only spot
|
|
745
|
+
# "trade_position_id": 485308, # only trades, only margin
|
|
746
|
+
# "report_type": "new" # "trade", "status"(snapshot)
|
|
747
|
+
# }
|
|
748
|
+
# }
|
|
749
|
+
#
|
|
750
|
+
# {
|
|
751
|
+
# "jsonrpc": "2.0",
|
|
752
|
+
# "method": "spot_orders", # "margin_orders", "future_orders"
|
|
753
|
+
# "params": [
|
|
754
|
+
# {
|
|
755
|
+
# "id": 584244931496,
|
|
756
|
+
# "client_order_id": "b5acd79c0a854b01b558665bcf379456",
|
|
757
|
+
# "symbol": "BTCUSDT",
|
|
758
|
+
# "side": "buy",
|
|
759
|
+
# "status": "new",
|
|
760
|
+
# "type": "limit",
|
|
761
|
+
# "time_in_force": "GTC",
|
|
762
|
+
# "quantity": "0.01000",
|
|
763
|
+
# "quantity_cumulative": "0",
|
|
764
|
+
# "price": "0.01", # only updates and snapshots
|
|
765
|
+
# "post_only": False,
|
|
766
|
+
# "reduce_only": False, # only margin and contract
|
|
767
|
+
# "display_quantity": "0", # only updates and snapshot
|
|
768
|
+
# "created_at": "2021-07-02T22:52:32.864Z",
|
|
769
|
+
# "updated_at": "2021-07-02T22:52:32.864Z",
|
|
770
|
+
# "trade_id": 1361977606, # only trades
|
|
771
|
+
# "trade_quantity": "0.00001", # only trades
|
|
772
|
+
# "trade_price": "49595.04", # only trades
|
|
773
|
+
# "trade_fee": "0.001239876000", # only trades
|
|
774
|
+
# "trade_taker": True, # only trades, only spot
|
|
775
|
+
# "trade_position_id": 485308, # only trades, only margin
|
|
776
|
+
# "report_type": "new" # "trade", "status"(snapshot)
|
|
777
|
+
# }
|
|
778
|
+
# ]
|
|
779
|
+
# }
|
|
780
|
+
#
|
|
781
|
+
if self.orders is None:
|
|
782
|
+
limit = self.safe_integer(self.options, 'ordersLimit')
|
|
783
|
+
self.orders = ArrayCacheBySymbolById(limit)
|
|
784
|
+
data = self.safe_value(message, 'params', [])
|
|
785
|
+
if isinstance(data, list):
|
|
786
|
+
for i in range(0, len(data)):
|
|
787
|
+
order = data[i]
|
|
788
|
+
self.handle_order_helper(client, message, order)
|
|
789
|
+
else:
|
|
790
|
+
self.handle_order_helper(client, message, data)
|
|
791
|
+
return message
|
|
792
|
+
|
|
793
|
+
def handle_order_helper(self, client: Client, message, order):
|
|
794
|
+
orders = self.orders
|
|
795
|
+
marketId = self.safe_string_lower_2(order, 'instrument', 'symbol')
|
|
796
|
+
method = self.safe_string(message, 'method')
|
|
797
|
+
splitMethod = method.split('_order')
|
|
798
|
+
messageHash = self.safe_string(splitMethod, 0)
|
|
799
|
+
symbol = self.safe_symbol(marketId)
|
|
800
|
+
parsed = self.parse_order(order)
|
|
801
|
+
orders.append(parsed)
|
|
802
|
+
client.resolve(orders, messageHash)
|
|
803
|
+
client.resolve(orders, messageHash + '::' + symbol)
|
|
804
|
+
|
|
805
|
+
def parse_ws_order_trade(self, trade, market=None):
|
|
806
|
+
#
|
|
807
|
+
# {
|
|
808
|
+
# "id": 584244931496,
|
|
809
|
+
# "client_order_id": "b5acd79c0a854b01b558665bcf379456",
|
|
810
|
+
# "symbol": "BTCUSDT",
|
|
811
|
+
# "side": "buy",
|
|
812
|
+
# "status": "new",
|
|
813
|
+
# "type": "limit",
|
|
814
|
+
# "time_in_force": "GTC",
|
|
815
|
+
# "quantity": "0.01000",
|
|
816
|
+
# "quantity_cumulative": "0",
|
|
817
|
+
# "price": "0.01", # only updates and snapshots
|
|
818
|
+
# "post_only": False,
|
|
819
|
+
# "reduce_only": False, # only margin and contract
|
|
820
|
+
# "display_quantity": "0", # only updates and snapshot
|
|
821
|
+
# "created_at": "2021-07-02T22:52:32.864Z",
|
|
822
|
+
# "updated_at": "2021-07-02T22:52:32.864Z",
|
|
823
|
+
# "trade_id": 1361977606, # only trades
|
|
824
|
+
# "trade_quantity": "0.00001", # only trades
|
|
825
|
+
# "trade_price": "49595.04", # only trades
|
|
826
|
+
# "trade_fee": "0.001239876000", # only trades
|
|
827
|
+
# "trade_taker": True, # only trades, only spot
|
|
828
|
+
# "trade_position_id": 485308, # only trades, only margin
|
|
829
|
+
# "report_type": "new" # "trade", "status"(snapshot)
|
|
830
|
+
# }
|
|
831
|
+
#
|
|
832
|
+
timestamp = self.safe_integer(trade, 'created_at')
|
|
833
|
+
marketId = self.safe_string(trade, 'symbol')
|
|
834
|
+
return self.safe_trade({
|
|
835
|
+
'info': trade,
|
|
836
|
+
'id': self.safe_string(trade, 'trade_id'),
|
|
837
|
+
'order': self.safe_string(trade, 'id'),
|
|
838
|
+
'timestamp': timestamp,
|
|
839
|
+
'datetime': self.iso8601(timestamp),
|
|
840
|
+
'symbol': self.safe_market(marketId, market),
|
|
841
|
+
'type': None,
|
|
842
|
+
'side': self.safe_string(trade, 'side'),
|
|
843
|
+
'takerOrMaker': self.safe_string(trade, 'trade_taker'),
|
|
844
|
+
'price': self.safe_string(trade, 'trade_price'),
|
|
845
|
+
'amount': self.safe_string(trade, 'trade_quantity'),
|
|
846
|
+
'cost': None,
|
|
847
|
+
'fee': {
|
|
848
|
+
'cost': self.safe_string(trade, 'trade_fee'),
|
|
849
|
+
'currency': None,
|
|
850
|
+
'rate': None,
|
|
851
|
+
},
|
|
852
|
+
}, market)
|
|
853
|
+
|
|
854
|
+
def parse_ws_order(self, order, market=None):
|
|
855
|
+
#
|
|
856
|
+
# {
|
|
857
|
+
# "id": 584244931496,
|
|
858
|
+
# "client_order_id": "b5acd79c0a854b01b558665bcf379456",
|
|
859
|
+
# "symbol": "BTCUSDT",
|
|
860
|
+
# "side": "buy",
|
|
861
|
+
# "status": "new",
|
|
862
|
+
# "type": "limit",
|
|
863
|
+
# "time_in_force": "GTC",
|
|
864
|
+
# "quantity": "0.01000",
|
|
865
|
+
# "quantity_cumulative": "0",
|
|
866
|
+
# "price": "0.01", # only updates and snapshots
|
|
867
|
+
# "post_only": False,
|
|
868
|
+
# "reduce_only": False, # only margin and contract
|
|
869
|
+
# "display_quantity": "0", # only updates and snapshot
|
|
870
|
+
# "created_at": "2021-07-02T22:52:32.864Z",
|
|
871
|
+
# "updated_at": "2021-07-02T22:52:32.864Z",
|
|
872
|
+
# "trade_id": 1361977606, # only trades
|
|
873
|
+
# "trade_quantity": "0.00001", # only trades
|
|
874
|
+
# "trade_price": "49595.04", # only trades
|
|
875
|
+
# "trade_fee": "0.001239876000", # only trades
|
|
876
|
+
# "trade_taker": True, # only trades, only spot
|
|
877
|
+
# "trade_position_id": 485308, # only trades, only margin
|
|
878
|
+
# "report_type": "new" # "trade", "status"(snapshot)
|
|
879
|
+
# }
|
|
880
|
+
#
|
|
881
|
+
timestamp = self.safe_string(order, 'created_at')
|
|
882
|
+
marketId = self.safe_string(order, 'symbol')
|
|
883
|
+
market = self.safe_market(marketId, market)
|
|
884
|
+
tradeId = self.safe_string(order, 'trade_id')
|
|
885
|
+
trades = None
|
|
886
|
+
if tradeId is not None:
|
|
887
|
+
trade = self.parse_ws_order_trade(order, market)
|
|
888
|
+
trades = [trade]
|
|
889
|
+
rawStatus = self.safe_string(order, 'status')
|
|
890
|
+
report_type = self.safe_string(order, 'report_type')
|
|
891
|
+
parsedStatus = None
|
|
892
|
+
if report_type == 'canceled':
|
|
893
|
+
parsedStatus = self.parse_order_status(report_type)
|
|
894
|
+
else:
|
|
895
|
+
parsedStatus = self.parse_order_status(rawStatus)
|
|
896
|
+
return self.safe_order({
|
|
897
|
+
'info': order,
|
|
898
|
+
'id': self.safe_string(order, 'id'),
|
|
899
|
+
'clientOrderId': self.safe_string(order, 'client_order_id'),
|
|
900
|
+
'timestamp': timestamp,
|
|
901
|
+
'datetime': self.iso8601(timestamp),
|
|
902
|
+
'lastTradeTimestamp': None,
|
|
903
|
+
'symbol': market['symbol'],
|
|
904
|
+
'price': self.safe_string(order, 'price'),
|
|
905
|
+
'amount': self.safe_string(order, 'quantity'),
|
|
906
|
+
'type': self.safe_string(order, 'type'),
|
|
907
|
+
'side': self.safe_string_upper(order, 'side'),
|
|
908
|
+
'timeInForce': self.safe_string(order, 'time_in_force'),
|
|
909
|
+
'postOnly': self.safe_string(order, 'post_only'),
|
|
910
|
+
'reduceOnly': self.safe_value(order, 'reduce_only'),
|
|
911
|
+
'filled': None,
|
|
912
|
+
'remaining': None,
|
|
913
|
+
'cost': None,
|
|
914
|
+
'status': parsedStatus,
|
|
915
|
+
'average': None,
|
|
916
|
+
'trades': trades,
|
|
917
|
+
'fee': None,
|
|
918
|
+
}, market)
|
|
919
|
+
|
|
920
|
+
async def watch_balance(self, params={}) -> Balances:
|
|
921
|
+
"""
|
|
922
|
+
watches balance updates, cannot subscribe to margin account balances
|
|
923
|
+
:see: https://api.hitbtc.com/#subscribe-to-spot-balances
|
|
924
|
+
:see: https://api.hitbtc.com/#subscribe-to-futures-balances
|
|
925
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
926
|
+
:param str [params.type]: 'spot', 'swap', or 'future'
|
|
927
|
+
*
|
|
928
|
+
* EXCHANGE SPECIFIC PARAMETERS
|
|
929
|
+
:param str [params.mode]: 'updates' or 'batches'(default), 'updates' = messages arrive after balance updates, 'batches' = messages arrive at equal intervals if there were any updates
|
|
930
|
+
:returns dict[]: a list of `balance structures <https://docs.ccxt.com/#/?id=balance-structure>`
|
|
931
|
+
"""
|
|
932
|
+
await self.load_markets()
|
|
933
|
+
type = None
|
|
934
|
+
type, params = self.handle_market_type_and_params('watchBalance', None, params)
|
|
935
|
+
name = self.get_supported_mapping(type, {
|
|
936
|
+
'spot': 'spot_balance_subscribe',
|
|
937
|
+
'swap': 'futures_balance_subscribe',
|
|
938
|
+
'future': 'futures_balance_subscribe',
|
|
939
|
+
})
|
|
940
|
+
mode = self.safe_string(params, 'mode', 'batches')
|
|
941
|
+
params = self.omit(params, 'mode')
|
|
942
|
+
request: dict = {
|
|
943
|
+
'mode': mode,
|
|
944
|
+
}
|
|
945
|
+
return await self.subscribe_private(name, None, self.extend(request, params))
|
|
946
|
+
|
|
947
|
+
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
|
948
|
+
"""
|
|
949
|
+
create a trade order
|
|
950
|
+
:see: https://api.hitbtc.com/#create-new-spot-order
|
|
951
|
+
:see: https://api.hitbtc.com/#create-margin-order
|
|
952
|
+
:see: https://api.hitbtc.com/#create-futures-order
|
|
953
|
+
:param str symbol: unified symbol of the market to create an order in
|
|
954
|
+
:param str type: 'market' or 'limit'
|
|
955
|
+
:param str side: 'buy' or 'sell'
|
|
956
|
+
:param float amount: how much of currency you want to trade in units of base currency
|
|
957
|
+
:param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
958
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
959
|
+
:param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported for spot-margin, swap supports both, default is 'cross'
|
|
960
|
+
:param bool [params.margin]: True for creating a margin order
|
|
961
|
+
:param float [params.triggerPrice]: The price at which a trigger order is triggered at
|
|
962
|
+
:param bool [params.postOnly]: if True, the order will only be posted to the order book and not executed immediately
|
|
963
|
+
:param str [params.timeInForce]: "GTC", "IOC", "FOK", "Day", "GTD"
|
|
964
|
+
:returns dict: an `order structure <https://github.com/ccxt/ccxt/wiki/Manual#order-structure>`
|
|
965
|
+
"""
|
|
966
|
+
await self.load_markets()
|
|
967
|
+
market = self.market(symbol)
|
|
968
|
+
request = None
|
|
969
|
+
marketType = None
|
|
970
|
+
marketType, params = self.handle_market_type_and_params('createOrder', market, params)
|
|
971
|
+
marginMode = None
|
|
972
|
+
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
|
973
|
+
request, params = self.create_order_request(market, marketType, type, side, amount, price, marginMode, params)
|
|
974
|
+
request = self.extend(request, params)
|
|
975
|
+
if marketType == 'swap':
|
|
976
|
+
return await self.trade_request('futures_new_order', request)
|
|
977
|
+
elif (marketType == 'margin') or (marginMode is not None):
|
|
978
|
+
return await self.trade_request('margin_new_order', request)
|
|
979
|
+
else:
|
|
980
|
+
return await self.trade_request('spot_new_order', request)
|
|
981
|
+
|
|
982
|
+
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
983
|
+
"""
|
|
984
|
+
:see: https://api.hitbtc.com/#cancel-spot-order-2
|
|
985
|
+
:see: https://api.hitbtc.com/#cancel-futures-order-2
|
|
986
|
+
:see: https://api.hitbtc.com/#cancel-margin-order-2
|
|
987
|
+
cancels an open order
|
|
988
|
+
:param str id: order id
|
|
989
|
+
:param str symbol: unified symbol of the market the order was made in
|
|
990
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
991
|
+
:param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
|
|
992
|
+
:param bool [params.margin]: True for canceling a margin order
|
|
993
|
+
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
994
|
+
"""
|
|
995
|
+
await self.load_markets()
|
|
996
|
+
market = None
|
|
997
|
+
request = {
|
|
998
|
+
'client_order_id': id,
|
|
999
|
+
}
|
|
1000
|
+
if symbol is not None:
|
|
1001
|
+
market = self.market(symbol)
|
|
1002
|
+
marketType = None
|
|
1003
|
+
marketType, params = self.handle_market_type_and_params('cancelOrderWs', market, params)
|
|
1004
|
+
marginMode, query = self.handle_margin_mode_and_params('cancelOrderWs', params)
|
|
1005
|
+
request = self.extend(request, query)
|
|
1006
|
+
if marketType == 'swap':
|
|
1007
|
+
return await self.trade_request('futures_cancel_order', request)
|
|
1008
|
+
elif (marketType == 'margin') or (marginMode is not None):
|
|
1009
|
+
return await self.trade_request('margin_cancel_order', request)
|
|
1010
|
+
else:
|
|
1011
|
+
return await self.trade_request('spot_cancel_order', request)
|
|
1012
|
+
|
|
1013
|
+
async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
|
|
1014
|
+
"""
|
|
1015
|
+
:see: https://api.hitbtc.com/#cancel-spot-orders
|
|
1016
|
+
:see: https://api.hitbtc.com/#cancel-futures-order-3
|
|
1017
|
+
cancel all open orders
|
|
1018
|
+
:param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
|
|
1019
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1020
|
+
:param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
|
|
1021
|
+
:param bool [params.margin]: True for canceling margin orders
|
|
1022
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
1023
|
+
"""
|
|
1024
|
+
await self.load_markets()
|
|
1025
|
+
market = None
|
|
1026
|
+
if symbol is not None:
|
|
1027
|
+
market = self.market(symbol)
|
|
1028
|
+
marketType = None
|
|
1029
|
+
marketType, params = self.handle_market_type_and_params('cancelAllOrdersWs', market, params)
|
|
1030
|
+
marginMode = None
|
|
1031
|
+
marginMode, params = self.handle_margin_mode_and_params('cancelAllOrdersWs', params)
|
|
1032
|
+
if marketType == 'swap':
|
|
1033
|
+
return await self.trade_request('futures_cancel_orders', params)
|
|
1034
|
+
elif (marketType == 'margin') or (marginMode is not None):
|
|
1035
|
+
raise NotSupported(self.id + ' cancelAllOrdersWs is not supported for margin orders')
|
|
1036
|
+
else:
|
|
1037
|
+
return await self.trade_request('spot_cancel_orders', params)
|
|
1038
|
+
|
|
1039
|
+
async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
1040
|
+
"""
|
|
1041
|
+
:see: https://api.hitbtc.com/#get-active-futures-orders-2
|
|
1042
|
+
:see: https://api.hitbtc.com/#get-margin-orders
|
|
1043
|
+
:see: https://api.hitbtc.com/#get-active-spot-orders
|
|
1044
|
+
fetch all unfilled currently open orders
|
|
1045
|
+
:param str symbol: unified market symbol
|
|
1046
|
+
:param int [since]: the earliest time in ms to fetch open orders for
|
|
1047
|
+
:param int [limit]: the maximum number of open orders structures to retrieve
|
|
1048
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1049
|
+
:param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported
|
|
1050
|
+
:param bool [params.margin]: True for fetching open margin orders
|
|
1051
|
+
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
1052
|
+
"""
|
|
1053
|
+
await self.load_markets()
|
|
1054
|
+
market = None
|
|
1055
|
+
request: dict = {}
|
|
1056
|
+
if symbol is not None:
|
|
1057
|
+
market = self.market(symbol)
|
|
1058
|
+
request['symbol'] = market['id']
|
|
1059
|
+
marketType = None
|
|
1060
|
+
marketType, params = self.handle_market_type_and_params('fetchOpenOrdersWs', market, params)
|
|
1061
|
+
marginMode = None
|
|
1062
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrdersWs', params)
|
|
1063
|
+
if marketType == 'swap':
|
|
1064
|
+
return await self.trade_request('futures_get_orders', request)
|
|
1065
|
+
elif (marketType == 'margin') or (marginMode is not None):
|
|
1066
|
+
return await self.trade_request('margin_get_orders', request)
|
|
1067
|
+
else:
|
|
1068
|
+
return await self.trade_request('spot_get_orders', request)
|
|
1069
|
+
|
|
1070
|
+
def handle_balance(self, client: Client, message):
|
|
1071
|
+
#
|
|
1072
|
+
# {
|
|
1073
|
+
# "jsonrpc": "2.0",
|
|
1074
|
+
# "method": "futures_balance",
|
|
1075
|
+
# "params": [
|
|
1076
|
+
# {
|
|
1077
|
+
# "currency": "BCN",
|
|
1078
|
+
# "available": "100.000000000000",
|
|
1079
|
+
# "reserved": "0",
|
|
1080
|
+
# "reserved_margin": "0"
|
|
1081
|
+
# },
|
|
1082
|
+
# ...
|
|
1083
|
+
# ]
|
|
1084
|
+
# }
|
|
1085
|
+
#
|
|
1086
|
+
messageHash = self.safe_string(message, 'method')
|
|
1087
|
+
params = self.safe_value(message, 'params')
|
|
1088
|
+
balance = self.parse_balance(params)
|
|
1089
|
+
self.balance = self.deep_extend(self.balance, balance)
|
|
1090
|
+
client.resolve(self.balance, messageHash)
|
|
1091
|
+
|
|
1092
|
+
def handle_notification(self, client: Client, message):
|
|
1093
|
+
#
|
|
1094
|
+
# {jsonrpc: "2.0", result: True, id: null}
|
|
1095
|
+
#
|
|
1096
|
+
return message
|
|
1097
|
+
|
|
1098
|
+
def handle_order_request(self, client: Client, message):
|
|
1099
|
+
#
|
|
1100
|
+
# createOrderWs, cancelOrderWs
|
|
1101
|
+
#
|
|
1102
|
+
# {
|
|
1103
|
+
# "jsonrpc": "2.0",
|
|
1104
|
+
# "result": {
|
|
1105
|
+
# "id": 1130310696965,
|
|
1106
|
+
# "client_order_id": "OPC2oyHSkEBqIpPtniLqeW-597hUL3Yo",
|
|
1107
|
+
# "symbol": "ADAUSDT",
|
|
1108
|
+
# "side": "buy",
|
|
1109
|
+
# "status": "new",
|
|
1110
|
+
# "type": "limit",
|
|
1111
|
+
# "time_in_force": "GTC",
|
|
1112
|
+
# "quantity": "4",
|
|
1113
|
+
# "quantity_cumulative": "0",
|
|
1114
|
+
# "price": "0.3300000",
|
|
1115
|
+
# "post_only": False,
|
|
1116
|
+
# "created_at": "2023-11-17T14:58:15.903Z",
|
|
1117
|
+
# "updated_at": "2023-11-17T14:58:15.903Z",
|
|
1118
|
+
# "original_client_order_id": "d6b645556af740b1bd1683400fd9cbce", # spot_replace_order only
|
|
1119
|
+
# "report_type": "new"
|
|
1120
|
+
# "margin_mode": "isolated", # margin and future only
|
|
1121
|
+
# "reduce_only": False, # margin and future only
|
|
1122
|
+
# },
|
|
1123
|
+
# "id": 1700233093414
|
|
1124
|
+
# }
|
|
1125
|
+
#
|
|
1126
|
+
messageHash = self.safe_string(message, 'id')
|
|
1127
|
+
result = self.safe_value(message, 'result', {})
|
|
1128
|
+
if isinstance(result, list):
|
|
1129
|
+
parsedOrders = []
|
|
1130
|
+
for i in range(0, len(result)):
|
|
1131
|
+
parsedOrder = self.parse_ws_order(result[i])
|
|
1132
|
+
parsedOrders.append(parsedOrder)
|
|
1133
|
+
client.resolve(parsedOrders, messageHash)
|
|
1134
|
+
else:
|
|
1135
|
+
parsedOrder = self.parse_ws_order(result)
|
|
1136
|
+
client.resolve(parsedOrder, messageHash)
|
|
1137
|
+
return message
|
|
1138
|
+
|
|
1139
|
+
def handle_message(self, client: Client, message):
|
|
1140
|
+
self.handle_error(client, message)
|
|
1141
|
+
channel = self.safe_string_2(message, 'ch', 'method')
|
|
1142
|
+
if channel is not None:
|
|
1143
|
+
splitChannel = channel.split('/')
|
|
1144
|
+
channel = self.safe_string(splitChannel, 0)
|
|
1145
|
+
methods: dict = {
|
|
1146
|
+
'candles': self.handle_ohlcv,
|
|
1147
|
+
'ticker': self.handle_ticker,
|
|
1148
|
+
'trades': self.handle_trades,
|
|
1149
|
+
'orderbook': self.handle_order_book,
|
|
1150
|
+
'spot_order': self.handle_order,
|
|
1151
|
+
'spot_orders': self.handle_order,
|
|
1152
|
+
'margin_order': self.handle_order,
|
|
1153
|
+
'margin_orders': self.handle_order,
|
|
1154
|
+
'futures_order': self.handle_order,
|
|
1155
|
+
'futures_orders': self.handle_order,
|
|
1156
|
+
'spot_balance': self.handle_balance,
|
|
1157
|
+
'futures_balance': self.handle_balance,
|
|
1158
|
+
}
|
|
1159
|
+
method = self.safe_value(methods, channel)
|
|
1160
|
+
if method is not None:
|
|
1161
|
+
method(client, message)
|
|
1162
|
+
else:
|
|
1163
|
+
result = self.safe_value(message, 'result')
|
|
1164
|
+
clientOrderId = self.safe_string(result, 'client_order_id')
|
|
1165
|
+
if clientOrderId is not None:
|
|
1166
|
+
self.handle_order_request(client, message)
|
|
1167
|
+
if (result is True) and not ('id' in message):
|
|
1168
|
+
self.handle_authenticate(client, message)
|
|
1169
|
+
if isinstance(result, list):
|
|
1170
|
+
# to do improve self, not very reliable right now
|
|
1171
|
+
first = self.safe_value(result, 0, {})
|
|
1172
|
+
arrayLength = len(result)
|
|
1173
|
+
if (arrayLength == 0) or ('client_order_id' in first):
|
|
1174
|
+
self.handle_order_request(client, message)
|
|
1175
|
+
|
|
1176
|
+
def handle_authenticate(self, client: Client, message):
|
|
1177
|
+
#
|
|
1178
|
+
# {
|
|
1179
|
+
# "jsonrpc": "2.0",
|
|
1180
|
+
# "result": True
|
|
1181
|
+
# }
|
|
1182
|
+
#
|
|
1183
|
+
success = self.safe_value(message, 'result')
|
|
1184
|
+
messageHash = 'authenticated'
|
|
1185
|
+
if success:
|
|
1186
|
+
future = self.safe_value(client.futures, messageHash)
|
|
1187
|
+
future.resolve(True)
|
|
1188
|
+
else:
|
|
1189
|
+
error = AuthenticationError(self.id + ' ' + self.json(message))
|
|
1190
|
+
client.reject(error, messageHash)
|
|
1191
|
+
if messageHash in client.subscriptions:
|
|
1192
|
+
del client.subscriptions[messageHash]
|
|
1193
|
+
return message
|
|
1194
|
+
|
|
1195
|
+
def handle_error(self, client: Client, message):
|
|
1196
|
+
#
|
|
1197
|
+
# {
|
|
1198
|
+
# jsonrpc: '2.0',
|
|
1199
|
+
# error: {
|
|
1200
|
+
# code: 20001,
|
|
1201
|
+
# message: 'Insufficient funds',
|
|
1202
|
+
# description: 'Check that the funds are sufficient, given commissions'
|
|
1203
|
+
# },
|
|
1204
|
+
# id: 1700228604325
|
|
1205
|
+
# }
|
|
1206
|
+
#
|
|
1207
|
+
error = self.safe_value(message, 'error')
|
|
1208
|
+
if error is not None:
|
|
1209
|
+
code = self.safe_value(error, 'code')
|
|
1210
|
+
errorMessage = self.safe_string(error, 'message')
|
|
1211
|
+
description = self.safe_string(error, 'description')
|
|
1212
|
+
feedback = self.id + ' ' + description
|
|
1213
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
|
1214
|
+
self.throw_broadly_matched_exception(self.exceptions['broad'], errorMessage, feedback)
|
|
1215
|
+
raise ExchangeError(feedback) # unknown message
|
|
1216
|
+
return None
|