ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__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 +36 -14
- ccxt/abstract/alpaca.py +4 -0
- ccxt/abstract/bigone.py +1 -1
- ccxt/abstract/binance.py +112 -48
- ccxt/abstract/binancecoinm.py +112 -48
- ccxt/abstract/binanceus.py +147 -83
- ccxt/abstract/binanceusdm.py +112 -48
- ccxt/abstract/bingx.py +133 -78
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex.py +136 -65
- ccxt/abstract/bitfinex1.py +69 -0
- ccxt/abstract/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +8 -1
- ccxt/abstract/bitmart.py +13 -1
- ccxt/abstract/bitopro.py +1 -0
- ccxt/abstract/bitpanda.py +0 -12
- ccxt/abstract/bitrue.py +3 -3
- ccxt/abstract/bitstamp.py +26 -3
- ccxt/abstract/blofin.py +24 -0
- ccxt/abstract/btcbox.py +1 -0
- ccxt/abstract/bybit.py +29 -14
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/coinbase.py +6 -0
- ccxt/abstract/coinbaseadvanced.py +94 -0
- ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/coincatch.py +94 -0
- ccxt/abstract/coinex.py +233 -123
- ccxt/abstract/coinmetro.py +1 -0
- ccxt/abstract/cryptocom.py +14 -0
- ccxt/abstract/defx.py +69 -0
- ccxt/abstract/deribit.py +1 -0
- ccxt/abstract/digifinex.py +1 -0
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/gate.py +20 -0
- ccxt/abstract/gateio.py +20 -0
- ccxt/abstract/gemini.py +1 -0
- ccxt/abstract/hashkey.py +67 -0
- ccxt/abstract/hyperliquid.py +1 -1
- ccxt/abstract/independentreserve.py +6 -0
- ccxt/abstract/kraken.py +4 -3
- ccxt/abstract/krakenfutures.py +4 -0
- ccxt/abstract/kucoin.py +24 -0
- ccxt/abstract/kucoinfutures.py +34 -0
- ccxt/abstract/luno.py +2 -0
- ccxt/abstract/mexc.py +4 -0
- ccxt/abstract/myokx.py +340 -0
- ccxt/abstract/oceanex.py +5 -0
- ccxt/abstract/okx.py +30 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/oxfun.py +34 -0
- ccxt/abstract/paradex.py +40 -0
- ccxt/abstract/phemex.py +1 -0
- ccxt/abstract/upbit.py +4 -0
- ccxt/abstract/vertex.py +19 -0
- ccxt/abstract/whitebit.py +31 -1
- ccxt/abstract/woo.py +6 -2
- ccxt/abstract/woofipro.py +119 -0
- ccxt/abstract/xt.py +153 -0
- ccxt/abstract/zonda.py +6 -0
- ccxt/ace.py +164 -60
- ccxt/alpaca.py +727 -63
- ccxt/ascendex.py +395 -249
- ccxt/async_support/__init__.py +36 -14
- ccxt/async_support/ace.py +164 -60
- ccxt/async_support/alpaca.py +727 -63
- ccxt/async_support/ascendex.py +396 -249
- ccxt/async_support/base/exchange.py +531 -155
- ccxt/async_support/base/ws/aiohttp_client.py +28 -5
- ccxt/async_support/base/ws/cache.py +3 -2
- ccxt/async_support/base/ws/client.py +26 -5
- ccxt/async_support/base/ws/fast_client.py +4 -3
- ccxt/async_support/base/ws/functions.py +1 -1
- ccxt/async_support/base/ws/future.py +40 -31
- ccxt/async_support/base/ws/order_book_side.py +3 -0
- ccxt/async_support/bequant.py +1 -1
- ccxt/async_support/bigone.py +329 -202
- ccxt/async_support/binance.py +3030 -1087
- ccxt/async_support/binancecoinm.py +2 -1
- ccxt/async_support/binanceus.py +12 -1
- ccxt/async_support/binanceusdm.py +3 -1
- ccxt/async_support/bingx.py +3205 -937
- ccxt/async_support/bit2c.py +119 -38
- ccxt/async_support/bitbank.py +215 -76
- ccxt/async_support/bitbns.py +124 -53
- ccxt/async_support/bitfinex.py +3236 -1078
- ccxt/async_support/bitfinex1.py +1711 -0
- ccxt/async_support/bitflyer.py +238 -49
- ccxt/async_support/bitget.py +1525 -573
- ccxt/async_support/bithumb.py +199 -65
- ccxt/async_support/bitmart.py +1320 -435
- ccxt/async_support/bitmex.py +308 -111
- ccxt/async_support/bitopro.py +256 -96
- ccxt/async_support/bitrue.py +365 -233
- ccxt/async_support/bitso.py +201 -89
- ccxt/async_support/bitstamp.py +438 -269
- ccxt/async_support/bitteam.py +179 -73
- ccxt/async_support/bitvavo.py +180 -70
- ccxt/async_support/bl3p.py +92 -25
- ccxt/async_support/blockchaincom.py +193 -79
- ccxt/async_support/blofin.py +392 -148
- ccxt/async_support/btcalpha.py +161 -55
- ccxt/async_support/btcbox.py +250 -34
- ccxt/async_support/btcmarkets.py +232 -85
- ccxt/async_support/btcturk.py +159 -60
- ccxt/async_support/bybit.py +2231 -1193
- ccxt/async_support/cex.py +1409 -1329
- ccxt/async_support/coinbase.py +1454 -287
- ccxt/async_support/coinbaseadvanced.py +17 -0
- ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/async_support/coinbaseinternational.py +428 -88
- ccxt/async_support/coincatch.py +5152 -0
- ccxt/async_support/coincheck.py +121 -38
- ccxt/async_support/coinex.py +4020 -3339
- ccxt/async_support/coinlist.py +273 -116
- ccxt/async_support/coinmate.py +204 -97
- ccxt/async_support/coinmetro.py +203 -110
- ccxt/async_support/coinone.py +142 -68
- ccxt/async_support/coinsph.py +223 -97
- ccxt/async_support/coinspot.py +137 -62
- ccxt/async_support/cryptocom.py +515 -185
- ccxt/async_support/currencycom.py +203 -85
- ccxt/async_support/defx.py +2066 -0
- ccxt/async_support/delta.py +404 -109
- ccxt/async_support/deribit.py +639 -323
- ccxt/async_support/digifinex.py +465 -233
- ccxt/async_support/ellipx.py +1887 -0
- ccxt/async_support/exmo.py +317 -128
- ccxt/async_support/gate.py +1472 -463
- ccxt/async_support/gemini.py +206 -84
- ccxt/async_support/hashkey.py +4164 -0
- ccxt/async_support/hitbtc.py +433 -178
- ccxt/async_support/hollaex.py +207 -83
- ccxt/async_support/htx.py +1095 -563
- ccxt/async_support/huobijp.py +178 -56
- ccxt/async_support/hyperliquid.py +1678 -292
- ccxt/async_support/idex.py +219 -95
- ccxt/async_support/independentreserve.py +300 -31
- ccxt/async_support/indodax.py +226 -62
- ccxt/async_support/kraken.py +871 -354
- ccxt/async_support/krakenfutures.py +324 -100
- ccxt/async_support/kucoin.py +917 -357
- ccxt/async_support/kucoinfutures.py +1004 -149
- ccxt/async_support/kuna.py +198 -107
- ccxt/async_support/latoken.py +199 -79
- ccxt/async_support/lbank.py +360 -113
- ccxt/async_support/luno.py +185 -62
- ccxt/async_support/lykke.py +168 -55
- ccxt/async_support/mercado.py +101 -29
- ccxt/async_support/mexc.py +995 -429
- ccxt/async_support/myokx.py +53 -0
- ccxt/async_support/ndax.py +234 -82
- ccxt/async_support/novadax.py +195 -75
- ccxt/async_support/oceanex.py +244 -59
- ccxt/async_support/okcoin.py +301 -165
- ccxt/async_support/okx.py +1776 -454
- ccxt/async_support/onetrading.py +198 -414
- ccxt/async_support/oxfun.py +2898 -0
- ccxt/async_support/p2b.py +142 -52
- ccxt/async_support/paradex.py +2085 -0
- ccxt/async_support/paymium.py +56 -32
- ccxt/async_support/phemex.py +572 -196
- ccxt/async_support/poloniex.py +218 -95
- ccxt/async_support/poloniexfutures.py +260 -92
- ccxt/async_support/probit.py +143 -110
- ccxt/async_support/timex.py +123 -70
- ccxt/async_support/tokocrypto.py +129 -93
- ccxt/async_support/tradeogre.py +39 -25
- ccxt/async_support/upbit.py +322 -113
- ccxt/async_support/vertex.py +2983 -0
- ccxt/async_support/wavesexchange.py +227 -173
- ccxt/async_support/wazirx.py +145 -65
- ccxt/async_support/whitebit.py +533 -138
- ccxt/async_support/woo.py +1137 -296
- ccxt/async_support/woofipro.py +2716 -0
- ccxt/async_support/xt.py +4628 -0
- ccxt/async_support/yobit.py +160 -92
- ccxt/async_support/zaif.py +80 -33
- ccxt/async_support/zonda.py +140 -69
- ccxt/base/errors.py +51 -20
- ccxt/base/exchange.py +1722 -480
- ccxt/base/precise.py +10 -0
- ccxt/base/types.py +223 -4
- ccxt/bequant.py +1 -1
- ccxt/bigone.py +329 -202
- ccxt/binance.py +3030 -1087
- ccxt/binancecoinm.py +2 -1
- ccxt/binanceus.py +12 -1
- ccxt/binanceusdm.py +3 -1
- ccxt/bingx.py +3205 -937
- ccxt/bit2c.py +119 -38
- ccxt/bitbank.py +215 -76
- ccxt/bitbns.py +124 -53
- ccxt/bitfinex.py +3235 -1078
- ccxt/bitfinex1.py +1710 -0
- ccxt/bitflyer.py +238 -49
- ccxt/bitget.py +1525 -573
- ccxt/bithumb.py +198 -65
- ccxt/bitmart.py +1320 -435
- ccxt/bitmex.py +308 -111
- ccxt/bitopro.py +256 -96
- ccxt/bitrue.py +365 -233
- ccxt/bitso.py +201 -89
- ccxt/bitstamp.py +438 -269
- ccxt/bitteam.py +179 -73
- ccxt/bitvavo.py +180 -70
- ccxt/bl3p.py +92 -25
- ccxt/blockchaincom.py +193 -79
- ccxt/blofin.py +392 -148
- ccxt/btcalpha.py +161 -55
- ccxt/btcbox.py +250 -34
- ccxt/btcmarkets.py +232 -85
- ccxt/btcturk.py +159 -60
- ccxt/bybit.py +2231 -1193
- ccxt/cex.py +1408 -1329
- ccxt/coinbase.py +1454 -287
- ccxt/coinbaseadvanced.py +17 -0
- ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/coinbaseinternational.py +428 -88
- ccxt/coincatch.py +5152 -0
- ccxt/coincheck.py +121 -38
- ccxt/coinex.py +4020 -3339
- ccxt/coinlist.py +273 -116
- ccxt/coinmate.py +204 -97
- ccxt/coinmetro.py +203 -110
- ccxt/coinone.py +142 -68
- ccxt/coinsph.py +223 -97
- ccxt/coinspot.py +137 -62
- ccxt/cryptocom.py +515 -185
- ccxt/currencycom.py +203 -85
- ccxt/defx.py +2065 -0
- ccxt/delta.py +404 -109
- ccxt/deribit.py +639 -323
- ccxt/digifinex.py +465 -233
- ccxt/ellipx.py +1887 -0
- ccxt/exmo.py +317 -128
- ccxt/gate.py +1472 -463
- ccxt/gemini.py +206 -84
- ccxt/hashkey.py +4164 -0
- ccxt/hitbtc.py +433 -178
- ccxt/hollaex.py +207 -83
- ccxt/htx.py +1095 -563
- ccxt/huobijp.py +178 -56
- ccxt/hyperliquid.py +1677 -292
- ccxt/idex.py +219 -95
- ccxt/independentreserve.py +299 -31
- ccxt/indodax.py +226 -62
- ccxt/kraken.py +871 -354
- ccxt/krakenfutures.py +324 -100
- ccxt/kucoin.py +917 -357
- ccxt/kucoinfutures.py +1004 -149
- ccxt/kuna.py +198 -107
- ccxt/latoken.py +199 -79
- ccxt/lbank.py +360 -113
- ccxt/luno.py +185 -62
- ccxt/lykke.py +168 -55
- ccxt/mercado.py +101 -29
- ccxt/mexc.py +994 -429
- ccxt/myokx.py +53 -0
- ccxt/ndax.py +234 -82
- ccxt/novadax.py +195 -75
- ccxt/oceanex.py +244 -59
- ccxt/okcoin.py +301 -165
- ccxt/okx.py +1776 -454
- ccxt/onetrading.py +198 -414
- ccxt/oxfun.py +2897 -0
- ccxt/p2b.py +142 -52
- ccxt/paradex.py +2085 -0
- ccxt/paymium.py +56 -32
- ccxt/phemex.py +572 -196
- ccxt/poloniex.py +218 -95
- ccxt/poloniexfutures.py +260 -92
- ccxt/pro/__init__.py +29 -5
- ccxt/pro/alpaca.py +32 -17
- ccxt/pro/ascendex.py +62 -14
- ccxt/pro/bequant.py +4 -0
- ccxt/pro/binance.py +1596 -329
- ccxt/pro/binancecoinm.py +1 -0
- ccxt/pro/binanceus.py +2 -9
- ccxt/pro/binanceusdm.py +2 -0
- ccxt/pro/bingx.py +527 -134
- ccxt/pro/bitcoincom.py +4 -1
- ccxt/pro/bitfinex.py +731 -266
- ccxt/pro/bitfinex1.py +635 -0
- ccxt/pro/bitget.py +726 -357
- ccxt/pro/bithumb.py +380 -0
- ccxt/pro/bitmart.py +143 -39
- ccxt/pro/bitmex.py +199 -40
- ccxt/pro/bitopro.py +25 -13
- ccxt/pro/bitrue.py +31 -32
- ccxt/pro/bitstamp.py +7 -6
- ccxt/pro/bitvavo.py +203 -81
- ccxt/pro/blockchaincom.py +30 -17
- ccxt/pro/blofin.py +692 -0
- ccxt/pro/bybit.py +791 -82
- ccxt/pro/cex.py +99 -51
- ccxt/pro/coinbase.py +220 -30
- ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
- ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
- ccxt/pro/coinbaseinternational.py +193 -30
- ccxt/pro/coincatch.py +1464 -0
- ccxt/pro/coincheck.py +11 -6
- ccxt/pro/coinex.py +965 -665
- ccxt/pro/coinone.py +17 -10
- ccxt/pro/cryptocom.py +446 -66
- ccxt/pro/currencycom.py +11 -10
- ccxt/pro/defx.py +832 -0
- ccxt/pro/deribit.py +167 -31
- ccxt/pro/exmo.py +252 -20
- ccxt/pro/gate.py +729 -64
- ccxt/pro/gemini.py +44 -26
- ccxt/pro/hashkey.py +802 -0
- ccxt/pro/hitbtc.py +208 -103
- ccxt/pro/hollaex.py +25 -9
- ccxt/pro/htx.py +83 -39
- ccxt/pro/huobijp.py +17 -16
- ccxt/pro/hyperliquid.py +502 -31
- ccxt/pro/idex.py +28 -13
- ccxt/pro/independentreserve.py +21 -16
- ccxt/pro/kraken.py +298 -51
- ccxt/pro/krakenfutures.py +166 -75
- ccxt/pro/kucoin.py +395 -77
- ccxt/pro/kucoinfutures.py +400 -99
- ccxt/pro/lbank.py +52 -31
- ccxt/pro/luno.py +12 -10
- ccxt/pro/mexc.py +400 -50
- ccxt/pro/myokx.py +28 -0
- ccxt/pro/ndax.py +25 -12
- ccxt/pro/okcoin.py +28 -9
- ccxt/pro/okx.py +935 -124
- ccxt/pro/onetrading.py +41 -24
- ccxt/pro/oxfun.py +1054 -0
- ccxt/pro/p2b.py +100 -24
- ccxt/pro/paradex.py +352 -0
- ccxt/pro/phemex.py +92 -33
- ccxt/pro/poloniex.py +128 -49
- ccxt/pro/poloniexfutures.py +53 -32
- ccxt/pro/probit.py +92 -85
- ccxt/pro/upbit.py +401 -8
- ccxt/pro/vertex.py +943 -0
- ccxt/pro/wazirx.py +46 -28
- ccxt/pro/whitebit.py +65 -12
- ccxt/pro/woo.py +437 -65
- ccxt/pro/woofipro.py +1271 -0
- ccxt/pro/xt.py +1067 -0
- ccxt/probit.py +143 -110
- ccxt/static_dependencies/__init__.py +1 -1
- 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/py.typed +0 -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/py.typed +0 -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/py.typed +0 -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/marshmallow_oneofschema/py.typed +0 -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/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/test/{test_async.py → tests_async.py} +456 -391
- ccxt/test/tests_helpers.py +285 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/{test_sync.py → tests_sync.py} +456 -393
- ccxt/timex.py +123 -70
- ccxt/tokocrypto.py +129 -93
- ccxt/tradeogre.py +39 -25
- ccxt/upbit.py +322 -113
- ccxt/vertex.py +2983 -0
- ccxt/wavesexchange.py +227 -173
- ccxt/wazirx.py +145 -65
- ccxt/whitebit.py +533 -138
- ccxt/woo.py +1137 -296
- ccxt/woofipro.py +2716 -0
- ccxt/xt.py +4627 -0
- ccxt/yobit.py +159 -92
- ccxt/zaif.py +80 -33
- ccxt/zonda.py +140 -69
- ccxt-4.4.49.dist-info/LICENSE.txt +21 -0
- ccxt-4.4.49.dist-info/METADATA +646 -0
- ccxt-4.4.49.dist-info/RECORD +669 -0
- {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/WHEEL +1 -1
- ccxt/abstract/bitbay.py +0 -47
- ccxt/abstract/bitfinex2.py +0 -139
- ccxt/abstract/hitbtc3.py +0 -115
- ccxt/async_support/bitbay.py +0 -17
- ccxt/async_support/bitfinex2.py +0 -3496
- ccxt/async_support/flowbtc.py +0 -34
- ccxt/bitbay.py +0 -17
- ccxt/bitfinex2.py +0 -3496
- ccxt/flowbtc.py +0 -34
- ccxt/hitbtc3.py +0 -16
- ccxt/pro/bitfinex2.py +0 -1081
- ccxt/test/base/__init__.py +0 -28
- ccxt/test/base/test_account.py +0 -26
- ccxt/test/base/test_balance.py +0 -56
- ccxt/test/base/test_borrow_interest.py +0 -35
- ccxt/test/base/test_borrow_rate.py +0 -32
- ccxt/test/base/test_calculate_fee.py +0 -51
- ccxt/test/base/test_crypto.py +0 -127
- ccxt/test/base/test_currency.py +0 -76
- ccxt/test/base/test_datetime.py +0 -103
- ccxt/test/base/test_decimal_to_precision.py +0 -392
- ccxt/test/base/test_deep_extend.py +0 -68
- ccxt/test/base/test_deposit_withdrawal.py +0 -50
- ccxt/test/base/test_exchange_datetime_functions.py +0 -76
- ccxt/test/base/test_funding_rate_history.py +0 -29
- ccxt/test/base/test_last_price.py +0 -32
- ccxt/test/base/test_ledger_entry.py +0 -45
- ccxt/test/base/test_ledger_item.py +0 -48
- ccxt/test/base/test_leverage_tier.py +0 -33
- ccxt/test/base/test_margin_mode.py +0 -24
- ccxt/test/base/test_margin_modification.py +0 -35
- ccxt/test/base/test_market.py +0 -190
- ccxt/test/base/test_number.py +0 -411
- ccxt/test/base/test_ohlcv.py +0 -32
- ccxt/test/base/test_open_interest.py +0 -32
- ccxt/test/base/test_order.py +0 -64
- ccxt/test/base/test_order_book.py +0 -63
- ccxt/test/base/test_position.py +0 -60
- ccxt/test/base/test_shared_methods.py +0 -345
- ccxt/test/base/test_status.py +0 -24
- ccxt/test/base/test_throttle.py +0 -126
- ccxt/test/base/test_ticker.py +0 -86
- ccxt/test/base/test_trade.py +0 -47
- ccxt/test/base/test_trading_fee.py +0 -26
- ccxt/test/base/test_transaction.py +0 -39
- ccxt-4.2.77.dist-info/METADATA +0 -626
- ccxt-4.2.77.dist-info/RECORD +0 -534
- {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
ccxt/pro/xt.py
ADDED
@@ -0,0 +1,1067 @@
|
|
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 Balances, Int, Market, Order, OrderBook, Str, Strings, Ticker, Tickers, Trade
|
9
|
+
from ccxt.async_support.base.ws.client import Client
|
10
|
+
from typing import List
|
11
|
+
|
12
|
+
|
13
|
+
class xt(ccxt.async_support.xt):
|
14
|
+
|
15
|
+
def describe(self):
|
16
|
+
return self.deep_extend(super(xt, self).describe(), {
|
17
|
+
'has': {
|
18
|
+
'ws': True,
|
19
|
+
'watchOHLCV': True,
|
20
|
+
'watchOrderBook': True,
|
21
|
+
'watchTicker': True,
|
22
|
+
'watchTickers': True,
|
23
|
+
'watchTrades': True,
|
24
|
+
'watchTradesForSymbols': False,
|
25
|
+
'watchBalance': True,
|
26
|
+
'watchOrders': True,
|
27
|
+
'watchMyTrades': True,
|
28
|
+
'watchPositions': None, # TODO https://doc.xt.com/#futures_user_websocket_v2position
|
29
|
+
},
|
30
|
+
'urls': {
|
31
|
+
'api': {
|
32
|
+
'ws': {
|
33
|
+
'spot': 'wss://stream.xt.com',
|
34
|
+
'contract': 'wss://fstream.xt.com/ws',
|
35
|
+
},
|
36
|
+
},
|
37
|
+
},
|
38
|
+
'options': {
|
39
|
+
'tradesLimit': 1000,
|
40
|
+
'ordersLimit': 1000,
|
41
|
+
'OHLCVLimit': 1000,
|
42
|
+
'watchTicker': {
|
43
|
+
'method': 'ticker', # agg_ticker(contract only)
|
44
|
+
},
|
45
|
+
'watchTickers': {
|
46
|
+
'method': 'tickers', # agg_tickers(contract only)
|
47
|
+
},
|
48
|
+
},
|
49
|
+
'streaming': {
|
50
|
+
'keepAlive': 20000,
|
51
|
+
'ping': self.ping,
|
52
|
+
},
|
53
|
+
'token': None,
|
54
|
+
})
|
55
|
+
|
56
|
+
async def get_listen_key(self, isContract: bool):
|
57
|
+
"""
|
58
|
+
@ignore
|
59
|
+
required for private endpoints
|
60
|
+
:param str isContract: True for contract trades
|
61
|
+
|
62
|
+
https://doc.xt.com/#websocket_privategetToken
|
63
|
+
https://doc.xt.com/#futures_user_websocket_v2base
|
64
|
+
|
65
|
+
:returns str: listen key / access token
|
66
|
+
"""
|
67
|
+
self.check_required_credentials()
|
68
|
+
tradeType = 'contract' if isContract else 'spot'
|
69
|
+
url = self.urls['api']['ws'][tradeType]
|
70
|
+
if not isContract:
|
71
|
+
url = url + '/private'
|
72
|
+
client = self.client(url)
|
73
|
+
token = self.safe_string(client.subscriptions, 'token')
|
74
|
+
if token is None:
|
75
|
+
if isContract:
|
76
|
+
response = await self.privateLinearGetFutureUserV1UserListenKey()
|
77
|
+
#
|
78
|
+
# {
|
79
|
+
# returnCode: '0',
|
80
|
+
# msgInfo: 'success',
|
81
|
+
# error: null,
|
82
|
+
# result: '3BC1D71D6CF96DA3458FC35B05B633351684511731128'
|
83
|
+
# }
|
84
|
+
#
|
85
|
+
client.subscriptions['token'] = self.safe_string(response, 'result')
|
86
|
+
else:
|
87
|
+
response = await self.privateSpotPostWsToken()
|
88
|
+
#
|
89
|
+
# {
|
90
|
+
# "rc": 0,
|
91
|
+
# "mc": "SUCCESS",
|
92
|
+
# "ma": [],
|
93
|
+
# "result": {
|
94
|
+
# "token": "eyJhbqGciOiJSUzI1NiJ9.eyJhY2NvdW50SWQiOiIyMTQ2Mjg1MzIyNTU5Iiwic3ViIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsInNjb3BlIjoiYXV0aCIsImlzcyI6Inh0LmNvbSIsImxhc3RBdXRoVGltZSI6MTY2MzgxMzY5MDk1NSwic2lnblR5cGUiOiJBSyIsInVzZXJOYW1lIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsImV4cCI6MTY2NjQwNTY5MCwiZGV2aWNlIjoidW5rbm93biIsInVzZXJJZCI6MjE0NjI4NTMyMjU1OX0.h3zJlJBQrK2x1HvUxsKivnn6PlSrSDXXXJ7WqHAYSrN2CG5XPTKc4zKnTVoYFbg6fTS0u1fT8wH7wXqcLWXX71vm0YuP8PCvdPAkUIq4-HyzltbPr5uDYd0UByx0FPQtq1exvsQGe7evXQuDXx3SEJXxEqUbq_DNlXPTq_JyScI",
|
95
|
+
# "refreshToken": "eyJhbGciOiqJSUzI1NiJ9.eyJhY2NvdW50SWQiOiIyMTQ2Mjg1MzIyNTU5Iiwic3ViIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsInNjb3BlIjoicmVmcmVzaCIsImlzcyI6Inh0LmNvbSIsImxhc3RBdXRoVGltZSI6MTY2MzgxMzY5MDk1NSwic2lnblR5cGUiOiJBSyIsInVzZXJOYW1lIjoibGh4dDRfMDAwMUBzbmFwbWFpbC5jYyIsImV4cCI6MTY2NjQwNTY5MCwiZGV2aWNlIjoidW5rbm93biIsInVzZXJJZCI6MjE0NjI4NTMyMjU1OX0.Fs3YVm5YrEOzzYOSQYETSmt9iwxUHBovh2u73liv1hLUec683WGfktA_s28gMk4NCpZKFeQWFii623FvdfNoteXR0v1yZ2519uNvNndtuZICDdv3BQ4wzW1wIHZa1skxFfqvsDnGdXpjqu9UFSbtHwxprxeYfnxChNk4ssei430"
|
96
|
+
# }
|
97
|
+
# }
|
98
|
+
#
|
99
|
+
result = self.safe_dict(response, 'result')
|
100
|
+
client.subscriptions['token'] = self.safe_string(result, 'accessToken')
|
101
|
+
return client.subscriptions['token']
|
102
|
+
|
103
|
+
def get_cache_index(self, orderbook, cache):
|
104
|
+
# return the first index of the cache that can be applied to the orderbook or -1 if not possible
|
105
|
+
nonce = self.safe_integer(orderbook, 'nonce')
|
106
|
+
firstDelta = self.safe_value(cache, 0)
|
107
|
+
firstDeltaNonce = self.safe_integer_2(firstDelta, 'i', 'u')
|
108
|
+
if nonce < firstDeltaNonce - 1:
|
109
|
+
return -1
|
110
|
+
for i in range(0, len(cache)):
|
111
|
+
delta = cache[i]
|
112
|
+
deltaNonce = self.safe_integer_2(delta, 'i', 'u')
|
113
|
+
if deltaNonce >= nonce:
|
114
|
+
return i
|
115
|
+
return len(cache)
|
116
|
+
|
117
|
+
def handle_delta(self, orderbook, delta):
|
118
|
+
orderbook['nonce'] = self.safe_integer_2(delta, 'i', 'u')
|
119
|
+
obAsks = self.safe_list(delta, 'a', [])
|
120
|
+
obBids = self.safe_list(delta, 'b', [])
|
121
|
+
bids = orderbook['bids']
|
122
|
+
asks = orderbook['asks']
|
123
|
+
for i in range(0, len(obBids)):
|
124
|
+
bid = obBids[i]
|
125
|
+
price = self.safe_number(bid, 0)
|
126
|
+
quantity = self.safe_number(bid, 1)
|
127
|
+
bids.store(price, quantity)
|
128
|
+
for i in range(0, len(obAsks)):
|
129
|
+
ask = obAsks[i]
|
130
|
+
price = self.safe_number(ask, 0)
|
131
|
+
quantity = self.safe_number(ask, 1)
|
132
|
+
asks.store(price, quantity)
|
133
|
+
# self.handleBidAsks(storedBids, bids)
|
134
|
+
# self.handleBidAsks(storedAsks, asks)
|
135
|
+
|
136
|
+
async def subscribe(self, name: str, access: str, methodName: str, market: Market = None, symbols: List[str] = None, params={}):
|
137
|
+
"""
|
138
|
+
@ignore
|
139
|
+
Connects to a websocket channel
|
140
|
+
|
141
|
+
https://doc.xt.com/#websocket_privaterequestFormat
|
142
|
+
https://doc.xt.com/#futures_market_websocket_v2base
|
143
|
+
|
144
|
+
:param str name: name of the channel
|
145
|
+
:param str access: public or private
|
146
|
+
:param str methodName: the name of the CCXT class method
|
147
|
+
:param dict [market]: CCXT market
|
148
|
+
:param str[] [symbols]: unified market symbols
|
149
|
+
:param dict params: extra parameters specific to the xt api
|
150
|
+
:returns dict: data from the websocket stream
|
151
|
+
"""
|
152
|
+
privateAccess = access == 'private'
|
153
|
+
type = None
|
154
|
+
type, params = self.handle_market_type_and_params(methodName, market, params)
|
155
|
+
isContract = (type != 'spot')
|
156
|
+
subscribe = {
|
157
|
+
'method': 'SUBSCRIBE' if isContract else 'subscribe',
|
158
|
+
'id': self.number_to_string(self.milliseconds()) + name, # call back ID
|
159
|
+
}
|
160
|
+
if privateAccess:
|
161
|
+
if not isContract:
|
162
|
+
subscribe['params'] = [name]
|
163
|
+
subscribe['listenKey'] = await self.get_listen_key(isContract)
|
164
|
+
else:
|
165
|
+
listenKey = await self.get_listen_key(isContract)
|
166
|
+
param = name + '@' + listenKey
|
167
|
+
subscribe['params'] = [param]
|
168
|
+
else:
|
169
|
+
subscribe['params'] = [name]
|
170
|
+
tradeType = 'contract' if isContract else 'spot'
|
171
|
+
messageHash = name + '::' + tradeType
|
172
|
+
if symbols is not None:
|
173
|
+
messageHash = messageHash + '::' + ','.join(symbols)
|
174
|
+
request = self.extend(subscribe, params)
|
175
|
+
tail = access
|
176
|
+
if isContract:
|
177
|
+
tail = 'user' if privateAccess else 'market'
|
178
|
+
url = self.urls['api']['ws'][tradeType] + '/' + tail
|
179
|
+
return await self.watch(url, messageHash, request, messageHash)
|
180
|
+
|
181
|
+
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
182
|
+
"""
|
183
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
184
|
+
|
185
|
+
https://doc.xt.com/#websocket_publictickerRealTime
|
186
|
+
https://doc.xt.com/#futures_market_websocket_v2tickerRealTime
|
187
|
+
https://doc.xt.com/#futures_market_websocket_v2aggTickerRealTime
|
188
|
+
|
189
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
190
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
191
|
+
:param str [params.method]: 'agg_ticker'(contract only) or 'ticker', default = 'ticker' - the endpoint that will be streamed
|
192
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
|
193
|
+
"""
|
194
|
+
await self.load_markets()
|
195
|
+
market = self.market(symbol)
|
196
|
+
options = self.safe_dict(self.options, 'watchTicker')
|
197
|
+
defaultMethod = self.safe_string(options, 'method', 'ticker')
|
198
|
+
method = self.safe_string(params, 'method', defaultMethod)
|
199
|
+
name = method + '@' + market['id']
|
200
|
+
return await self.subscribe(name, 'public', 'watchTicker', market, None, params)
|
201
|
+
|
202
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
203
|
+
"""
|
204
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
205
|
+
|
206
|
+
https://doc.xt.com/#websocket_publicallTicker
|
207
|
+
https://doc.xt.com/#futures_market_websocket_v2allTicker
|
208
|
+
https://doc.xt.com/#futures_market_websocket_v2allAggTicker
|
209
|
+
|
210
|
+
:param str [symbols]: unified market symbols
|
211
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
212
|
+
:param str [params.method]: 'agg_tickers'(contract only) or 'tickers', default = 'tickers' - the endpoint that will be streamed
|
213
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/en/latest/manual.html#ticker-structure>`
|
214
|
+
"""
|
215
|
+
await self.load_markets()
|
216
|
+
options = self.safe_dict(self.options, 'watchTickers')
|
217
|
+
defaultMethod = self.safe_string(options, 'method', 'tickers')
|
218
|
+
name = self.safe_string(params, 'method', defaultMethod)
|
219
|
+
market = None
|
220
|
+
if symbols is not None:
|
221
|
+
market = self.market(symbols[0])
|
222
|
+
tickers = await self.subscribe(name, 'public', 'watchTickers', market, symbols, params)
|
223
|
+
if self.newUpdates:
|
224
|
+
return tickers
|
225
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
226
|
+
|
227
|
+
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
228
|
+
"""
|
229
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
230
|
+
|
231
|
+
https://doc.xt.com/#websocket_publicsymbolKline
|
232
|
+
https://doc.xt.com/#futures_market_websocket_v2symbolKline
|
233
|
+
|
234
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
235
|
+
:param str timeframe: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, or 1M
|
236
|
+
:param int [since]: not used by xt watchOHLCV
|
237
|
+
:param int [limit]: not used by xt watchOHLCV
|
238
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
239
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
240
|
+
"""
|
241
|
+
await self.load_markets()
|
242
|
+
market = self.market(symbol)
|
243
|
+
name = 'kline@' + market['id'] + ',' + timeframe
|
244
|
+
ohlcv = await self.subscribe(name, 'public', 'watchOHLCV', market, None, params)
|
245
|
+
if self.newUpdates:
|
246
|
+
limit = ohlcv.getLimit(symbol, limit)
|
247
|
+
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
248
|
+
|
249
|
+
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
250
|
+
"""
|
251
|
+
get the list of most recent trades for a particular symbol
|
252
|
+
|
253
|
+
https://doc.xt.com/#websocket_publicdealRecord
|
254
|
+
https://doc.xt.com/#futures_market_websocket_v2dealRecord
|
255
|
+
|
256
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
257
|
+
:param int [since]: timestamp in ms of the earliest trade to fetch
|
258
|
+
:param int [limit]: the maximum amount of trades to fetch
|
259
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
260
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
|
261
|
+
"""
|
262
|
+
await self.load_markets()
|
263
|
+
market = self.market(symbol)
|
264
|
+
name = 'trade@' + market['id']
|
265
|
+
trades = await self.subscribe(name, 'public', 'watchTrades', market, None, params)
|
266
|
+
if self.newUpdates:
|
267
|
+
limit = trades.getLimit(symbol, limit)
|
268
|
+
return self.filter_by_since_limit(trades, since, limit, 'timestamp')
|
269
|
+
|
270
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
271
|
+
"""
|
272
|
+
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
273
|
+
|
274
|
+
https://doc.xt.com/#websocket_publiclimitDepth
|
275
|
+
https://doc.xt.com/#websocket_publicincreDepth
|
276
|
+
https://doc.xt.com/#futures_market_websocket_v2limitDepth
|
277
|
+
https://doc.xt.com/#futures_market_websocket_v2increDepth
|
278
|
+
|
279
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
280
|
+
:param int [limit]: not used by xt watchOrderBook
|
281
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
282
|
+
:param int [params.levels]: 5, 10, 20, or 50
|
283
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/en/latest/manual.html#order-book-structure>` indexed by market symbols
|
284
|
+
"""
|
285
|
+
await self.load_markets()
|
286
|
+
market = self.market(symbol)
|
287
|
+
levels = self.safe_string(params, 'levels')
|
288
|
+
params = self.omit(params, 'levels')
|
289
|
+
name = 'depth_update@' + market['id']
|
290
|
+
if levels is not None:
|
291
|
+
name = 'depth@' + market['id'] + ',' + levels
|
292
|
+
orderbook = await self.subscribe(name, 'public', 'watchOrderBook', market, None, params)
|
293
|
+
return orderbook.limit()
|
294
|
+
|
295
|
+
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
296
|
+
"""
|
297
|
+
watches information on multiple orders made by the user
|
298
|
+
|
299
|
+
https://doc.xt.com/#websocket_privateorderChange
|
300
|
+
https://doc.xt.com/#futures_user_websocket_v2order
|
301
|
+
|
302
|
+
:param str [symbol]: unified market symbol
|
303
|
+
:param int [since]: not used by xt watchOrders
|
304
|
+
:param int [limit]: the maximum number of orders to return
|
305
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
306
|
+
:returns dict[]: a list of `order structures <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
|
307
|
+
"""
|
308
|
+
await self.load_markets()
|
309
|
+
name = 'order'
|
310
|
+
market = None
|
311
|
+
if symbol is not None:
|
312
|
+
market = self.market(symbol)
|
313
|
+
orders = await self.subscribe(name, 'private', 'watchOrders', market, None, params)
|
314
|
+
if self.newUpdates:
|
315
|
+
limit = orders.getLimit(symbol, limit)
|
316
|
+
return self.filter_by_since_limit(orders, since, limit, 'timestamp')
|
317
|
+
|
318
|
+
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
319
|
+
"""
|
320
|
+
watches information on multiple trades made by the user
|
321
|
+
|
322
|
+
https://doc.xt.com/#websocket_privateorderDeal
|
323
|
+
https://doc.xt.com/#futures_user_websocket_v2trade
|
324
|
+
|
325
|
+
:param str symbol: unified market symbol of the market orders were made in
|
326
|
+
:param int [since]: the earliest time in ms to fetch orders for
|
327
|
+
:param int [limit]: the maximum number of orde structures to retrieve
|
328
|
+
:param dict params: extra parameters specific to the kucoin api endpoint
|
329
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
330
|
+
"""
|
331
|
+
await self.load_markets()
|
332
|
+
name = 'trade'
|
333
|
+
market = None
|
334
|
+
if symbol is not None:
|
335
|
+
market = self.market(symbol)
|
336
|
+
trades = await self.subscribe(name, 'private', 'watchMyTrades', market, None, params)
|
337
|
+
if self.newUpdates:
|
338
|
+
limit = trades.getLimit(symbol, limit)
|
339
|
+
return self.filter_by_since_limit(trades, since, limit, 'timestamp')
|
340
|
+
|
341
|
+
async def watch_balance(self, params={}) -> Balances:
|
342
|
+
"""
|
343
|
+
watches information on multiple orders made by the user
|
344
|
+
|
345
|
+
https://doc.xt.com/#websocket_privatebalanceChange
|
346
|
+
https://doc.xt.com/#futures_user_websocket_v2balance
|
347
|
+
|
348
|
+
:param dict params: extra parameters specific to the xt api endpoint
|
349
|
+
:returns dict[]: a list of `balance structures <https://docs.ccxt.com/#/?id=balance-structure>`
|
350
|
+
"""
|
351
|
+
await self.load_markets()
|
352
|
+
name = 'balance'
|
353
|
+
return await self.subscribe(name, 'private', 'watchBalance', None, None, params)
|
354
|
+
|
355
|
+
def handle_ticker(self, client: Client, message: dict):
|
356
|
+
#
|
357
|
+
# spot
|
358
|
+
#
|
359
|
+
# {
|
360
|
+
# topic: 'ticker',
|
361
|
+
# event: 'ticker@btc_usdt',
|
362
|
+
# data: {
|
363
|
+
# s: 'btc_usdt', # symbol
|
364
|
+
# t: 1683501935877, # time(Last transaction time)
|
365
|
+
# cv: '-82.67', # priceChangeValue(24 hour price change)
|
366
|
+
# cr: '-0.0028', # priceChangeRate 24-hour price change(percentage)
|
367
|
+
# o: '28823.87', # open price
|
368
|
+
# c: '28741.20', # close price
|
369
|
+
# h: '29137.64', # highest price
|
370
|
+
# l: '28660.93', # lowest price
|
371
|
+
# q: '6372.601573', # quantity
|
372
|
+
# v: '184086075.2772391' # volume
|
373
|
+
# }
|
374
|
+
# }
|
375
|
+
#
|
376
|
+
# contract
|
377
|
+
#
|
378
|
+
# {
|
379
|
+
# "topic": "ticker",
|
380
|
+
# "event": "ticker@btc_usdt",
|
381
|
+
# "data": {
|
382
|
+
# "s": "btc_index", # trading pair
|
383
|
+
# "o": "49000", # opening price
|
384
|
+
# "c": "50000", # closing price
|
385
|
+
# "h": "0.1", # highest price
|
386
|
+
# "l": "0.1", # lowest price
|
387
|
+
# "a": "0.1", # volume
|
388
|
+
# "v": "0.1", # turnover
|
389
|
+
# "ch": "0.21", # quote change
|
390
|
+
# "t": 123124124 # timestamp
|
391
|
+
# }
|
392
|
+
# }
|
393
|
+
#
|
394
|
+
# agg_ticker(contract)
|
395
|
+
#
|
396
|
+
# {
|
397
|
+
# "topic": "agg_ticker",
|
398
|
+
# "event": "agg_ticker@btc_usdt",
|
399
|
+
# "data": {
|
400
|
+
# "s": "btc_index", # trading pair
|
401
|
+
# "o": "49000", # opening price
|
402
|
+
# "c": "50000", # closing price
|
403
|
+
# "h": "0.1", # highest price
|
404
|
+
# "l": "0.1", # lowest price
|
405
|
+
# "a": "0.1", # volume
|
406
|
+
# "v": "0.1", # turnover
|
407
|
+
# "ch": "0.21", # quote change
|
408
|
+
# "i": "0.21" , # index price
|
409
|
+
# "m": "0.21", # mark price
|
410
|
+
# "bp": "0.21", # bid price
|
411
|
+
# "ap": "0.21" , # ask price
|
412
|
+
# "t": 123124124 # timestamp
|
413
|
+
# }
|
414
|
+
# }
|
415
|
+
#
|
416
|
+
data = self.safe_dict(message, 'data')
|
417
|
+
marketId = self.safe_string(data, 's')
|
418
|
+
if marketId is not None:
|
419
|
+
cv = self.safe_string(data, 'cv')
|
420
|
+
isSpot = cv is not None
|
421
|
+
ticker = self.parse_ticker(data)
|
422
|
+
symbol = ticker['symbol']
|
423
|
+
self.tickers[symbol] = ticker
|
424
|
+
event = self.safe_string(message, 'event')
|
425
|
+
messageHashTail = 'spot' if isSpot else 'contract'
|
426
|
+
messageHash = event + '::' + messageHashTail
|
427
|
+
client.resolve(ticker, messageHash)
|
428
|
+
return message
|
429
|
+
|
430
|
+
def handle_tickers(self, client: Client, message: dict):
|
431
|
+
#
|
432
|
+
# spot
|
433
|
+
#
|
434
|
+
# {
|
435
|
+
# topic: 'tickers',
|
436
|
+
# event: 'tickers',
|
437
|
+
# data: [
|
438
|
+
# {
|
439
|
+
# s: 'elon_usdt',
|
440
|
+
# t: 1683502958381,
|
441
|
+
# cv: '-0.0000000125',
|
442
|
+
# cr: '-0.0495',
|
443
|
+
# o: '0.0000002522',
|
444
|
+
# c: '0.0000002397',
|
445
|
+
# h: '0.0000002690',
|
446
|
+
# l: '0.0000002371',
|
447
|
+
# q: '3803783034.0000000000',
|
448
|
+
# v: '955.3260820022'
|
449
|
+
# },
|
450
|
+
# ...
|
451
|
+
# ]
|
452
|
+
# }
|
453
|
+
#
|
454
|
+
# contract
|
455
|
+
#
|
456
|
+
# {
|
457
|
+
# "topic": "tickers",
|
458
|
+
# "event": "tickers",
|
459
|
+
# "data": [
|
460
|
+
# {
|
461
|
+
# "s": "btc_index", # trading pair
|
462
|
+
# "o": "49000", # opening price
|
463
|
+
# "c": "50000", # closing price
|
464
|
+
# "h": "0.1", # highest price
|
465
|
+
# "l": "0.1", # lowest price
|
466
|
+
# "a": "0.1", # volume
|
467
|
+
# "v": "0.1", # turnover
|
468
|
+
# "ch": "0.21", # quote change
|
469
|
+
# "t": 123124124 # timestamp
|
470
|
+
# }
|
471
|
+
# ]
|
472
|
+
# }
|
473
|
+
#
|
474
|
+
# agg_ticker(contract)
|
475
|
+
#
|
476
|
+
# {
|
477
|
+
# "topic": "agg_tickers",
|
478
|
+
# "event": "agg_tickers",
|
479
|
+
# "data": [
|
480
|
+
# {
|
481
|
+
# "s": "btc_index", # trading pair
|
482
|
+
# "o": "49000", # opening price
|
483
|
+
# "c": "50000", # closing price
|
484
|
+
# "h": "0.1", # highest price
|
485
|
+
# "l": "0.1", # lowest price
|
486
|
+
# "a": "0.1", # volume
|
487
|
+
# "v": "0.1", # turnover
|
488
|
+
# "ch": "0.21", # quote change
|
489
|
+
# "i": "0.21" , # index price
|
490
|
+
# "m": "0.21", # mark price
|
491
|
+
# "bp": "0.21", # bid price
|
492
|
+
# "ap": "0.21" , # ask price
|
493
|
+
# "t": 123124124 # timestamp
|
494
|
+
# }
|
495
|
+
# ]
|
496
|
+
# }
|
497
|
+
#
|
498
|
+
data = self.safe_list(message, 'data', [])
|
499
|
+
firstTicker = self.safe_dict(data, 0)
|
500
|
+
spotTest = self.safe_string_2(firstTicker, 'cv', 'aq')
|
501
|
+
tradeType = 'spot' if (spotTest is not None) else 'contract'
|
502
|
+
newTickers = []
|
503
|
+
for i in range(0, len(data)):
|
504
|
+
tickerData = data[i]
|
505
|
+
ticker = self.parse_ticker(tickerData)
|
506
|
+
symbol = ticker['symbol']
|
507
|
+
self.tickers[symbol] = ticker
|
508
|
+
newTickers.append(ticker)
|
509
|
+
messageHashStart = self.safe_string(message, 'topic') + '::' + tradeType
|
510
|
+
messageHashes = self.find_message_hashes(client, messageHashStart + '::')
|
511
|
+
for i in range(0, len(messageHashes)):
|
512
|
+
messageHash = messageHashes[i]
|
513
|
+
parts = messageHash.split('::')
|
514
|
+
symbolsString = parts[2]
|
515
|
+
symbols = symbolsString.split(',')
|
516
|
+
tickers = self.filter_by_array(newTickers, 'symbol', symbols)
|
517
|
+
tickersSymbols = list(tickers.keys())
|
518
|
+
numTickers = len(tickersSymbols)
|
519
|
+
if numTickers > 0:
|
520
|
+
client.resolve(tickers, messageHash)
|
521
|
+
client.resolve(self.tickers, messageHashStart)
|
522
|
+
return message
|
523
|
+
|
524
|
+
def handle_ohlcv(self, client: Client, message: dict):
|
525
|
+
#
|
526
|
+
# spot
|
527
|
+
#
|
528
|
+
# {
|
529
|
+
# "topic": "kline",
|
530
|
+
# "event": "kline@btc_usdt,5m",
|
531
|
+
# "data": {
|
532
|
+
# "s": "btc_usdt", # symbol
|
533
|
+
# "t": 1656043200000, # time
|
534
|
+
# "i": "5m", # interval
|
535
|
+
# "o": "44000", # open price
|
536
|
+
# "c": "50000", # close price
|
537
|
+
# "h": "52000", # highest price
|
538
|
+
# "l": "36000", # lowest price
|
539
|
+
# "q": "34.2", # qty(quantity)
|
540
|
+
# "v": "230000" # volume
|
541
|
+
# }
|
542
|
+
# }
|
543
|
+
#
|
544
|
+
# contract
|
545
|
+
#
|
546
|
+
# {
|
547
|
+
# "topic": "kline",
|
548
|
+
# "event": "kline@btc_usdt,5m",
|
549
|
+
# "data": {
|
550
|
+
# "s": "btc_index", # trading pair
|
551
|
+
# "o": "49000", # opening price
|
552
|
+
# "c": "50000", # closing price
|
553
|
+
# "h": "0.1", # highest price
|
554
|
+
# "l": "0.1", # lowest price
|
555
|
+
# "a": "0.1", # volume
|
556
|
+
# "v": "0.1", # turnover
|
557
|
+
# "ch": "0.21", # quote change
|
558
|
+
# "t": 123124124 # timestamp
|
559
|
+
# }
|
560
|
+
# }
|
561
|
+
#
|
562
|
+
data = self.safe_dict(message, 'data', {})
|
563
|
+
marketId = self.safe_string(data, 's')
|
564
|
+
if marketId is not None:
|
565
|
+
timeframe = self.safe_string(data, 'i')
|
566
|
+
tradeType = 'spot' if ('q' in data) else 'contract'
|
567
|
+
market = self.safe_market(marketId, None, None, tradeType)
|
568
|
+
symbol = market['symbol']
|
569
|
+
parsed = self.parse_ohlcv(data, market)
|
570
|
+
self.ohlcvs[symbol] = self.safe_dict(self.ohlcvs, symbol, {})
|
571
|
+
stored = self.safe_value(self.ohlcvs[symbol], timeframe)
|
572
|
+
if stored is None:
|
573
|
+
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
574
|
+
stored = ArrayCacheByTimestamp(limit)
|
575
|
+
self.ohlcvs[symbol][timeframe] = stored
|
576
|
+
stored.append(parsed)
|
577
|
+
event = self.safe_string(message, 'event')
|
578
|
+
messageHash = event + '::' + tradeType
|
579
|
+
client.resolve(stored, messageHash)
|
580
|
+
return message
|
581
|
+
|
582
|
+
def handle_trade(self, client: Client, message: dict):
|
583
|
+
#
|
584
|
+
# spot
|
585
|
+
#
|
586
|
+
# {
|
587
|
+
# topic: 'trade',
|
588
|
+
# event: 'trade@btc_usdt',
|
589
|
+
# data: {
|
590
|
+
# s: 'btc_usdt',
|
591
|
+
# i: '228825383103928709',
|
592
|
+
# t: 1684258222702,
|
593
|
+
# p: '27003.65',
|
594
|
+
# q: '0.000796',
|
595
|
+
# b: True
|
596
|
+
# }
|
597
|
+
# }
|
598
|
+
#
|
599
|
+
# contract
|
600
|
+
#
|
601
|
+
# {
|
602
|
+
# "topic": "trade",
|
603
|
+
# "event": "trade@btc_usdt",
|
604
|
+
# "data": {
|
605
|
+
# "s": "btc_index", # trading pair
|
606
|
+
# "p": "50000", # price
|
607
|
+
# "a": "0.1" # Quantity
|
608
|
+
# "m": "BID" # Deal side BID:Buy ASK:Sell
|
609
|
+
# "t": 123124124 # timestamp
|
610
|
+
# }
|
611
|
+
# }
|
612
|
+
#
|
613
|
+
data = self.safe_dict(message, 'data')
|
614
|
+
marketId = self.safe_string_lower(data, 's')
|
615
|
+
if marketId is not None:
|
616
|
+
trade = self.parse_trade(data)
|
617
|
+
i = self.safe_string(data, 'i')
|
618
|
+
tradeType = 'spot' if (i is not None) else 'contract'
|
619
|
+
market = self.safe_market(marketId, None, None, tradeType)
|
620
|
+
symbol = market['symbol']
|
621
|
+
event = self.safe_string(message, 'event')
|
622
|
+
tradesArray = self.safe_value(self.trades, symbol)
|
623
|
+
if tradesArray is None:
|
624
|
+
tradesLimit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
625
|
+
tradesArray = ArrayCache(tradesLimit)
|
626
|
+
self.trades[symbol] = tradesArray
|
627
|
+
tradesArray.append(trade)
|
628
|
+
messageHash = event + '::' + tradeType
|
629
|
+
client.resolve(tradesArray, messageHash)
|
630
|
+
return message
|
631
|
+
|
632
|
+
def handle_order_book(self, client: Client, message: dict):
|
633
|
+
#
|
634
|
+
# spot
|
635
|
+
#
|
636
|
+
# {
|
637
|
+
# "topic": "depth",
|
638
|
+
# "event": "depth@btc_usdt,20",
|
639
|
+
# "data": {
|
640
|
+
# "s": "btc_usdt", # symbol
|
641
|
+
# "fi": 1681433733351, # firstUpdateId = previous lastUpdateId + 1
|
642
|
+
# "i": 1681433733371, # updateId
|
643
|
+
# "a": [ # asks(sell order)
|
644
|
+
# [ # [0]price, [1]quantity
|
645
|
+
# "34000", # price
|
646
|
+
# "1.2" # quantity
|
647
|
+
# ],
|
648
|
+
# [
|
649
|
+
# "34001",
|
650
|
+
# "2.3"
|
651
|
+
# ]
|
652
|
+
# ],
|
653
|
+
# "b": [ # bids(buy order)
|
654
|
+
# [
|
655
|
+
# "32000",
|
656
|
+
# "0.2"
|
657
|
+
# ],
|
658
|
+
# [
|
659
|
+
# "31000",
|
660
|
+
# "0.5"
|
661
|
+
# ]
|
662
|
+
# ]
|
663
|
+
# }
|
664
|
+
# }
|
665
|
+
#
|
666
|
+
# contract
|
667
|
+
#
|
668
|
+
# {
|
669
|
+
# "topic": "depth",
|
670
|
+
# "event": "depth@btc_usdt,20",
|
671
|
+
# "data": {
|
672
|
+
# s: "btc_usdt",
|
673
|
+
# pu: "548111455664",
|
674
|
+
# fu: "548111455665",
|
675
|
+
# u: "548111455667",
|
676
|
+
# a: [
|
677
|
+
# [
|
678
|
+
# "26841.5",
|
679
|
+
# "50210",
|
680
|
+
# ],
|
681
|
+
# ],
|
682
|
+
# b: [
|
683
|
+
# [
|
684
|
+
# "26841",
|
685
|
+
# "67075",
|
686
|
+
# ],
|
687
|
+
# ],
|
688
|
+
# t: 1684530667083,
|
689
|
+
# }
|
690
|
+
# }
|
691
|
+
#
|
692
|
+
data = self.safe_dict(message, 'data')
|
693
|
+
marketId = self.safe_string(data, 's')
|
694
|
+
if marketId is not None:
|
695
|
+
event = self.safe_string(message, 'event')
|
696
|
+
splitEvent = event.split(',')
|
697
|
+
event = self.safe_string(splitEvent, 0)
|
698
|
+
tradeType = 'contract' if ('fu' in data) else 'spot'
|
699
|
+
market = self.safe_market(marketId, None, None, tradeType)
|
700
|
+
symbol = market['symbol']
|
701
|
+
obAsks = self.safe_list(data, 'a')
|
702
|
+
obBids = self.safe_list(data, 'b')
|
703
|
+
messageHash = event + '::' + tradeType
|
704
|
+
if not (symbol in self.orderbooks):
|
705
|
+
subscription = self.safe_dict(client.subscriptions, messageHash, {})
|
706
|
+
limit = self.safe_integer(subscription, 'limit')
|
707
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
708
|
+
orderbook = self.orderbooks[symbol]
|
709
|
+
nonce = self.safe_integer(orderbook, 'nonce')
|
710
|
+
if nonce is None:
|
711
|
+
cacheLength = len(orderbook.cache)
|
712
|
+
snapshotDelay = self.handle_option('watchOrderBook', 'snapshotDelay', 25)
|
713
|
+
if cacheLength == snapshotDelay:
|
714
|
+
self.spawn(self.load_order_book, client, messageHash, symbol)
|
715
|
+
orderbook.cache.append(data)
|
716
|
+
return
|
717
|
+
if obAsks is not None:
|
718
|
+
asks = orderbook['asks']
|
719
|
+
for i in range(0, len(obAsks)):
|
720
|
+
ask = obAsks[i]
|
721
|
+
price = self.safe_number(ask, 0)
|
722
|
+
quantity = self.safe_number(ask, 1)
|
723
|
+
asks.store(price, quantity)
|
724
|
+
if obBids is not None:
|
725
|
+
bids = orderbook['bids']
|
726
|
+
for i in range(0, len(obBids)):
|
727
|
+
bid = obBids[i]
|
728
|
+
price = self.safe_number(bid, 0)
|
729
|
+
quantity = self.safe_number(bid, 1)
|
730
|
+
bids.store(price, quantity)
|
731
|
+
timestamp = self.safe_integer(data, 't')
|
732
|
+
orderbook['nonce'] = self.safe_integer_2(data, 'i', 'u')
|
733
|
+
orderbook['timestamp'] = timestamp
|
734
|
+
orderbook['datetime'] = self.iso8601(timestamp)
|
735
|
+
orderbook['symbol'] = symbol
|
736
|
+
client.resolve(orderbook, messageHash)
|
737
|
+
|
738
|
+
def parse_ws_order_trade(self, trade: dict, market: Market = None):
|
739
|
+
#
|
740
|
+
# {
|
741
|
+
# "s": "btc_usdt", # symbol
|
742
|
+
# "t": 1656043204763, # time happened time
|
743
|
+
# "i": "6216559590087220004", # orderId,
|
744
|
+
# "ci": "test123", # clientOrderId
|
745
|
+
# "st": "PARTIALLY_FILLED", # state
|
746
|
+
# "sd": "BUY", # side BUY/SELL
|
747
|
+
# "eq": "2", # executedQty executed quantity
|
748
|
+
# "ap": "30000", # avg price
|
749
|
+
# "f": "0.002" # fee
|
750
|
+
# }
|
751
|
+
#
|
752
|
+
# contract
|
753
|
+
#
|
754
|
+
# {
|
755
|
+
# "symbol": "btc_usdt", # Trading pair
|
756
|
+
# "orderId": "1234", # Order Id
|
757
|
+
# "origQty": "34244", # Original Quantity
|
758
|
+
# "avgPrice": "123", # Quantity
|
759
|
+
# "price": "1111", # Average price
|
760
|
+
# "executedQty": "34244", # Volume(Cont)
|
761
|
+
# "orderSide": "BUY", # BUY, SELL
|
762
|
+
# "positionSide": "LONG", # LONG, SHORT
|
763
|
+
# "marginFrozen": "123", # Occupied margin
|
764
|
+
# "sourceType": "default", # DEFAULT:normal order,ENTRUST:plan commission,PROFIR:Take Profit and Stop Loss
|
765
|
+
# "sourceId" : "1231231", # Triggering conditions ID
|
766
|
+
# "state": "", # state:NEW:New order(unfilled);PARTIALLY_FILLED:Partial deal;PARTIALLY_CANCELED:Partial revocation;FILLED:Filled;CANCELED:Cancled;REJECTED:Order failed;EXPIRED:Expired
|
767
|
+
# "createTime": 1731231231, # CreateTime
|
768
|
+
# "clientOrderId": "204788317630342726"
|
769
|
+
# }
|
770
|
+
#
|
771
|
+
marketId = self.safe_string(trade, 's')
|
772
|
+
tradeType = 'contract' if ('symbol' in trade) else 'spot'
|
773
|
+
market = self.safe_market(marketId, market, None, tradeType)
|
774
|
+
timestamp = self.safe_string(trade, 't')
|
775
|
+
return self.safe_trade({
|
776
|
+
'info': trade,
|
777
|
+
'id': None,
|
778
|
+
'timestamp': timestamp,
|
779
|
+
'datetime': self.iso8601(timestamp),
|
780
|
+
'symbol': market['symbol'],
|
781
|
+
'order': self.safe_string(trade, 'i', 'orderId'),
|
782
|
+
'type': self.parse_order_status(self.safe_string(trade, 'st', 'state')),
|
783
|
+
'side': self.safe_string_lower(trade, 'sd', 'orderSide'),
|
784
|
+
'takerOrMaker': None,
|
785
|
+
'price': self.safe_number(trade, 'price'),
|
786
|
+
'amount': self.safe_string(trade, 'origQty'),
|
787
|
+
'cost': None,
|
788
|
+
'fee': {
|
789
|
+
'currency': None,
|
790
|
+
'cost': self.safe_number(trade, 'f'),
|
791
|
+
'rate': None,
|
792
|
+
},
|
793
|
+
}, market)
|
794
|
+
|
795
|
+
def parse_ws_order(self, order: dict, market: Market = None):
|
796
|
+
#
|
797
|
+
# spot
|
798
|
+
#
|
799
|
+
# {
|
800
|
+
# "s": "btc_usdt", # symbol
|
801
|
+
# "bc": "btc", # base currency
|
802
|
+
# "qc": "usdt", # quotation currency
|
803
|
+
# "t": 1656043204763, # happened time
|
804
|
+
# "ct": 1656043204663, # create time
|
805
|
+
# "i": "6216559590087220004", # order id,
|
806
|
+
# "ci": "test123", # client order id
|
807
|
+
# "st": "PARTIALLY_FILLED", # state NEW/PARTIALLY_FILLED/FILLED/CANCELED/REJECTED/EXPIRED
|
808
|
+
# "sd": "BUY", # side BUY/SELL
|
809
|
+
# "tp": "LIMIT", # type LIMIT/MARKET
|
810
|
+
# "oq": "4" # original quantity
|
811
|
+
# "oqq": 48000, # original quotation quantity
|
812
|
+
# "eq": "2", # executed quantity
|
813
|
+
# "lq": "2", # remaining quantity
|
814
|
+
# "p": "4000", # price
|
815
|
+
# "ap": "30000", # avg price
|
816
|
+
# "f":"0.002" # fee
|
817
|
+
# }
|
818
|
+
#
|
819
|
+
# contract
|
820
|
+
#
|
821
|
+
# {
|
822
|
+
# "symbol": "btc_usdt", # Trading pair
|
823
|
+
# "orderId": "1234", # Order Id
|
824
|
+
# "origQty": "34244", # Original Quantity
|
825
|
+
# "avgPrice": "123", # Quantity
|
826
|
+
# "price": "1111", # Average price
|
827
|
+
# "executedQty": "34244", # Volume(Cont)
|
828
|
+
# "orderSide": "BUY", # BUY, SELL
|
829
|
+
# "positionSide": "LONG", # LONG, SHORT
|
830
|
+
# "marginFrozen": "123", # Occupied margin
|
831
|
+
# "sourceType": "default", # DEFAULT:normal order,ENTRUST:plan commission,PROFIR:Take Profit and Stop Loss
|
832
|
+
# "sourceId" : "1231231", # Triggering conditions ID
|
833
|
+
# "state": "", # state:NEW:New order(unfilled);PARTIALLY_FILLED:Partial deal;PARTIALLY_CANCELED:Partial revocation;FILLED:Filled;CANCELED:Cancled;REJECTED:Order failed;EXPIRED:Expired
|
834
|
+
# "createTime": 1731231231, # CreateTime
|
835
|
+
# "clientOrderId": "204788317630342726"
|
836
|
+
# }
|
837
|
+
#
|
838
|
+
marketId = self.safe_string_2(order, 's', 'symbol')
|
839
|
+
tradeType = 'contract' if ('symbol' in order) else 'spot'
|
840
|
+
market = self.safe_market(marketId, market, None, tradeType)
|
841
|
+
timestamp = self.safe_integer_2(order, 'ct', 'createTime')
|
842
|
+
return self.safe_order({
|
843
|
+
'info': order,
|
844
|
+
'id': self.safe_string_2(order, 'i', 'orderId'),
|
845
|
+
'clientOrderId': self.safe_string_2(order, 'ci', 'clientOrderId'),
|
846
|
+
'timestamp': timestamp,
|
847
|
+
'datetime': self.iso8601(timestamp),
|
848
|
+
'lastTradeTimestamp': None,
|
849
|
+
'symbol': market['symbol'],
|
850
|
+
'type': market['type'],
|
851
|
+
'timeInForce': None,
|
852
|
+
'postOnly': None,
|
853
|
+
'side': self.safe_string_lower_2(order, 'sd', 'orderSide'),
|
854
|
+
'price': self.safe_number_2(order, 'p', 'price'),
|
855
|
+
'stopPrice': None,
|
856
|
+
'stopLoss': None,
|
857
|
+
'takeProfit': None,
|
858
|
+
'amount': self.safe_string_2(order, 'oq', 'origQty'),
|
859
|
+
'filled': self.safe_string_2(order, 'eq', 'executedQty'),
|
860
|
+
'remaining': self.safe_string(order, 'lq'),
|
861
|
+
'cost': None,
|
862
|
+
'average': self.safe_string_2(order, 'ap', 'avgPrice'),
|
863
|
+
'status': self.parse_order_status(self.safe_string(order, 'st', 'state')),
|
864
|
+
'fee': {
|
865
|
+
'currency': None,
|
866
|
+
'cost': self.safe_number(order, 'f'),
|
867
|
+
},
|
868
|
+
'trades': None,
|
869
|
+
}, market)
|
870
|
+
|
871
|
+
def handle_order(self, client: Client, message: dict):
|
872
|
+
#
|
873
|
+
# spot
|
874
|
+
#
|
875
|
+
# {
|
876
|
+
# "topic": "order",
|
877
|
+
# "event": "order",
|
878
|
+
# "data": {
|
879
|
+
# "s": "btc_usdt", # symbol
|
880
|
+
# "t": 1656043204763, # time happened time
|
881
|
+
# "i": "6216559590087220004", # orderId,
|
882
|
+
# "ci": "test123", # clientOrderId
|
883
|
+
# "st": "PARTIALLY_FILLED", # state
|
884
|
+
# "sd": "BUY", # side BUY/SELL
|
885
|
+
# "eq": "2", # executedQty executed quantity
|
886
|
+
# "ap": "30000", # avg price
|
887
|
+
# "f": "0.002" # fee
|
888
|
+
# }
|
889
|
+
# }
|
890
|
+
#
|
891
|
+
# contract
|
892
|
+
#
|
893
|
+
# {
|
894
|
+
# "topic": "order",
|
895
|
+
# "event": "order@123456",
|
896
|
+
# "data": {
|
897
|
+
# "symbol": "btc_usdt", # Trading pair
|
898
|
+
# "orderId": "1234", # Order Id
|
899
|
+
# "origQty": "34244", # Original Quantity
|
900
|
+
# "avgPrice": "123", # Quantity
|
901
|
+
# "price": "1111", # Average price
|
902
|
+
# "executedQty": "34244", # Volume(Cont)
|
903
|
+
# "orderSide": "BUY", # BUY, SELL
|
904
|
+
# "positionSide": "LONG", # LONG, SHORT
|
905
|
+
# "marginFrozen": "123", # Occupied margin
|
906
|
+
# "sourceType": "default", # DEFAULT:normal order,ENTRUST:plan commission,PROFIR:Take Profit and Stop Loss
|
907
|
+
# "sourceId" : "1231231", # Triggering conditions ID
|
908
|
+
# "state": "", # state:NEW:New order(unfilled);PARTIALLY_FILLED:Partial deal;PARTIALLY_CANCELED:Partial revocation;FILLED:Filled;CANCELED:Cancled;REJECTED:Order failed;EXPIRED:Expired
|
909
|
+
# "createTime": 1731231231, # CreateTime
|
910
|
+
# "clientOrderId": "204788317630342726"
|
911
|
+
# }
|
912
|
+
# }
|
913
|
+
#
|
914
|
+
orders = self.orders
|
915
|
+
if orders is None:
|
916
|
+
limit = self.safe_integer(self.options, 'ordersLimit')
|
917
|
+
orders = ArrayCacheBySymbolById(limit)
|
918
|
+
self.orders = orders
|
919
|
+
order = self.safe_dict(message, 'data', {})
|
920
|
+
marketId = self.safe_string_2(order, 's', 'symbol')
|
921
|
+
if marketId is not None:
|
922
|
+
tradeType = 'contract' if ('symbol' in order) else 'spot'
|
923
|
+
market = self.safe_market(marketId, None, None, tradeType)
|
924
|
+
parsed = self.parse_ws_order(order, market)
|
925
|
+
orders.append(parsed)
|
926
|
+
client.resolve(orders, 'order::' + tradeType)
|
927
|
+
return message
|
928
|
+
|
929
|
+
def handle_balance(self, client: Client, message: dict):
|
930
|
+
#
|
931
|
+
# spot
|
932
|
+
#
|
933
|
+
# {
|
934
|
+
# topic: 'balance',
|
935
|
+
# event: 'balance',
|
936
|
+
# data: {
|
937
|
+
# a: 3513677381884,
|
938
|
+
# t: 1684250056775,
|
939
|
+
# c: 'usdt',
|
940
|
+
# b: '7.71000000',
|
941
|
+
# f: '0.00000000',
|
942
|
+
# z: 'SPOT'
|
943
|
+
# }
|
944
|
+
# }
|
945
|
+
#
|
946
|
+
# contract
|
947
|
+
#
|
948
|
+
# {
|
949
|
+
# "topic": "balance",
|
950
|
+
# "event": "balance@123456",
|
951
|
+
# "data": {
|
952
|
+
# "coin": "usdt",
|
953
|
+
# "underlyingType": 1, # 1:Coin-M,2:USDT-M
|
954
|
+
# "walletBalance": "123", # Balance
|
955
|
+
# "openOrderMarginFrozen": "123", # Frozen order
|
956
|
+
# "isolatedMargin": "213", # Isolated Margin
|
957
|
+
# "crossedMargin": "0" # Crossed Margin
|
958
|
+
# "availableBalance": '2.256114450000000000',
|
959
|
+
# "coupon": '0',
|
960
|
+
# "bonus": '0'
|
961
|
+
# }
|
962
|
+
# }
|
963
|
+
#
|
964
|
+
data = self.safe_dict(message, 'data', {})
|
965
|
+
currencyId = self.safe_string_2(data, 'c', 'coin')
|
966
|
+
code = self.safe_currency_code(currencyId)
|
967
|
+
account = self.account()
|
968
|
+
account['free'] = self.safe_string(data, 'availableBalance')
|
969
|
+
account['used'] = self.safe_string(data, 'f')
|
970
|
+
account['total'] = self.safe_string_2(data, 'b', 'walletBalance')
|
971
|
+
self.balance[code] = account
|
972
|
+
self.balance = self.safe_balance(self.balance)
|
973
|
+
tradeType = 'contract' if ('coin' in data) else 'spot'
|
974
|
+
client.resolve(self.balance, 'balance::' + tradeType)
|
975
|
+
|
976
|
+
def handle_my_trades(self, client: Client, message: dict):
|
977
|
+
#
|
978
|
+
# spot
|
979
|
+
#
|
980
|
+
# {
|
981
|
+
# "topic": "trade",
|
982
|
+
# "event": "trade",
|
983
|
+
# "data": {
|
984
|
+
# "s": "btc_usdt", # symbol
|
985
|
+
# "t": 1656043204763, # time
|
986
|
+
# "i": "6316559590087251233", # tradeId
|
987
|
+
# "oi": "6216559590087220004", # orderId
|
988
|
+
# "p": "30000", # trade price
|
989
|
+
# "q": "3", # qty quantity
|
990
|
+
# "v": "90000" # volume trade amount
|
991
|
+
# }
|
992
|
+
# }
|
993
|
+
#
|
994
|
+
# contract
|
995
|
+
#
|
996
|
+
# {
|
997
|
+
# "topic": "trade",
|
998
|
+
# "event": "trade@123456",
|
999
|
+
# "data": {
|
1000
|
+
# "symbol": 'btc_usdt',
|
1001
|
+
# "orderSide": 'SELL',
|
1002
|
+
# "positionSide": 'LONG',
|
1003
|
+
# "orderId": '231485367663419328',
|
1004
|
+
# "price": '27152.7',
|
1005
|
+
# "quantity": '33',
|
1006
|
+
# "marginUnfrozen": '2.85318000',
|
1007
|
+
# "timestamp": 1684892412565
|
1008
|
+
# }
|
1009
|
+
# }
|
1010
|
+
#
|
1011
|
+
data = self.safe_dict(message, 'data', {})
|
1012
|
+
stored = self.myTrades
|
1013
|
+
if stored is None:
|
1014
|
+
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
1015
|
+
stored = ArrayCacheBySymbolById(limit)
|
1016
|
+
self.myTrades = stored
|
1017
|
+
parsedTrade = self.parse_trade(data)
|
1018
|
+
market = self.market(parsedTrade['symbol'])
|
1019
|
+
stored.append(parsedTrade)
|
1020
|
+
tradeType = 'contract' if market['contract'] else 'spot'
|
1021
|
+
client.resolve(stored, 'trade::' + tradeType)
|
1022
|
+
|
1023
|
+
def handle_message(self, client: Client, message):
|
1024
|
+
event = self.safe_string(message, 'event')
|
1025
|
+
if event == 'pong':
|
1026
|
+
client.onPong()
|
1027
|
+
elif event is not None:
|
1028
|
+
topic = self.safe_string(message, 'topic')
|
1029
|
+
methods = {
|
1030
|
+
'kline': self.handle_ohlcv,
|
1031
|
+
'depth': self.handle_order_book,
|
1032
|
+
'depth_update': self.handle_order_book,
|
1033
|
+
'ticker': self.handle_ticker,
|
1034
|
+
'agg_ticker': self.handle_ticker,
|
1035
|
+
'tickers': self.handle_tickers,
|
1036
|
+
'agg_tickers': self.handle_tickers,
|
1037
|
+
'balance': self.handle_balance,
|
1038
|
+
'order': self.handle_order,
|
1039
|
+
}
|
1040
|
+
method = self.safe_value(methods, topic)
|
1041
|
+
if topic == 'trade':
|
1042
|
+
data = self.safe_dict(message, 'data')
|
1043
|
+
if ('oi' in data) or ('orderId' in data):
|
1044
|
+
method = self.handle_my_trades
|
1045
|
+
else:
|
1046
|
+
method = self.handle_trade
|
1047
|
+
if method is not None:
|
1048
|
+
method(client, message)
|
1049
|
+
|
1050
|
+
def ping(self, client: Client):
|
1051
|
+
client.lastPong = self.milliseconds()
|
1052
|
+
return 'ping'
|
1053
|
+
|
1054
|
+
def handle_error_message(self, client: Client, message: dict):
|
1055
|
+
#
|
1056
|
+
# {
|
1057
|
+
# "id": "123",
|
1058
|
+
# "code": 401,
|
1059
|
+
# "msg": "token expire"
|
1060
|
+
# }
|
1061
|
+
#
|
1062
|
+
msg = self.safe_string(message, 'msg')
|
1063
|
+
if (msg == 'invalid_listen_key') or (msg == 'token expire'):
|
1064
|
+
client.subscriptions['token'] = None
|
1065
|
+
self.get_listen_key(True)
|
1066
|
+
return
|
1067
|
+
client.reject(message)
|