ccxt 4.2.77__py2.py3-none-any.whl → 4.4.48__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 +3104 -880
- 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 +1513 -563
- 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 +206 -89
- 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 +557 -323
- ccxt/async_support/digifinex.py +340 -223
- ccxt/async_support/ellipx.py +1826 -0
- ccxt/async_support/exmo.py +259 -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 +334 -178
- ccxt/async_support/hollaex.py +134 -83
- ccxt/async_support/htx.py +1095 -563
- ccxt/async_support/huobijp.py +105 -56
- ccxt/async_support/hyperliquid.py +1633 -268
- ccxt/async_support/idex.py +148 -95
- ccxt/async_support/independentreserve.py +236 -31
- ccxt/async_support/indodax.py +165 -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 +138 -106
- ccxt/async_support/latoken.py +135 -79
- ccxt/async_support/lbank.py +290 -113
- ccxt/async_support/luno.py +112 -62
- ccxt/async_support/lykke.py +104 -55
- ccxt/async_support/mercado.py +36 -29
- ccxt/async_support/mexc.py +995 -429
- ccxt/async_support/myokx.py +43 -0
- ccxt/async_support/ndax.py +163 -82
- ccxt/async_support/novadax.py +121 -75
- ccxt/async_support/oceanex.py +175 -59
- ccxt/async_support/okcoin.py +222 -163
- ccxt/async_support/okx.py +1776 -454
- ccxt/async_support/onetrading.py +132 -414
- ccxt/async_support/oxfun.py +2832 -0
- ccxt/async_support/p2b.py +79 -51
- ccxt/async_support/paradex.py +2017 -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 +3104 -880
- 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 +1513 -563
- 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 +206 -89
- 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 +557 -323
- ccxt/digifinex.py +340 -223
- ccxt/ellipx.py +1826 -0
- ccxt/exmo.py +259 -128
- ccxt/gate.py +1472 -463
- ccxt/gemini.py +206 -84
- ccxt/hashkey.py +4164 -0
- ccxt/hitbtc.py +334 -178
- ccxt/hollaex.py +134 -83
- ccxt/htx.py +1095 -563
- ccxt/huobijp.py +105 -56
- ccxt/hyperliquid.py +1632 -268
- ccxt/idex.py +148 -95
- ccxt/independentreserve.py +235 -31
- ccxt/indodax.py +165 -62
- ccxt/kraken.py +871 -354
- ccxt/krakenfutures.py +324 -100
- ccxt/kucoin.py +917 -357
- ccxt/kucoinfutures.py +1004 -149
- ccxt/kuna.py +138 -106
- ccxt/latoken.py +135 -79
- ccxt/lbank.py +290 -113
- ccxt/luno.py +112 -62
- ccxt/lykke.py +104 -55
- ccxt/mercado.py +36 -29
- ccxt/mexc.py +994 -429
- ccxt/myokx.py +43 -0
- ccxt/ndax.py +163 -82
- ccxt/novadax.py +121 -75
- ccxt/oceanex.py +175 -59
- ccxt/okcoin.py +222 -163
- ccxt/okx.py +1776 -454
- ccxt/onetrading.py +132 -414
- ccxt/oxfun.py +2831 -0
- ccxt/p2b.py +79 -51
- ccxt/paradex.py +2017 -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 +138 -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.48.dist-info/LICENSE.txt +21 -0
- ccxt-4.4.48.dist-info/METADATA +646 -0
- ccxt-4.4.48.dist-info/RECORD +669 -0
- {ccxt-4.2.77.dist-info → ccxt-4.4.48.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.48.dist-info}/top_level.txt +0 -0
ccxt/pro/okx.py
CHANGED
@@ -6,13 +6,16 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
|
+
from typing import Any
|
13
|
+
from ccxt.base.errors import ExchangeError
|
14
|
+
from ccxt.base.errors import AuthenticationError
|
12
15
|
from ccxt.base.errors import ArgumentsRequired
|
13
16
|
from ccxt.base.errors import BadRequest
|
14
17
|
from ccxt.base.errors import InvalidNonce
|
15
|
-
from ccxt.base.errors import
|
18
|
+
from ccxt.base.errors import ChecksumError
|
16
19
|
|
17
20
|
|
18
21
|
class okx(ccxt.async_support.okx):
|
@@ -22,17 +25,26 @@ class okx(ccxt.async_support.okx):
|
|
22
25
|
'has': {
|
23
26
|
'ws': True,
|
24
27
|
'watchTicker': True,
|
28
|
+
'watchMarkPrice': True,
|
29
|
+
'watchMarkPrices': True,
|
25
30
|
'watchTickers': True,
|
31
|
+
'watchBidsAsks': True,
|
26
32
|
'watchOrderBook': True,
|
27
33
|
'watchTrades': True,
|
28
34
|
'watchTradesForSymbols': True,
|
29
35
|
'watchOrderBookForSymbols': True,
|
30
36
|
'watchBalance': True,
|
37
|
+
'watchLiquidations': 'emulated',
|
38
|
+
'watchLiquidationsForSymbols': True,
|
39
|
+
'watchMyLiquidations': 'emulated',
|
40
|
+
'watchMyLiquidationsForSymbols': True,
|
31
41
|
'watchOHLCV': True,
|
32
42
|
'watchOHLCVForSymbols': True,
|
33
43
|
'watchOrders': True,
|
34
44
|
'watchMyTrades': True,
|
35
45
|
'watchPositions': True,
|
46
|
+
'watchFundingRate': True,
|
47
|
+
'watchFundingRates': True,
|
36
48
|
'createOrderWs': True,
|
37
49
|
'editOrderWs': True,
|
38
50
|
'cancelOrderWs': True,
|
@@ -49,6 +61,7 @@ class okx(ccxt.async_support.okx):
|
|
49
61
|
},
|
50
62
|
'options': {
|
51
63
|
'watchOrderBook': {
|
64
|
+
'checksum': True,
|
52
65
|
#
|
53
66
|
# bbo-tbt
|
54
67
|
# 1. Newly added channel that sends tick-by-tick Level 1 data
|
@@ -96,13 +109,12 @@ class okx(ccxt.async_support.okx):
|
|
96
109
|
'ws': {
|
97
110
|
# 'inflate': True,
|
98
111
|
},
|
99
|
-
'checksum': True,
|
100
112
|
},
|
101
113
|
'streaming': {
|
102
114
|
# okex does not support built-in ws protocol-level ping-pong
|
103
115
|
# instead it requires a custom text-based ping-pong
|
104
116
|
'ping': self.ping,
|
105
|
-
'keepAlive':
|
117
|
+
'keepAlive': 18000,
|
106
118
|
},
|
107
119
|
})
|
108
120
|
|
@@ -125,33 +137,33 @@ class okx(ccxt.async_support.okx):
|
|
125
137
|
symbols = self.symbols
|
126
138
|
symbols = self.market_symbols(symbols)
|
127
139
|
url = self.get_url(channel, access)
|
128
|
-
|
140
|
+
messageHashes = []
|
129
141
|
args = []
|
130
|
-
messageHash += '::' + ','.join(symbols)
|
131
142
|
for i in range(0, len(symbols)):
|
132
143
|
marketId = self.market_id(symbols[i])
|
133
|
-
arg = {
|
144
|
+
arg: dict = {
|
134
145
|
'channel': channel,
|
135
146
|
'instId': marketId,
|
136
147
|
}
|
137
148
|
args.append(self.extend(arg, params))
|
138
|
-
|
149
|
+
messageHashes.append(channel + '::' + symbols[i])
|
150
|
+
request: dict = {
|
139
151
|
'op': 'subscribe',
|
140
152
|
'args': args,
|
141
153
|
}
|
142
|
-
return await self.
|
154
|
+
return await self.watch_multiple(url, messageHashes, request, messageHashes)
|
143
155
|
|
144
156
|
async def subscribe(self, access, messageHash, channel, symbol, params={}):
|
145
157
|
await self.load_markets()
|
146
158
|
url = self.get_url(channel, access)
|
147
|
-
firstArgument = {
|
159
|
+
firstArgument: dict = {
|
148
160
|
'channel': channel,
|
149
161
|
}
|
150
162
|
if symbol is not None:
|
151
163
|
market = self.market(symbol)
|
152
164
|
messageHash += ':' + market['id']
|
153
165
|
firstArgument['instId'] = market['id']
|
154
|
-
request = {
|
166
|
+
request: dict = {
|
155
167
|
'op': 'subscribe',
|
156
168
|
'args': [
|
157
169
|
self.deep_extend(firstArgument, params),
|
@@ -173,7 +185,7 @@ class okx(ccxt.async_support.okx):
|
|
173
185
|
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
174
186
|
"""
|
175
187
|
get the list of most recent trades for a particular symbol
|
176
|
-
:param str
|
188
|
+
:param str symbols:
|
177
189
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
178
190
|
:param int [limit]: the maximum amount of trades to fetch
|
179
191
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -191,12 +203,12 @@ class okx(ccxt.async_support.okx):
|
|
191
203
|
symbol = symbols[i]
|
192
204
|
messageHashes.append(channel + ':' + symbol)
|
193
205
|
marketId = self.market_id(symbol)
|
194
|
-
topic = {
|
206
|
+
topic: dict = {
|
195
207
|
'channel': channel,
|
196
208
|
'instId': marketId,
|
197
209
|
}
|
198
210
|
topics.append(topic)
|
199
|
-
request = {
|
211
|
+
request: dict = {
|
200
212
|
'op': 'subscribe',
|
201
213
|
'args': topics,
|
202
214
|
}
|
@@ -208,6 +220,43 @@ class okx(ccxt.async_support.okx):
|
|
208
220
|
limit = trades.getLimit(tradeSymbol, limit)
|
209
221
|
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
210
222
|
|
223
|
+
async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
|
224
|
+
"""
|
225
|
+
unWatches from the stream channel
|
226
|
+
:param str[] symbols:
|
227
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
228
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
229
|
+
"""
|
230
|
+
await self.load_markets()
|
231
|
+
symbols = self.market_symbols(symbols, None, False)
|
232
|
+
channel = 'trades'
|
233
|
+
topics = []
|
234
|
+
messageHashes = []
|
235
|
+
for i in range(0, len(symbols)):
|
236
|
+
symbol = symbols[i]
|
237
|
+
messageHashes.append('unsubscribe:trades:' + symbol)
|
238
|
+
marketId = self.market_id(symbol)
|
239
|
+
topic: dict = {
|
240
|
+
'channel': channel,
|
241
|
+
'instId': marketId,
|
242
|
+
}
|
243
|
+
topics.append(topic)
|
244
|
+
request: dict = {
|
245
|
+
'op': 'unsubscribe',
|
246
|
+
'args': topics,
|
247
|
+
}
|
248
|
+
url = self.get_url(channel, 'public')
|
249
|
+
return await self.watch_multiple(url, messageHashes, request, messageHashes)
|
250
|
+
|
251
|
+
async def un_watch_trades(self, symbol: str, params={}) -> Any:
|
252
|
+
"""
|
253
|
+
unWatches from the stream channel
|
254
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
255
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
256
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
257
|
+
"""
|
258
|
+
return await self.un_watch_trades_for_symbols([symbol], params)
|
259
|
+
|
211
260
|
def handle_trades(self, client: Client, message):
|
212
261
|
#
|
213
262
|
# {
|
@@ -240,9 +289,90 @@ class okx(ccxt.async_support.okx):
|
|
240
289
|
stored.append(trade)
|
241
290
|
client.resolve(stored, messageHash)
|
242
291
|
|
292
|
+
async def watch_funding_rate(self, symbol: str, params={}) -> FundingRate:
|
293
|
+
"""
|
294
|
+
watch the current funding rate
|
295
|
+
|
296
|
+
https://www.okx.com/docs-v5/en/#public-data-websocket-funding-rate-channel
|
297
|
+
|
298
|
+
:param str symbol: unified market symbol
|
299
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
300
|
+
:returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
|
301
|
+
"""
|
302
|
+
symbol = self.symbol(symbol)
|
303
|
+
fr = await self.watch_funding_rates([symbol], params)
|
304
|
+
return fr[symbol]
|
305
|
+
|
306
|
+
async def watch_funding_rates(self, symbols: List[str], params={}) -> FundingRates:
|
307
|
+
"""
|
308
|
+
watch the funding rate for multiple markets
|
309
|
+
|
310
|
+
https://www.okx.com/docs-v5/en/#public-data-websocket-funding-rate-channel
|
311
|
+
|
312
|
+
:param str[] symbols: list of unified market symbols
|
313
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
314
|
+
:returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
|
315
|
+
"""
|
316
|
+
await self.load_markets()
|
317
|
+
symbols = self.market_symbols(symbols)
|
318
|
+
channel = 'funding-rate'
|
319
|
+
topics = []
|
320
|
+
messageHashes = []
|
321
|
+
for i in range(0, len(symbols)):
|
322
|
+
symbol = symbols[i]
|
323
|
+
messageHashes.append(channel + ':' + symbol)
|
324
|
+
marketId = self.market_id(symbol)
|
325
|
+
topic: dict = {
|
326
|
+
'channel': channel,
|
327
|
+
'instId': marketId,
|
328
|
+
}
|
329
|
+
topics.append(topic)
|
330
|
+
request: dict = {
|
331
|
+
'op': 'subscribe',
|
332
|
+
'args': topics,
|
333
|
+
}
|
334
|
+
url = self.get_url(channel, 'public')
|
335
|
+
fundingRate = await self.watch_multiple(url, messageHashes, request, messageHashes)
|
336
|
+
if self.newUpdates:
|
337
|
+
symbol = self.safe_string(fundingRate, 'symbol')
|
338
|
+
result: dict = {}
|
339
|
+
result[symbol] = fundingRate
|
340
|
+
return result
|
341
|
+
return self.filter_by_array(self.fundingRates, 'symbol', symbols)
|
342
|
+
|
343
|
+
def handle_funding_rate(self, client: Client, message):
|
344
|
+
#
|
345
|
+
# "data":[
|
346
|
+
# {
|
347
|
+
# "fundingRate":"0.0001875391284828",
|
348
|
+
# "fundingTime":"1700726400000",
|
349
|
+
# "instId":"BTC-USD-SWAP",
|
350
|
+
# "instType":"SWAP",
|
351
|
+
# "method": "next_period",
|
352
|
+
# "maxFundingRate":"0.00375",
|
353
|
+
# "minFundingRate":"-0.00375",
|
354
|
+
# "nextFundingRate":"0.0002608059239328",
|
355
|
+
# "nextFundingTime":"1700755200000",
|
356
|
+
# "premium": "0.0001233824646391",
|
357
|
+
# "settFundingRate":"0.0001699799259033",
|
358
|
+
# "settState":"settled",
|
359
|
+
# "ts":"1700724675402"
|
360
|
+
# }
|
361
|
+
# ]
|
362
|
+
#
|
363
|
+
data = self.safe_list(message, 'data', [])
|
364
|
+
for i in range(0, len(data)):
|
365
|
+
rawfr = data[i]
|
366
|
+
fundingRate = self.parse_funding_rate(rawfr)
|
367
|
+
symbol = fundingRate['symbol']
|
368
|
+
self.fundingRates[symbol] = fundingRate
|
369
|
+
client.resolve(fundingRate, 'funding-rate' + ':' + fundingRate['symbol'])
|
370
|
+
|
243
371
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
244
372
|
"""
|
245
|
-
|
373
|
+
|
374
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
|
375
|
+
|
246
376
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
247
377
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
248
378
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -252,20 +382,37 @@ class okx(ccxt.async_support.okx):
|
|
252
382
|
channel = None
|
253
383
|
channel, params = self.handle_option_and_params(params, 'watchTicker', 'channel', 'tickers')
|
254
384
|
params['channel'] = channel
|
385
|
+
market = self.market(symbol)
|
386
|
+
symbol = market['symbol']
|
255
387
|
ticker = await self.watch_tickers([symbol], params)
|
256
388
|
return self.safe_value(ticker, symbol)
|
257
389
|
|
390
|
+
async def un_watch_ticker(self, symbol: str, params={}) -> Any:
|
391
|
+
"""
|
392
|
+
|
393
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
|
394
|
+
|
395
|
+
unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
396
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
397
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
398
|
+
:param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
|
399
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
400
|
+
"""
|
401
|
+
return await self.un_watch_tickers([symbol], params)
|
402
|
+
|
258
403
|
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
259
404
|
"""
|
260
|
-
|
405
|
+
|
406
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
|
407
|
+
|
261
408
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
262
409
|
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
263
410
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
264
411
|
:param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
|
265
412
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
266
413
|
"""
|
267
|
-
|
268
|
-
|
414
|
+
await self.load_markets()
|
415
|
+
symbols = self.market_symbols(symbols, None, False)
|
269
416
|
channel = None
|
270
417
|
channel, params = self.handle_option_and_params(params, 'watchTickers', 'channel', 'tickers')
|
271
418
|
newTickers = await self.subscribe_multiple('public', channel, symbols, params)
|
@@ -273,6 +420,78 @@ class okx(ccxt.async_support.okx):
|
|
273
420
|
return newTickers
|
274
421
|
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
275
422
|
|
423
|
+
async def watch_mark_price(self, symbol: str, params={}) -> Ticker:
|
424
|
+
"""
|
425
|
+
|
426
|
+
https://www.okx.com/docs-v5/en/#public-data-websocket-mark-price-channel
|
427
|
+
|
428
|
+
watches a mark price
|
429
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
430
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
431
|
+
:param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
|
432
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
433
|
+
"""
|
434
|
+
channel = None
|
435
|
+
channel, params = self.handle_option_and_params(params, 'watchMarkPrice', 'channel', 'mark-price')
|
436
|
+
params['channel'] = channel
|
437
|
+
market = self.market(symbol)
|
438
|
+
symbol = market['symbol']
|
439
|
+
ticker = await self.watch_mark_prices([symbol], params)
|
440
|
+
return ticker[symbol]
|
441
|
+
|
442
|
+
async def watch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
|
443
|
+
"""
|
444
|
+
|
445
|
+
https://www.okx.com/docs-v5/en/#public-data-websocket-mark-price-channel
|
446
|
+
|
447
|
+
watches mark prices
|
448
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
449
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
450
|
+
:param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
|
451
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
452
|
+
"""
|
453
|
+
await self.load_markets()
|
454
|
+
symbols = self.market_symbols(symbols, None, False)
|
455
|
+
channel = None
|
456
|
+
channel, params = self.handle_option_and_params(params, 'watchMarkPrices', 'channel', 'mark-price')
|
457
|
+
newTickers = await self.subscribe_multiple('public', channel, symbols, params)
|
458
|
+
if self.newUpdates:
|
459
|
+
return newTickers
|
460
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
461
|
+
|
462
|
+
async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
|
463
|
+
"""
|
464
|
+
|
465
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
|
466
|
+
|
467
|
+
unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
468
|
+
:param str[] [symbols]: unified symbol of the market to fetch the ticker for
|
469
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
470
|
+
:param str [params.channel]: the channel to subscribe to, tickers by default. Can be tickers, sprd-tickers, index-tickers, block-tickers
|
471
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
472
|
+
"""
|
473
|
+
await self.load_markets()
|
474
|
+
symbols = self.market_symbols(symbols, None, False)
|
475
|
+
channel = None
|
476
|
+
channel, params = self.handle_option_and_params(params, 'watchTickers', 'channel', 'tickers')
|
477
|
+
topics = []
|
478
|
+
messageHashes = []
|
479
|
+
for i in range(0, len(symbols)):
|
480
|
+
symbol = symbols[i]
|
481
|
+
messageHashes.append('unsubscribe:ticker:' + symbol)
|
482
|
+
marketId = self.market_id(symbol)
|
483
|
+
topic: dict = {
|
484
|
+
'channel': channel,
|
485
|
+
'instId': marketId,
|
486
|
+
}
|
487
|
+
topics.append(topic)
|
488
|
+
request: dict = {
|
489
|
+
'op': 'unsubscribe',
|
490
|
+
'args': topics,
|
491
|
+
}
|
492
|
+
url = self.get_url(channel, 'public')
|
493
|
+
return await self.watch_multiple(url, messageHashes, request, messageHashes)
|
494
|
+
|
276
495
|
def handle_ticker(self, client: Client, message):
|
277
496
|
#
|
278
497
|
# {
|
@@ -299,27 +518,370 @@ class okx(ccxt.async_support.okx):
|
|
299
518
|
# ]
|
300
519
|
# }
|
301
520
|
#
|
521
|
+
self.handle_bid_ask(client, message)
|
302
522
|
arg = self.safe_value(message, 'arg', {})
|
523
|
+
marketId = self.safe_string(arg, 'instId')
|
524
|
+
market = self.safe_market(marketId, None, '-')
|
525
|
+
symbol = market['symbol']
|
303
526
|
channel = self.safe_string(arg, 'channel')
|
304
527
|
data = self.safe_value(message, 'data', [])
|
305
|
-
newTickers =
|
528
|
+
newTickers: dict = {}
|
306
529
|
for i in range(0, len(data)):
|
307
530
|
ticker = self.parse_ticker(data[i])
|
308
|
-
symbol = ticker['symbol']
|
309
531
|
self.tickers[symbol] = ticker
|
310
|
-
newTickers
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
532
|
+
newTickers[symbol] = ticker
|
533
|
+
messageHash = channel + '::' + symbol
|
534
|
+
client.resolve(newTickers, messageHash)
|
535
|
+
|
536
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
537
|
+
"""
|
538
|
+
|
539
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
|
540
|
+
|
541
|
+
watches best bid & ask for symbols
|
542
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
543
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
544
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
545
|
+
"""
|
546
|
+
await self.load_markets()
|
547
|
+
symbols = self.market_symbols(symbols, None, False)
|
548
|
+
channel = None
|
549
|
+
channel, params = self.handle_option_and_params(params, 'watchBidsAsks', 'channel', 'tickers')
|
550
|
+
url = self.get_url(channel, 'public')
|
551
|
+
messageHashes = []
|
552
|
+
args = []
|
553
|
+
for i in range(0, len(symbols)):
|
554
|
+
marketId = self.market_id(symbols[i])
|
555
|
+
arg: dict = {
|
556
|
+
'channel': channel,
|
557
|
+
'instId': marketId,
|
558
|
+
}
|
559
|
+
args.append(self.extend(arg, params))
|
560
|
+
messageHashes.append('bidask::' + symbols[i])
|
561
|
+
request: dict = {
|
562
|
+
'op': 'subscribe',
|
563
|
+
'args': args,
|
564
|
+
}
|
565
|
+
newTickers = await self.watch_multiple(url, messageHashes, request, messageHashes)
|
566
|
+
if self.newUpdates:
|
567
|
+
tickers: dict = {}
|
568
|
+
tickers[newTickers['symbol']] = newTickers
|
569
|
+
return tickers
|
570
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
571
|
+
|
572
|
+
def handle_bid_ask(self, client: Client, message):
|
573
|
+
#
|
574
|
+
# {
|
575
|
+
# "arg": {channel: "tickers", instId: "BTC-USDT"},
|
576
|
+
# "data": [
|
577
|
+
# {
|
578
|
+
# "instType": "SPOT",
|
579
|
+
# "instId": "BTC-USDT",
|
580
|
+
# "last": "31500.1",
|
581
|
+
# "lastSz": "0.00001754",
|
582
|
+
# "askPx": "31500.1",
|
583
|
+
# "askSz": "0.00998144",
|
584
|
+
# "bidPx": "31500",
|
585
|
+
# "bidSz": "3.05652439",
|
586
|
+
# "open24h": "31697",
|
587
|
+
# "high24h": "32248",
|
588
|
+
# "low24h": "31165.6",
|
589
|
+
# "sodUtc0": "31385.5",
|
590
|
+
# "sodUtc8": "32134.9",
|
591
|
+
# "volCcy24h": "503403597.38138519",
|
592
|
+
# "vol24h": "15937.10781721",
|
593
|
+
# "ts": "1626526618762"
|
594
|
+
# }
|
595
|
+
# ]
|
596
|
+
# }
|
597
|
+
#
|
598
|
+
data = self.safe_list(message, 'data', [])
|
599
|
+
ticker = self.safe_dict(data, 0, {})
|
600
|
+
parsedTicker = self.parse_ws_bid_ask(ticker)
|
601
|
+
symbol = parsedTicker['symbol']
|
602
|
+
self.bidsasks[symbol] = parsedTicker
|
603
|
+
messageHash = 'bidask::' + symbol
|
604
|
+
client.resolve(parsedTicker, messageHash)
|
605
|
+
|
606
|
+
def parse_ws_bid_ask(self, ticker, market=None):
|
607
|
+
marketId = self.safe_string(ticker, 'instId')
|
608
|
+
market = self.safe_market(marketId, market)
|
609
|
+
symbol = self.safe_string(market, 'symbol')
|
610
|
+
timestamp = self.safe_integer(ticker, 'ts')
|
611
|
+
return self.safe_ticker({
|
612
|
+
'symbol': symbol,
|
613
|
+
'timestamp': timestamp,
|
614
|
+
'datetime': self.iso8601(timestamp),
|
615
|
+
'ask': self.safe_string(ticker, 'askPx'),
|
616
|
+
'askVolume': self.safe_string(ticker, 'askSz'),
|
617
|
+
'bid': self.safe_string(ticker, 'bidPx'),
|
618
|
+
'bidVolume': self.safe_string(ticker, 'bidSz'),
|
619
|
+
'info': ticker,
|
620
|
+
}, market)
|
621
|
+
|
622
|
+
async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
623
|
+
"""
|
624
|
+
watch the public liquidations of a trading pair
|
625
|
+
|
626
|
+
https://www.okx.com/docs-v5/en/#public-data-websocket-liquidation-orders-channel
|
627
|
+
|
628
|
+
:param str symbols:
|
629
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
630
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
631
|
+
:param dict [params]: exchange specific parameters for the okx api endpoint
|
632
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
633
|
+
"""
|
634
|
+
await self.load_markets()
|
635
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
636
|
+
messageHash = 'liquidations'
|
637
|
+
messageHashes = []
|
638
|
+
if symbols is not None:
|
639
|
+
for i in range(0, len(symbols)):
|
640
|
+
symbol = symbols[i]
|
641
|
+
messageHashes.append(messageHash + '::' + symbol)
|
642
|
+
else:
|
643
|
+
messageHashes.append(messageHash)
|
644
|
+
market = self.get_market_from_symbols(symbols)
|
645
|
+
type = None
|
646
|
+
type, params = self.handle_market_type_and_params('watchliquidationsForSymbols', market, params)
|
647
|
+
channel = 'liquidation-orders'
|
648
|
+
if type == 'spot':
|
649
|
+
type = 'SWAP'
|
650
|
+
elif type == 'future':
|
651
|
+
type = 'futures'
|
652
|
+
uppercaseType = type.upper()
|
653
|
+
request = {
|
654
|
+
'op': 'subscribe',
|
655
|
+
'args': [
|
656
|
+
{
|
657
|
+
'channel': channel,
|
658
|
+
'instType': uppercaseType,
|
659
|
+
},
|
660
|
+
],
|
661
|
+
}
|
662
|
+
url = self.get_url(channel, 'public')
|
663
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, request, messageHashes)
|
664
|
+
if self.newUpdates:
|
665
|
+
return newLiquidations
|
666
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
667
|
+
|
668
|
+
def handle_liquidation(self, client: Client, message):
|
669
|
+
#
|
670
|
+
# {
|
671
|
+
# "arg": {
|
672
|
+
# "channel": "liquidation-orders",
|
673
|
+
# "instType": "SWAP"
|
674
|
+
# },
|
675
|
+
# "data": [
|
676
|
+
# {
|
677
|
+
# "details": [
|
678
|
+
# {
|
679
|
+
# "bkLoss": "0",
|
680
|
+
# "bkPx": "0.007831",
|
681
|
+
# "ccy": "",
|
682
|
+
# "posSide": "short",
|
683
|
+
# "side": "buy",
|
684
|
+
# "sz": "13",
|
685
|
+
# "ts": "1692266434010"
|
686
|
+
# }
|
687
|
+
# ],
|
688
|
+
# "instFamily": "IOST-USDT",
|
689
|
+
# "instId": "IOST-USDT-SWAP",
|
690
|
+
# "instType": "SWAP",
|
691
|
+
# "uly": "IOST-USDT"
|
692
|
+
# }
|
693
|
+
# ]
|
694
|
+
# }
|
695
|
+
#
|
696
|
+
rawLiquidations = self.safe_list(message, 'data', [])
|
697
|
+
for i in range(0, len(rawLiquidations)):
|
698
|
+
rawLiquidation = rawLiquidations[i]
|
699
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation)
|
700
|
+
symbol = self.safe_string(liquidation, 'symbol')
|
701
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
702
|
+
if liquidations is None:
|
703
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
704
|
+
liquidations = ArrayCache(limit)
|
705
|
+
liquidations.append(liquidation)
|
706
|
+
self.liquidations[symbol] = liquidations
|
707
|
+
client.resolve([liquidation], 'liquidations')
|
708
|
+
client.resolve([liquidation], 'liquidations::' + symbol)
|
709
|
+
|
710
|
+
async def watch_my_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
711
|
+
"""
|
712
|
+
watch the private liquidations of a trading pair
|
713
|
+
|
714
|
+
https://www.okx.com/docs-v5/en/#trading-account-websocket-balance-and-position-channel
|
715
|
+
|
716
|
+
:param str[] symbols:
|
717
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
718
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
719
|
+
:param dict [params]: exchange specific parameters for the okx api endpoint
|
720
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
721
|
+
"""
|
722
|
+
await self.load_markets()
|
723
|
+
isTrigger = self.safe_value_2(params, 'stop', 'trigger', False)
|
724
|
+
params = self.omit(params, ['stop', 'trigger'])
|
725
|
+
await self.authenticate({'access': 'business' if isTrigger else 'private'})
|
726
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
727
|
+
messageHash = 'myLiquidations'
|
728
|
+
messageHashes = []
|
729
|
+
if symbols is not None:
|
730
|
+
for i in range(0, len(symbols)):
|
731
|
+
symbol = symbols[i]
|
732
|
+
messageHashes.append(messageHash + '::' + symbol)
|
733
|
+
else:
|
734
|
+
messageHashes.append(messageHash)
|
735
|
+
channel = 'balance_and_position'
|
736
|
+
request: dict = {
|
737
|
+
'op': 'subscribe',
|
738
|
+
'args': [
|
739
|
+
{
|
740
|
+
'channel': channel,
|
741
|
+
},
|
742
|
+
],
|
743
|
+
}
|
744
|
+
url = self.get_url(channel, 'private')
|
745
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), messageHashes)
|
746
|
+
if self.newUpdates:
|
747
|
+
return newLiquidations
|
748
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
749
|
+
|
750
|
+
def handle_my_liquidation(self, client: Client, message):
|
751
|
+
#
|
752
|
+
# {
|
753
|
+
# "arg": {
|
754
|
+
# "channel": "balance_and_position",
|
755
|
+
# "uid": "77982378738415879"
|
756
|
+
# },
|
757
|
+
# "data": [{
|
758
|
+
# "pTime": "1597026383085",
|
759
|
+
# "eventType": "snapshot",
|
760
|
+
# "balData": [{
|
761
|
+
# "ccy": "BTC",
|
762
|
+
# "cashBal": "1",
|
763
|
+
# "uTime": "1597026383085"
|
764
|
+
# }],
|
765
|
+
# "posData": [{
|
766
|
+
# "posId": "1111111111",
|
767
|
+
# "tradeId": "2",
|
768
|
+
# "instId": "BTC-USD-191018",
|
769
|
+
# "instType": "FUTURES",
|
770
|
+
# "mgnMode": "cross",
|
771
|
+
# "posSide": "long",
|
772
|
+
# "pos": "10",
|
773
|
+
# "ccy": "BTC",
|
774
|
+
# "posCcy": "",
|
775
|
+
# "avgPx": "3320",
|
776
|
+
# "uTIme": "1597026383085"
|
777
|
+
# }],
|
778
|
+
# "trades": [{
|
779
|
+
# "instId": "BTC-USD-191018",
|
780
|
+
# "tradeId": "2",
|
781
|
+
# }]
|
782
|
+
# }]
|
783
|
+
# }
|
784
|
+
#
|
785
|
+
rawLiquidations = self.safe_list(message, 'data', [])
|
786
|
+
for i in range(0, len(rawLiquidations)):
|
787
|
+
rawLiquidation = rawLiquidations[i]
|
788
|
+
eventType = self.safe_string(rawLiquidation, 'eventType')
|
789
|
+
if eventType != 'liquidation':
|
790
|
+
return
|
791
|
+
liquidation = self.parse_ws_my_liquidation(rawLiquidation)
|
792
|
+
symbol = self.safe_string(liquidation, 'symbol')
|
793
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
794
|
+
if liquidations is None:
|
795
|
+
limit = self.safe_integer(self.options, 'myLiquidationsLimit', 1000)
|
796
|
+
liquidations = ArrayCache(limit)
|
797
|
+
liquidations.append(liquidation)
|
798
|
+
self.liquidations[symbol] = liquidations
|
799
|
+
client.resolve([liquidation], 'myLiquidations')
|
800
|
+
client.resolve([liquidation], 'myLiquidations::' + symbol)
|
801
|
+
|
802
|
+
def parse_ws_my_liquidation(self, liquidation, market=None):
|
803
|
+
#
|
804
|
+
# {
|
805
|
+
# "pTime": "1597026383085",
|
806
|
+
# "eventType": "snapshot",
|
807
|
+
# "balData": [{
|
808
|
+
# "ccy": "BTC",
|
809
|
+
# "cashBal": "1",
|
810
|
+
# "uTime": "1597026383085"
|
811
|
+
# }],
|
812
|
+
# "posData": [{
|
813
|
+
# "posId": "1111111111",
|
814
|
+
# "tradeId": "2",
|
815
|
+
# "instId": "BTC-USD-191018",
|
816
|
+
# "instType": "FUTURES",
|
817
|
+
# "mgnMode": "cross",
|
818
|
+
# "posSide": "long",
|
819
|
+
# "pos": "10",
|
820
|
+
# "ccy": "BTC",
|
821
|
+
# "posCcy": "",
|
822
|
+
# "avgPx": "3320",
|
823
|
+
# "uTIme": "1597026383085"
|
824
|
+
# }],
|
825
|
+
# "trades": [{
|
826
|
+
# "instId": "BTC-USD-191018",
|
827
|
+
# "tradeId": "2",
|
828
|
+
# }]
|
829
|
+
# }
|
830
|
+
#
|
831
|
+
posData = self.safe_list(liquidation, 'posData', [])
|
832
|
+
firstPosData = self.safe_dict(posData, 0, {})
|
833
|
+
marketId = self.safe_string(firstPosData, 'instId')
|
834
|
+
market = self.safe_market(marketId, market)
|
835
|
+
timestamp = self.safe_integer(firstPosData, 'uTIme')
|
836
|
+
return self.safe_liquidation({
|
837
|
+
'info': liquidation,
|
838
|
+
'symbol': self.safe_symbol(marketId, market),
|
839
|
+
'contracts': self.safe_number(firstPosData, 'pos'),
|
840
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
841
|
+
'price': self.safe_number(liquidation, 'avgPx'),
|
842
|
+
'baseValue': None,
|
843
|
+
'quoteValue': None,
|
844
|
+
'timestamp': timestamp,
|
845
|
+
'datetime': self.iso8601(timestamp),
|
846
|
+
})
|
847
|
+
|
848
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
849
|
+
#
|
850
|
+
# public liquidation
|
851
|
+
# {
|
852
|
+
# "details": [
|
853
|
+
# {
|
854
|
+
# "bkLoss": "0",
|
855
|
+
# "bkPx": "0.007831",
|
856
|
+
# "ccy": "",
|
857
|
+
# "posSide": "short",
|
858
|
+
# "side": "buy",
|
859
|
+
# "sz": "13",
|
860
|
+
# "ts": "1692266434010"
|
861
|
+
# }
|
862
|
+
# ],
|
863
|
+
# "instFamily": "IOST-USDT",
|
864
|
+
# "instId": "IOST-USDT-SWAP",
|
865
|
+
# "instType": "SWAP",
|
866
|
+
# "uly": "IOST-USDT"
|
867
|
+
# }
|
868
|
+
#
|
869
|
+
details = self.safe_list(liquidation, 'details', [])
|
870
|
+
liquidationDetails = self.safe_dict(details, 0, {})
|
871
|
+
marketId = self.safe_string(liquidation, 'instId')
|
872
|
+
market = self.safe_market(marketId, market)
|
873
|
+
timestamp = self.safe_integer(liquidationDetails, 'ts')
|
874
|
+
return self.safe_liquidation({
|
875
|
+
'info': liquidation,
|
876
|
+
'symbol': self.safe_symbol(marketId, market),
|
877
|
+
'contracts': self.safe_number(liquidationDetails, 'sz'),
|
878
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
879
|
+
'price': self.safe_number(liquidationDetails, 'bkPx'),
|
880
|
+
'baseValue': None,
|
881
|
+
'quoteValue': None,
|
882
|
+
'timestamp': timestamp,
|
883
|
+
'datetime': self.iso8601(timestamp),
|
884
|
+
})
|
323
885
|
|
324
886
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
325
887
|
"""
|
@@ -340,6 +902,17 @@ class okx(ccxt.async_support.okx):
|
|
340
902
|
limit = ohlcv.getLimit(symbol, limit)
|
341
903
|
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
|
342
904
|
|
905
|
+
async def un_watch_ohlcv(self, symbol: str, timeframe='1m', params={}) -> Any:
|
906
|
+
"""
|
907
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
908
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
909
|
+
:param str timeframe: the length of time each candle represents
|
910
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
911
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
912
|
+
"""
|
913
|
+
await self.load_markets()
|
914
|
+
return await self.un_watch_ohlcv_for_symbols([[symbol, timeframe]], params)
|
915
|
+
|
343
916
|
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
|
344
917
|
"""
|
345
918
|
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
@@ -362,13 +935,13 @@ class okx(ccxt.async_support.okx):
|
|
362
935
|
marketId = self.market_id(sym)
|
363
936
|
interval = self.safe_string(self.timeframes, tf, tf)
|
364
937
|
channel = 'candle' + interval
|
365
|
-
topic = {
|
938
|
+
topic: dict = {
|
366
939
|
'channel': channel,
|
367
940
|
'instId': marketId,
|
368
941
|
}
|
369
942
|
topics.append(topic)
|
370
943
|
messageHashes.append('multi:' + channel + ':' + sym)
|
371
|
-
request = {
|
944
|
+
request: dict = {
|
372
945
|
'op': 'subscribe',
|
373
946
|
'args': topics,
|
374
947
|
}
|
@@ -379,6 +952,39 @@ class okx(ccxt.async_support.okx):
|
|
379
952
|
filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
|
380
953
|
return self.create_ohlcv_object(symbol, timeframe, filtered)
|
381
954
|
|
955
|
+
async def un_watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], params={}) -> Any:
|
956
|
+
"""
|
957
|
+
unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
958
|
+
:param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
959
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
960
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
961
|
+
"""
|
962
|
+
symbolsLength = len(symbolsAndTimeframes)
|
963
|
+
if symbolsLength == 0 or not isinstance(symbolsAndTimeframes[0], list):
|
964
|
+
raise ArgumentsRequired(self.id + " watchOHLCVForSymbols() requires a an array of symbols and timeframes, like [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]")
|
965
|
+
await self.load_markets()
|
966
|
+
topics = []
|
967
|
+
messageHashes = []
|
968
|
+
for i in range(0, len(symbolsAndTimeframes)):
|
969
|
+
symbolAndTimeframe = symbolsAndTimeframes[i]
|
970
|
+
sym = symbolAndTimeframe[0]
|
971
|
+
tf = symbolAndTimeframe[1]
|
972
|
+
marketId = self.market_id(sym)
|
973
|
+
interval = self.safe_string(self.timeframes, tf, tf)
|
974
|
+
channel = 'candle' + interval
|
975
|
+
topic: dict = {
|
976
|
+
'channel': channel,
|
977
|
+
'instId': marketId,
|
978
|
+
}
|
979
|
+
topics.append(topic)
|
980
|
+
messageHashes.append('unsubscribe:multi:' + channel + ':' + sym)
|
981
|
+
request: dict = {
|
982
|
+
'op': 'unsubscribe',
|
983
|
+
'args': topics,
|
984
|
+
}
|
985
|
+
url = self.get_url('candle', 'public')
|
986
|
+
return await self.watch_multiple(url, messageHashes, request, messageHashes)
|
987
|
+
|
382
988
|
def handle_ohlcv(self, client: Client, message):
|
383
989
|
#
|
384
990
|
# {
|
@@ -424,10 +1030,14 @@ class okx(ccxt.async_support.okx):
|
|
424
1030
|
|
425
1031
|
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
426
1032
|
"""
|
1033
|
+
|
1034
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
|
1035
|
+
|
427
1036
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
428
1037
|
:param str symbol: unified symbol of the market to fetch the order book for
|
429
1038
|
:param int [limit]: the maximum amount of order book entries to return
|
430
1039
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1040
|
+
:param str [params.depth]: okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
|
431
1041
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
432
1042
|
"""
|
433
1043
|
#
|
@@ -457,17 +1067,32 @@ class okx(ccxt.async_support.okx):
|
|
457
1067
|
|
458
1068
|
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
459
1069
|
"""
|
1070
|
+
|
1071
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
|
1072
|
+
|
460
1073
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
461
1074
|
:param str[] symbols: unified array of symbols
|
462
|
-
:param int [limit]: the maximum amount of order book entries to return
|
1075
|
+
:param int [limit]: 1,5, 400, 50(l2-tbt, vip4+) or 40000(vip5+) the maximum amount of order book entries to return
|
463
1076
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1077
|
+
:param str [params.depth]: okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
|
464
1078
|
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
465
1079
|
"""
|
466
1080
|
await self.load_markets()
|
467
1081
|
symbols = self.market_symbols(symbols)
|
468
|
-
|
469
|
-
depth = self.
|
1082
|
+
depth = None
|
1083
|
+
depth, params = self.handle_option_and_params(params, 'watchOrderBook', 'depth', 'books')
|
1084
|
+
if limit is not None:
|
1085
|
+
if limit == 1:
|
1086
|
+
depth = 'bbo-tbt'
|
1087
|
+
elif limit > 1 and limit <= 5:
|
1088
|
+
depth = 'books5'
|
1089
|
+
elif limit == 50:
|
1090
|
+
depth = 'books50-l2-tbt' # Make sure you have VIP4 and above
|
1091
|
+
elif limit == 400:
|
1092
|
+
depth = 'books'
|
470
1093
|
if (depth == 'books-l2-tbt') or (depth == 'books50-l2-tbt'):
|
1094
|
+
if not self.check_required_credentials(False):
|
1095
|
+
raise AuthenticationError(self.id + ' watchOrderBook/watchOrderBookForSymbols requires authentication for self depth. Add credentials or change the depth option to books or books5')
|
471
1096
|
await self.authenticate({'access': 'public'})
|
472
1097
|
topics = []
|
473
1098
|
messageHashes = []
|
@@ -475,12 +1100,12 @@ class okx(ccxt.async_support.okx):
|
|
475
1100
|
symbol = symbols[i]
|
476
1101
|
messageHashes.append(depth + ':' + symbol)
|
477
1102
|
marketId = self.market_id(symbol)
|
478
|
-
topic = {
|
1103
|
+
topic: dict = {
|
479
1104
|
'channel': depth,
|
480
1105
|
'instId': marketId,
|
481
1106
|
}
|
482
1107
|
topics.append(topic)
|
483
|
-
request = {
|
1108
|
+
request: dict = {
|
484
1109
|
'op': 'subscribe',
|
485
1110
|
'args': topics,
|
486
1111
|
}
|
@@ -488,6 +1113,66 @@ class okx(ccxt.async_support.okx):
|
|
488
1113
|
orderbook = await self.watch_multiple(url, messageHashes, request, messageHashes)
|
489
1114
|
return orderbook.limit()
|
490
1115
|
|
1116
|
+
async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}) -> Any:
|
1117
|
+
"""
|
1118
|
+
|
1119
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
|
1120
|
+
|
1121
|
+
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
1122
|
+
:param str[] symbols: unified array of symbols
|
1123
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1124
|
+
:param int [params.limit]: the maximum amount of order book entries to return
|
1125
|
+
:param str [params.depth]: okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
|
1126
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
1127
|
+
"""
|
1128
|
+
await self.load_markets()
|
1129
|
+
symbols = self.market_symbols(symbols, None, False)
|
1130
|
+
depth = None
|
1131
|
+
depth, params = self.handle_option_and_params(params, 'watchOrderBook', 'depth', 'books')
|
1132
|
+
limit = self.safe_integer(params, 'limit')
|
1133
|
+
if limit is not None:
|
1134
|
+
if limit == 1:
|
1135
|
+
depth = 'bbo-tbt'
|
1136
|
+
elif limit > 1 and limit <= 5:
|
1137
|
+
depth = 'books5'
|
1138
|
+
elif limit == 50:
|
1139
|
+
depth = 'books50-l2-tbt' # Make sure you have VIP4 and above
|
1140
|
+
elif limit == 400:
|
1141
|
+
depth = 'books'
|
1142
|
+
topics = []
|
1143
|
+
subMessageHashes = []
|
1144
|
+
messageHashes = []
|
1145
|
+
for i in range(0, len(symbols)):
|
1146
|
+
symbol = symbols[i]
|
1147
|
+
subMessageHashes.append(depth + ':' + symbol)
|
1148
|
+
messageHashes.append('unsubscribe:orderbook:' + symbol)
|
1149
|
+
marketId = self.market_id(symbol)
|
1150
|
+
topic: dict = {
|
1151
|
+
'channel': depth,
|
1152
|
+
'instId': marketId,
|
1153
|
+
}
|
1154
|
+
topics.append(topic)
|
1155
|
+
request: dict = {
|
1156
|
+
'op': 'unsubscribe',
|
1157
|
+
'args': topics,
|
1158
|
+
}
|
1159
|
+
url = self.get_url(depth, 'public')
|
1160
|
+
return await self.watch_multiple(url, messageHashes, request, messageHashes)
|
1161
|
+
|
1162
|
+
async def un_watch_order_book(self, symbol: str, params={}) -> Any:
|
1163
|
+
"""
|
1164
|
+
|
1165
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
|
1166
|
+
|
1167
|
+
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
1168
|
+
:param str symbol: unified array of symbols
|
1169
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1170
|
+
:param int [params.limit]: the maximum amount of order book entries to return
|
1171
|
+
:param str [params.depth]: okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
|
1172
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
1173
|
+
"""
|
1174
|
+
return await self.un_watch_order_book_for_symbols([symbol], params)
|
1175
|
+
|
491
1176
|
def handle_delta(self, bookside, delta):
|
492
1177
|
#
|
493
1178
|
# [
|
@@ -505,7 +1190,7 @@ class okx(ccxt.async_support.okx):
|
|
505
1190
|
for i in range(0, len(deltas)):
|
506
1191
|
self.handle_delta(bookside, deltas[i])
|
507
1192
|
|
508
|
-
def handle_order_book_message(self, client: Client, message, orderbook, messageHash):
|
1193
|
+
def handle_order_book_message(self, client: Client, message, orderbook, messageHash, market=None):
|
509
1194
|
#
|
510
1195
|
# {
|
511
1196
|
# "asks": [
|
@@ -520,6 +1205,9 @@ class okx(ccxt.async_support.okx):
|
|
520
1205
|
# ],
|
521
1206
|
# "instId": "BTC-USDT",
|
522
1207
|
# "ts": "1626537446491"
|
1208
|
+
# "checksum": -855196043,
|
1209
|
+
# "prevSeqId": 123456,
|
1210
|
+
# "seqId": 123457
|
523
1211
|
# }
|
524
1212
|
#
|
525
1213
|
asks = self.safe_value(message, 'asks', [])
|
@@ -528,8 +1216,13 @@ class okx(ccxt.async_support.okx):
|
|
528
1216
|
storedBids = orderbook['bids']
|
529
1217
|
self.handle_deltas(storedAsks, asks)
|
530
1218
|
self.handle_deltas(storedBids, bids)
|
531
|
-
|
1219
|
+
marketId = self.safe_string(message, 'instId')
|
1220
|
+
symbol = self.safe_symbol(marketId, market)
|
1221
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
1222
|
+
seqId = self.safe_integer(message, 'seqId')
|
532
1223
|
if checksum:
|
1224
|
+
prevSeqId = self.safe_integer(message, 'prevSeqId')
|
1225
|
+
nonce = orderbook['nonce']
|
533
1226
|
asksLength = len(storedAsks)
|
534
1227
|
bidsLength = len(storedBids)
|
535
1228
|
payloadArray = []
|
@@ -543,10 +1236,17 @@ class okx(ccxt.async_support.okx):
|
|
543
1236
|
payload = ':'.join(payloadArray)
|
544
1237
|
responseChecksum = self.safe_integer(message, 'checksum')
|
545
1238
|
localChecksum = self.crc32(payload, True)
|
1239
|
+
error = None
|
1240
|
+
if prevSeqId != -1 and nonce != prevSeqId:
|
1241
|
+
error = InvalidNonce(self.id + ' watchOrderBook received invalid nonce')
|
546
1242
|
if responseChecksum != localChecksum:
|
547
|
-
error =
|
1243
|
+
error = ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
1244
|
+
if error is not None:
|
1245
|
+
del client.subscriptions[messageHash]
|
1246
|
+
del self.orderbooks[symbol]
|
548
1247
|
client.reject(error, messageHash)
|
549
1248
|
timestamp = self.safe_integer(message, 'ts')
|
1249
|
+
orderbook['nonce'] = seqId
|
550
1250
|
orderbook['timestamp'] = timestamp
|
551
1251
|
orderbook['datetime'] = self.iso8601(timestamp)
|
552
1252
|
return orderbook
|
@@ -637,14 +1337,14 @@ class okx(ccxt.async_support.okx):
|
|
637
1337
|
# ]
|
638
1338
|
# }
|
639
1339
|
#
|
640
|
-
arg = self.
|
1340
|
+
arg = self.safe_dict(message, 'arg', {})
|
641
1341
|
channel = self.safe_string(arg, 'channel')
|
642
1342
|
action = self.safe_string(message, 'action')
|
643
|
-
data = self.
|
1343
|
+
data = self.safe_list(message, 'data', [])
|
644
1344
|
marketId = self.safe_string(arg, 'instId')
|
645
1345
|
market = self.safe_market(marketId)
|
646
1346
|
symbol = market['symbol']
|
647
|
-
depths = {
|
1347
|
+
depths: dict = {
|
648
1348
|
'bbo-tbt': 1,
|
649
1349
|
'books': 400,
|
650
1350
|
'books5': 5,
|
@@ -666,13 +1366,12 @@ class okx(ccxt.async_support.okx):
|
|
666
1366
|
orderbook = self.orderbooks[symbol]
|
667
1367
|
for i in range(0, len(data)):
|
668
1368
|
update = data[i]
|
669
|
-
self.handle_order_book_message(client, update, orderbook, messageHash)
|
1369
|
+
self.handle_order_book_message(client, update, orderbook, messageHash, market)
|
670
1370
|
client.resolve(orderbook, messageHash)
|
671
1371
|
elif (channel == 'books5') or (channel == 'bbo-tbt'):
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
self.orderbooks[symbol] = orderbook
|
1372
|
+
if not (symbol in self.orderbooks):
|
1373
|
+
self.orderbooks[symbol] = self.order_book({}, limit)
|
1374
|
+
orderbook = self.orderbooks[symbol]
|
676
1375
|
for i in range(0, len(data)):
|
677
1376
|
update = data[i]
|
678
1377
|
timestamp = self.safe_integer(update, 'ts')
|
@@ -697,7 +1396,7 @@ class okx(ccxt.async_support.okx):
|
|
697
1396
|
auth = timestamp + method + path
|
698
1397
|
signature = self.hmac(self.encode(auth), self.encode(self.secret), hashlib.sha256, 'base64')
|
699
1398
|
operation = 'login'
|
700
|
-
request = {
|
1399
|
+
request: dict = {
|
701
1400
|
'op': operation,
|
702
1401
|
'args': [
|
703
1402
|
{
|
@@ -708,8 +1407,10 @@ class okx(ccxt.async_support.okx):
|
|
708
1407
|
},
|
709
1408
|
],
|
710
1409
|
}
|
711
|
-
|
712
|
-
|
1410
|
+
# Only add params['access'] to prevent sending custom parameters, such.
|
1411
|
+
if 'access' in params:
|
1412
|
+
request['access'] = params['access']
|
1413
|
+
self.watch(url, messageHash, request, messageHash)
|
713
1414
|
return await future
|
714
1415
|
|
715
1416
|
async def watch_balance(self, params={}) -> Balances:
|
@@ -722,6 +1423,9 @@ class okx(ccxt.async_support.okx):
|
|
722
1423
|
await self.authenticate()
|
723
1424
|
return await self.subscribe('private', 'account', 'account', None, params)
|
724
1425
|
|
1426
|
+
def handle_balance_and_position(self, client: Client, message):
|
1427
|
+
self.handle_my_liquidation(client, message)
|
1428
|
+
|
725
1429
|
def handle_balance(self, client: Client, message):
|
726
1430
|
#
|
727
1431
|
# {
|
@@ -802,24 +1506,26 @@ class okx(ccxt.async_support.okx):
|
|
802
1506
|
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
803
1507
|
"""
|
804
1508
|
watches information on multiple trades made by the user
|
805
|
-
|
1509
|
+
|
1510
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-order-channel
|
1511
|
+
|
806
1512
|
:param str [symbol]: unified market symbol of the market trades were made in
|
807
1513
|
:param int [since]: the earliest time in ms to fetch trades for
|
808
1514
|
:param int [limit]: the maximum number of trade structures to retrieve
|
809
1515
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
810
|
-
:param bool [params.
|
1516
|
+
:param bool [params.trigger]: True if fetching trigger or conditional trades
|
811
1517
|
:param str [params.type]: 'spot', 'swap', 'future', 'option', 'ANY', 'SPOT', 'MARGIN', 'SWAP', 'FUTURES' or 'OPTION'
|
812
1518
|
:param str [params.marginMode]: 'cross' or 'isolated', for automatically setting the type to spot margin
|
813
|
-
:returns dict[]: a list of
|
1519
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
814
1520
|
"""
|
815
1521
|
# By default, receive order updates from any instrument type
|
816
1522
|
type = None
|
817
1523
|
type, params = self.handle_option_and_params(params, 'watchMyTrades', 'type', 'ANY')
|
818
|
-
|
819
|
-
params = self.omit(params, ['stop'])
|
1524
|
+
isTrigger = self.safe_bool_2(params, 'trigger', 'stop', False)
|
1525
|
+
params = self.omit(params, ['trigger', 'stop'])
|
820
1526
|
await self.load_markets()
|
821
|
-
await self.authenticate({'access': 'business' if
|
822
|
-
channel = 'orders-algo' if
|
1527
|
+
await self.authenticate({'access': 'business' if isTrigger else 'private'})
|
1528
|
+
channel = 'orders-algo' if isTrigger else 'orders'
|
823
1529
|
messageHash = channel + '::myTrades'
|
824
1530
|
market = None
|
825
1531
|
if symbol is not None:
|
@@ -835,7 +1541,7 @@ class okx(ccxt.async_support.okx):
|
|
835
1541
|
if uppercaseType == 'SPOT':
|
836
1542
|
if marginMode is not None:
|
837
1543
|
uppercaseType = 'MARGIN'
|
838
|
-
request = {
|
1544
|
+
request: dict = {
|
839
1545
|
'instType': uppercaseType,
|
840
1546
|
}
|
841
1547
|
orders = await self.subscribe('private', messageHash, channel, None, self.extend(request, params))
|
@@ -845,27 +1551,31 @@ class okx(ccxt.async_support.okx):
|
|
845
1551
|
|
846
1552
|
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
847
1553
|
"""
|
848
|
-
|
1554
|
+
|
1555
|
+
https://www.okx.com/docs-v5/en/#trading-account-websocket-positions-channel
|
1556
|
+
|
849
1557
|
watch all open positions
|
850
1558
|
:param str[]|None symbols: list of unified market symbols
|
1559
|
+
@param since
|
1560
|
+
@param limit
|
851
1561
|
:param dict params: extra parameters specific to the exchange API endpoint
|
852
1562
|
:returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
|
853
1563
|
"""
|
854
1564
|
await self.load_markets()
|
855
1565
|
await self.authenticate(params)
|
856
1566
|
symbols = self.market_symbols(symbols)
|
857
|
-
request = {
|
1567
|
+
request: dict = {
|
858
1568
|
'instType': 'ANY',
|
859
1569
|
}
|
860
1570
|
channel = 'positions'
|
861
1571
|
newPositions = None
|
862
1572
|
if symbols is None:
|
863
|
-
arg = {
|
1573
|
+
arg: dict = {
|
864
1574
|
'channel': 'positions',
|
865
1575
|
'instType': 'ANY',
|
866
1576
|
}
|
867
|
-
args = [arg]
|
868
|
-
nonSymbolRequest = {
|
1577
|
+
args = [self.extend(arg, params)]
|
1578
|
+
nonSymbolRequest: dict = {
|
869
1579
|
'op': 'subscribe',
|
870
1580
|
'args': args,
|
871
1581
|
}
|
@@ -945,6 +1655,9 @@ class okx(ccxt.async_support.okx):
|
|
945
1655
|
# }
|
946
1656
|
#
|
947
1657
|
arg = self.safe_value(message, 'arg', {})
|
1658
|
+
marketId = self.safe_string(arg, 'instId')
|
1659
|
+
market = self.safe_market(marketId, None, '-')
|
1660
|
+
symbol = market['symbol']
|
948
1661
|
channel = self.safe_string(arg, 'channel', '')
|
949
1662
|
data = self.safe_value(message, 'data', [])
|
950
1663
|
if self.positions is None:
|
@@ -954,28 +1667,30 @@ class okx(ccxt.async_support.okx):
|
|
954
1667
|
for i in range(0, len(data)):
|
955
1668
|
rawPosition = data[i]
|
956
1669
|
position = self.parse_position(rawPosition)
|
1670
|
+
if position['contracts'] == 0:
|
1671
|
+
position['side'] = 'long'
|
1672
|
+
shortPosition = self.clone(position)
|
1673
|
+
shortPosition['side'] = 'short'
|
1674
|
+
cache.append(shortPosition)
|
1675
|
+
newPositions.append(shortPosition)
|
957
1676
|
newPositions.append(position)
|
958
1677
|
cache.append(position)
|
959
|
-
|
960
|
-
|
961
|
-
messageHash =
|
962
|
-
|
963
|
-
symbolsString = parts[1]
|
964
|
-
symbols = symbolsString.split(',')
|
965
|
-
positions = self.filter_by_array(newPositions, 'symbol', symbols, False)
|
966
|
-
if not self.is_empty(positions):
|
967
|
-
client.resolve(positions, messageHash)
|
968
|
-
client.resolve(newPositions, channel)
|
1678
|
+
messageHash = channel
|
1679
|
+
if symbol is not None:
|
1680
|
+
messageHash = channel + '::' + symbol
|
1681
|
+
client.resolve(newPositions, messageHash)
|
969
1682
|
|
970
1683
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
971
1684
|
"""
|
972
1685
|
watches information on multiple orders made by the user
|
973
|
-
|
1686
|
+
|
1687
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-order-channel
|
1688
|
+
|
974
1689
|
:param str [symbol]: unified market symbol of the market the orders were made in
|
975
1690
|
:param int [since]: the earliest time in ms to fetch orders for
|
976
1691
|
:param int [limit]: the maximum number of order structures to retrieve
|
977
1692
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
978
|
-
:param bool [params.
|
1693
|
+
:param bool [params.trigger]: True if fetching trigger or conditional orders
|
979
1694
|
:param str [params.type]: 'spot', 'swap', 'future', 'option', 'ANY', 'SPOT', 'MARGIN', 'SWAP', 'FUTURES' or 'OPTION'
|
980
1695
|
:param str [params.marginMode]: 'cross' or 'isolated', for automatically setting the type to spot margin
|
981
1696
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
@@ -983,10 +1698,10 @@ class okx(ccxt.async_support.okx):
|
|
983
1698
|
type = None
|
984
1699
|
# By default, receive order updates from any instrument type
|
985
1700
|
type, params = self.handle_option_and_params(params, 'watchOrders', 'type', 'ANY')
|
986
|
-
|
1701
|
+
isTrigger = self.safe_value_2(params, 'stop', 'trigger', False)
|
987
1702
|
params = self.omit(params, ['stop', 'trigger'])
|
988
1703
|
await self.load_markets()
|
989
|
-
await self.authenticate({'access': 'business' if
|
1704
|
+
await self.authenticate({'access': 'business' if isTrigger else 'private'})
|
990
1705
|
market = None
|
991
1706
|
if symbol is not None:
|
992
1707
|
market = self.market(symbol)
|
@@ -1000,10 +1715,10 @@ class okx(ccxt.async_support.okx):
|
|
1000
1715
|
if uppercaseType == 'SPOT':
|
1001
1716
|
if marginMode is not None:
|
1002
1717
|
uppercaseType = 'MARGIN'
|
1003
|
-
request = {
|
1718
|
+
request: dict = {
|
1004
1719
|
'instType': uppercaseType,
|
1005
1720
|
}
|
1006
|
-
channel = 'orders-algo' if
|
1721
|
+
channel = 'orders-algo' if isTrigger else 'orders'
|
1007
1722
|
orders = await self.subscribe('private', channel, channel, symbol, self.extend(request, params))
|
1008
1723
|
if self.newUpdates:
|
1009
1724
|
limit = orders.getLimit(symbol, limit)
|
@@ -1161,7 +1876,7 @@ class okx(ccxt.async_support.okx):
|
|
1161
1876
|
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
|
1162
1877
|
self.myTrades = ArrayCacheBySymbolById(limit)
|
1163
1878
|
myTrades = self.myTrades
|
1164
|
-
symbols = {}
|
1879
|
+
symbols: dict = {}
|
1165
1880
|
for i in range(0, len(filteredOrders)):
|
1166
1881
|
rawTrade = filteredOrders[i]
|
1167
1882
|
trade = self.order_to_trade(rawTrade)
|
@@ -1173,17 +1888,25 @@ class okx(ccxt.async_support.okx):
|
|
1173
1888
|
tradeSymbols = list(symbols.keys())
|
1174
1889
|
for i in range(0, len(tradeSymbols)):
|
1175
1890
|
symbolMessageHash = messageHash + '::' + tradeSymbols[i]
|
1176
|
-
client.resolve(self.
|
1891
|
+
client.resolve(self.myTrades, symbolMessageHash)
|
1892
|
+
|
1893
|
+
def request_id(self):
|
1894
|
+
ts = str(self.milliseconds())
|
1895
|
+
randomNumber = self.rand_number(4)
|
1896
|
+
randomPart = str(randomNumber)
|
1897
|
+
return ts + randomPart
|
1177
1898
|
|
1178
1899
|
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
1179
1900
|
"""
|
1180
|
-
|
1901
|
+
|
1902
|
+
https://www.okx.com/docs-v5/en/#websocket-api-trade-place-order
|
1903
|
+
|
1181
1904
|
create a trade order
|
1182
1905
|
:param str symbol: unified symbol of the market to create an order in
|
1183
1906
|
:param str type: 'market' or 'limit'
|
1184
1907
|
:param str side: 'buy' or 'sell'
|
1185
1908
|
:param float amount: how much of currency you want to trade in units of base currency
|
1186
|
-
:param float|None [price]: the price at which the order is to be
|
1909
|
+
:param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1187
1910
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1188
1911
|
:param boolean params['test']: test order, default False
|
1189
1912
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
@@ -1191,7 +1914,7 @@ class okx(ccxt.async_support.okx):
|
|
1191
1914
|
await self.load_markets()
|
1192
1915
|
await self.authenticate()
|
1193
1916
|
url = self.get_url('private', 'private')
|
1194
|
-
messageHash =
|
1917
|
+
messageHash = self.request_id()
|
1195
1918
|
op = None
|
1196
1919
|
op, params = self.handle_option_and_params(params, 'createOrderWs', 'op', 'batch-orders')
|
1197
1920
|
args = self.create_order_request(symbol, type, side, amount, price, params)
|
@@ -1200,7 +1923,7 @@ class okx(ccxt.async_support.okx):
|
|
1200
1923
|
raise BadRequest(self.id + ' createOrderWs() does not support algo trading. self.options["createOrderWs"]["op"] must be either order or batch-order')
|
1201
1924
|
if (op != 'order') and (op != 'batch-orders'):
|
1202
1925
|
raise BadRequest(self.id + ' createOrderWs() does not support algo trading. self.options["createOrderWs"]["op"] must be either order or privatePostTradeOrder or privatePostTradeOrderAlgo')
|
1203
|
-
request = {
|
1926
|
+
request: dict = {
|
1204
1927
|
'id': messageHash,
|
1205
1928
|
'op': op,
|
1206
1929
|
'args': [args],
|
@@ -1234,32 +1957,35 @@ class okx(ccxt.async_support.okx):
|
|
1234
1957
|
if self.is_empty(args):
|
1235
1958
|
method = self.safe_string(message, 'op')
|
1236
1959
|
stringMsg = self.json(message)
|
1237
|
-
self.handle_errors(None, None, client.url, method, None, stringMsg,
|
1960
|
+
self.handle_errors(None, None, client.url, method, None, stringMsg, message, None, None)
|
1238
1961
|
orders = self.parse_orders(args, None, None, None)
|
1239
|
-
|
1962
|
+
first = self.safe_dict(orders, 0, {})
|
1963
|
+
client.resolve(first, messageHash)
|
1240
1964
|
|
1241
|
-
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount:
|
1965
|
+
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
|
1242
1966
|
"""
|
1243
1967
|
edit a trade order
|
1244
|
-
|
1245
|
-
|
1968
|
+
|
1969
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-amend-order
|
1970
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-amend-multiple-orders
|
1971
|
+
|
1246
1972
|
:param str id: order id
|
1247
1973
|
:param str symbol: unified symbol of the market to create an order in
|
1248
1974
|
:param str type: 'market' or 'limit'
|
1249
1975
|
:param str side: 'buy' or 'sell'
|
1250
1976
|
:param float amount: how much of the currency you want to trade in units of the base currency
|
1251
|
-
:param float|None [price]: the price at which the order is to be
|
1977
|
+
:param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1252
1978
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1253
1979
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1254
1980
|
"""
|
1255
1981
|
await self.load_markets()
|
1256
1982
|
await self.authenticate()
|
1257
1983
|
url = self.get_url('private', 'private')
|
1258
|
-
messageHash =
|
1984
|
+
messageHash = self.request_id()
|
1259
1985
|
op = None
|
1260
1986
|
op, params = self.handle_option_and_params(params, 'editOrderWs', 'op', 'amend-order')
|
1261
1987
|
args = self.edit_order_request(id, symbol, type, side, amount, price, params)
|
1262
|
-
request = {
|
1988
|
+
request: dict = {
|
1263
1989
|
'id': messageHash,
|
1264
1990
|
'op': op,
|
1265
1991
|
'args': [args],
|
@@ -1268,7 +1994,9 @@ class okx(ccxt.async_support.okx):
|
|
1268
1994
|
|
1269
1995
|
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
1270
1996
|
"""
|
1271
|
-
|
1997
|
+
|
1998
|
+
https://okx-docs.github.io/apidocs/websocket_api/en/#cancel-order-trade
|
1999
|
+
|
1272
2000
|
cancel multiple orders
|
1273
2001
|
:param str id: order id
|
1274
2002
|
:param str symbol: unified market symbol, default is None
|
@@ -1281,17 +2009,17 @@ class okx(ccxt.async_support.okx):
|
|
1281
2009
|
await self.load_markets()
|
1282
2010
|
await self.authenticate()
|
1283
2011
|
url = self.get_url('private', 'private')
|
1284
|
-
messageHash =
|
2012
|
+
messageHash = self.request_id()
|
1285
2013
|
clientOrderId = self.safe_string_2(params, 'clOrdId', 'clientOrderId')
|
1286
2014
|
params = self.omit(params, ['clientOrderId', 'clOrdId'])
|
1287
|
-
arg = {
|
2015
|
+
arg: dict = {
|
1288
2016
|
'instId': self.market_id(symbol),
|
1289
2017
|
}
|
1290
2018
|
if clientOrderId is not None:
|
1291
2019
|
arg['clOrdId'] = clientOrderId
|
1292
2020
|
else:
|
1293
2021
|
arg['ordId'] = id
|
1294
|
-
request = {
|
2022
|
+
request: dict = {
|
1295
2023
|
'id': messageHash,
|
1296
2024
|
'op': 'cancel-order',
|
1297
2025
|
'args': [self.extend(arg, params)],
|
@@ -1300,14 +2028,16 @@ class okx(ccxt.async_support.okx):
|
|
1300
2028
|
|
1301
2029
|
async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
|
1302
2030
|
"""
|
1303
|
-
|
2031
|
+
|
2032
|
+
https://www.okx.com/docs-v5/en/#order-book-trading-trade-ws-mass-cancel-order
|
2033
|
+
|
1304
2034
|
cancel multiple orders
|
1305
2035
|
:param str[] ids: order ids
|
1306
2036
|
:param str symbol: unified market symbol, default is None
|
1307
2037
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1308
2038
|
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1309
2039
|
"""
|
1310
|
-
idsLength = len(ids)
|
2040
|
+
idsLength: number = len(ids)
|
1311
2041
|
if idsLength > 20:
|
1312
2042
|
raise BadRequest(self.id + ' cancelOrdersWs() accepts up to 20 ids at a time')
|
1313
2043
|
if symbol is None:
|
@@ -1315,15 +2045,15 @@ class okx(ccxt.async_support.okx):
|
|
1315
2045
|
await self.load_markets()
|
1316
2046
|
await self.authenticate()
|
1317
2047
|
url = self.get_url('private', 'private')
|
1318
|
-
messageHash =
|
2048
|
+
messageHash = self.request_id()
|
1319
2049
|
args = []
|
1320
2050
|
for i in range(0, idsLength):
|
1321
|
-
arg = {
|
2051
|
+
arg: dict = {
|
1322
2052
|
'instId': self.market_id(symbol),
|
1323
2053
|
'ordId': ids[i],
|
1324
2054
|
}
|
1325
2055
|
args.append(arg)
|
1326
|
-
request = {
|
2056
|
+
request: dict = {
|
1327
2057
|
'id': messageHash,
|
1328
2058
|
'op': 'batch-cancel-orders',
|
1329
2059
|
'args': args,
|
@@ -1332,7 +2062,9 @@ class okx(ccxt.async_support.okx):
|
|
1332
2062
|
|
1333
2063
|
async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
|
1334
2064
|
"""
|
1335
|
-
|
2065
|
+
|
2066
|
+
https://docs.okx.com/websockets/#message-cancelAll
|
2067
|
+
|
1336
2068
|
cancel all open orders of a type. Only applicable to Option in Portfolio Margin mode, and MMP privilege is required.
|
1337
2069
|
:param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
|
1338
2070
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -1346,8 +2078,8 @@ class okx(ccxt.async_support.okx):
|
|
1346
2078
|
if market['type'] != 'option':
|
1347
2079
|
raise BadRequest(self.id + 'cancelAllOrdersWs is only applicable to Option in Portfolio Margin mode, and MMP privilege is required.')
|
1348
2080
|
url = self.get_url('private', 'private')
|
1349
|
-
messageHash =
|
1350
|
-
request = {
|
2081
|
+
messageHash = self.request_id()
|
2082
|
+
request: dict = {
|
1351
2083
|
'id': messageHash,
|
1352
2084
|
'op': 'mass-cancel',
|
1353
2085
|
'args': [self.extend({
|
@@ -1390,9 +2122,9 @@ class okx(ccxt.async_support.okx):
|
|
1390
2122
|
future = self.safe_value(client.futures, 'authenticated')
|
1391
2123
|
future.resolve(True)
|
1392
2124
|
|
1393
|
-
def ping(self, client):
|
1394
|
-
#
|
1395
|
-
#
|
2125
|
+
def ping(self, client: Client):
|
2126
|
+
# OKX does not support the built-in WebSocket protocol-level ping-pong.
|
2127
|
+
# Instead, it requires a custom text-based ping-pong mechanism.
|
1396
2128
|
return 'ping'
|
1397
2129
|
|
1398
2130
|
def handle_pong(self, client: Client, message):
|
@@ -1403,24 +2135,44 @@ class okx(ccxt.async_support.okx):
|
|
1403
2135
|
#
|
1404
2136
|
# {event: 'error', msg: "Illegal request: {"op":"subscribe","args":["spot/ticker:BTC-USDT"]}", code: "60012"}
|
1405
2137
|
# {event: 'error", msg: "channel:ticker,instId:BTC-USDT doesn"t exist", code: "60018"}
|
2138
|
+
# {"event":"error","msg":"Illegal request: {\\"id\\":\\"17321173472466905\\",\\"op\\":\\"amend-order\\",\\"args\\":[{\\"instId\\":\\"ETH-USDC\\",\\"ordId\\":\\"2000345622407479296\\",\\"newSz\\":\\"0.050857\\",\\"newPx\\":\\"2949.4\\",\\"postOnly\\":true}],\\"postOnly\\":true}","code":"60012","connId":"0808af6c"}
|
1406
2139
|
#
|
1407
|
-
errorCode = self.
|
2140
|
+
errorCode = self.safe_string(message, 'code')
|
1408
2141
|
try:
|
1409
|
-
if errorCode:
|
2142
|
+
if errorCode and errorCode != '0':
|
1410
2143
|
feedback = self.id + ' ' + self.json(message)
|
1411
|
-
|
2144
|
+
if errorCode != '1':
|
2145
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
|
1412
2146
|
messageString = self.safe_value(message, 'msg')
|
1413
2147
|
if messageString is not None:
|
1414
2148
|
self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
|
2149
|
+
else:
|
2150
|
+
data = self.safe_list(message, 'data', [])
|
2151
|
+
for i in range(0, len(data)):
|
2152
|
+
d = data[i]
|
2153
|
+
errorCode = self.safe_string(d, 'sCode')
|
2154
|
+
if errorCode is not None:
|
2155
|
+
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
|
2156
|
+
messageString = self.safe_value(message, 'sMsg')
|
2157
|
+
if messageString is not None:
|
2158
|
+
self.throw_broadly_matched_exception(self.exceptions['broad'], messageString, feedback)
|
2159
|
+
raise ExchangeError(feedback)
|
1415
2160
|
except Exception as e:
|
1416
|
-
if
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
2161
|
+
# if the message contains an id, it means it is a response to a request
|
2162
|
+
# so we only reject that promise, instead of deleting all futures, destroying the authentication future
|
2163
|
+
id = self.safe_string(message, 'id')
|
2164
|
+
if id is None:
|
2165
|
+
# try to parse it from the stringified json inside msg
|
2166
|
+
msg = self.safe_string(message, 'msg')
|
2167
|
+
if msg is not None and msg.startswith('Illegal request: {'):
|
2168
|
+
stringifiedJson = msg.replace('Illegal request: ', '')
|
2169
|
+
parsedJson = self.parse_json(stringifiedJson)
|
2170
|
+
id = self.safe_string(parsedJson, 'id')
|
2171
|
+
if id is not None:
|
2172
|
+
client.reject(e, id)
|
1421
2173
|
return False
|
1422
|
-
|
1423
|
-
|
2174
|
+
client.reject(e)
|
2175
|
+
return False
|
1424
2176
|
return message
|
1425
2177
|
|
1426
2178
|
def handle_message(self, client: Client, message):
|
@@ -1472,11 +2224,12 @@ class okx(ccxt.async_support.okx):
|
|
1472
2224
|
# if table is None:
|
1473
2225
|
event = self.safe_string_2(message, 'event', 'op')
|
1474
2226
|
if event is not None:
|
1475
|
-
methods = {
|
2227
|
+
methods: dict = {
|
1476
2228
|
# 'info': self.handleSystemStatus,
|
1477
2229
|
# 'book': 'handleOrderBook',
|
1478
2230
|
'login': self.handle_authenticate,
|
1479
2231
|
'subscribe': self.handle_subscription_status,
|
2232
|
+
'unsubscribe': self.handle_unsubscription,
|
1480
2233
|
'order': self.handle_place_orders,
|
1481
2234
|
'batch-orders': self.handle_place_orders,
|
1482
2235
|
'amend-order': self.handle_place_orders,
|
@@ -1490,22 +2243,26 @@ class okx(ccxt.async_support.okx):
|
|
1490
2243
|
else:
|
1491
2244
|
arg = self.safe_value(message, 'arg', {})
|
1492
2245
|
channel = self.safe_string(arg, 'channel')
|
1493
|
-
methods = {
|
2246
|
+
methods: dict = {
|
1494
2247
|
'bbo-tbt': self.handle_order_book, # newly added channel that sends tick-by-tick Level 1 data, all API users can subscribe, public depth channel, verification not required
|
1495
2248
|
'books': self.handle_order_book, # all API users can subscribe, public depth channel, verification not required
|
1496
2249
|
'books5': self.handle_order_book, # all API users can subscribe, public depth channel, verification not required, data feeds will be delivered every 100ms(vs. every 200ms now)
|
1497
2250
|
'books50-l2-tbt': self.handle_order_book, # only users who're VIP4 and above can subscribe, identity verification required before subscription
|
1498
2251
|
'books-l2-tbt': self.handle_order_book, # only users who're VIP5 and above can subscribe, identity verification required before subscription
|
1499
2252
|
'tickers': self.handle_ticker,
|
2253
|
+
'mark-price': self.handle_ticker,
|
1500
2254
|
'positions': self.handle_positions,
|
1501
2255
|
'index-tickers': self.handle_ticker,
|
1502
2256
|
'sprd-tickers': self.handle_ticker,
|
1503
2257
|
'block-tickers': self.handle_ticker,
|
1504
2258
|
'trades': self.handle_trades,
|
1505
2259
|
'account': self.handle_balance,
|
2260
|
+
'funding-rate': self.handle_funding_rate,
|
1506
2261
|
# 'margin_account': self.handle_balance,
|
1507
2262
|
'orders': self.handle_orders,
|
1508
2263
|
'orders-algo': self.handle_orders,
|
2264
|
+
'liquidation-orders': self.handle_liquidation,
|
2265
|
+
'balance_and_position': self.handle_balance_and_position,
|
1509
2266
|
}
|
1510
2267
|
method = self.safe_value(methods, channel)
|
1511
2268
|
if method is None:
|
@@ -1513,3 +2270,57 @@ class okx(ccxt.async_support.okx):
|
|
1513
2270
|
self.handle_ohlcv(client, message)
|
1514
2271
|
else:
|
1515
2272
|
method(client, message)
|
2273
|
+
|
2274
|
+
def handle_un_subscription_trades(self, client: Client, symbol: str):
|
2275
|
+
subMessageHash = 'trades:' + symbol
|
2276
|
+
messageHash = 'unsubscribe:trades:' + symbol
|
2277
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2278
|
+
if symbol in self.trades:
|
2279
|
+
del self.trades[symbol]
|
2280
|
+
|
2281
|
+
def handle_unsubscription_order_book(self, client: Client, symbol: str, channel: str):
|
2282
|
+
subMessageHash = channel + ':' + symbol
|
2283
|
+
messageHash = 'unsubscribe:orderbook:' + symbol
|
2284
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2285
|
+
if symbol in self.orderbooks:
|
2286
|
+
del self.orderbooks[symbol]
|
2287
|
+
|
2288
|
+
def handle_unsubscription_ohlcv(self, client: Client, symbol: str, channel: str):
|
2289
|
+
tf = channel.replace('candle', '')
|
2290
|
+
timeframe = self.find_timeframe(tf)
|
2291
|
+
subMessageHash = 'multi:' + channel + ':' + symbol
|
2292
|
+
messageHash = 'unsubscribe:' + subMessageHash
|
2293
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2294
|
+
if timeframe in self.ohlcvs[symbol]:
|
2295
|
+
del self.ohlcvs[symbol][timeframe]
|
2296
|
+
|
2297
|
+
def handle_unsubscription_ticker(self, client: Client, symbol: str, channel):
|
2298
|
+
subMessageHash = channel + '::' + symbol
|
2299
|
+
messageHash = 'unsubscribe:ticker:' + symbol
|
2300
|
+
self.clean_unsubscription(client, subMessageHash, messageHash)
|
2301
|
+
if symbol in self.tickers:
|
2302
|
+
del self.tickers[symbol]
|
2303
|
+
|
2304
|
+
def handle_unsubscription(self, client: Client, message):
|
2305
|
+
#
|
2306
|
+
# {
|
2307
|
+
# "event": "unsubscribe",
|
2308
|
+
# "arg": {
|
2309
|
+
# "channel": "tickers",
|
2310
|
+
# "instId": "LTC-USD-200327"
|
2311
|
+
# },
|
2312
|
+
# "connId": "a4d3ae55"
|
2313
|
+
# }
|
2314
|
+
# arg might be an array or list
|
2315
|
+
arg = self.safe_dict(message, 'arg', {})
|
2316
|
+
channel = self.safe_string(arg, 'channel', '')
|
2317
|
+
marketId = self.safe_string(arg, 'instId')
|
2318
|
+
symbol = self.safe_symbol(marketId)
|
2319
|
+
if channel == 'trades':
|
2320
|
+
self.handle_un_subscription_trades(client, symbol)
|
2321
|
+
elif channel.startswith('bbo') or channel.startswith('book'):
|
2322
|
+
self.handle_unsubscription_order_book(client, symbol, channel)
|
2323
|
+
elif channel.find('tickers') > -1:
|
2324
|
+
self.handle_unsubscription_ticker(client, symbol, channel)
|
2325
|
+
elif channel.startswith('candle'):
|
2326
|
+
self.handle_unsubscription_ohlcv(client, symbol, channel)
|