ccxt 4.2.76__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 +25 -0
- ccxt/abstract/kucoinfutures.py +35 -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 +3513 -1511
- 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 +3105 -881
- 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 +239 -50
- ccxt/async_support/bitget.py +1513 -563
- ccxt/async_support/bithumb.py +201 -67
- 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 +403 -150
- 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 +2326 -1255
- ccxt/async_support/cex.py +1409 -1329
- ccxt/async_support/coinbase.py +1455 -288
- 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 +467 -158
- ccxt/async_support/deribit.py +558 -324
- 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 +1473 -464
- 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 +1634 -269
- 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 +1050 -355
- 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 +1777 -455
- 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 +1155 -295
- 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 +1729 -482
- 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 +3513 -1511
- ccxt/binancecoinm.py +2 -1
- ccxt/binanceus.py +12 -1
- ccxt/binanceusdm.py +3 -1
- ccxt/bingx.py +3105 -881
- 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 +239 -50
- ccxt/bitget.py +1513 -563
- ccxt/bithumb.py +200 -67
- 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 +403 -150
- ccxt/btcalpha.py +161 -55
- ccxt/btcbox.py +250 -34
- ccxt/btcmarkets.py +232 -85
- ccxt/btcturk.py +159 -60
- ccxt/bybit.py +2326 -1255
- ccxt/cex.py +1408 -1329
- ccxt/coinbase.py +1455 -288
- 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 +467 -158
- ccxt/deribit.py +558 -324
- ccxt/digifinex.py +340 -223
- ccxt/ellipx.py +1826 -0
- ccxt/exmo.py +259 -128
- ccxt/gate.py +1473 -464
- 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 +1633 -269
- 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 +1050 -355
- 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 +1777 -455
- 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 +63 -15
- 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 +204 -82
- 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 +967 -661
- 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 +168 -32
- ccxt/pro/exmo.py +253 -21
- 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 +93 -34
- ccxt/pro/poloniex.py +129 -50
- ccxt/pro/poloniexfutures.py +53 -32
- ccxt/pro/probit.py +93 -86
- 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 +486 -70
- 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} +465 -407
- ccxt/test/tests_helpers.py +285 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/{test_sync.py → tests_sync.py} +465 -409
- 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 +1155 -295
- 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.76.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.76.dist-info/METADATA +0 -626
- ccxt-4.2.76.dist-info/RECORD +0 -534
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
ccxt/pro/binance.py
CHANGED
@@ -6,25 +6,36 @@
|
|
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, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
|
-
from
|
12
|
+
from typing import Any
|
13
13
|
from ccxt.base.errors import ArgumentsRequired
|
14
14
|
from ccxt.base.errors import BadRequest
|
15
|
+
from ccxt.base.errors import NotSupported
|
16
|
+
from ccxt.base.errors import ChecksumError
|
15
17
|
from ccxt.base.precise import Precise
|
16
18
|
|
17
19
|
|
18
20
|
class binance(ccxt.async_support.binance):
|
19
21
|
|
20
22
|
def describe(self):
|
21
|
-
|
23
|
+
superDescribe = super(binance, self).describe()
|
24
|
+
return self.deep_extend(superDescribe, self.describe_data())
|
25
|
+
|
26
|
+
def describe_data(self):
|
27
|
+
return {
|
22
28
|
'has': {
|
23
29
|
'ws': True,
|
24
30
|
'watchBalance': True,
|
31
|
+
'watchLiquidations': True,
|
32
|
+
'watchLiquidationsForSymbols': True,
|
33
|
+
'watchMyLiquidations': True,
|
34
|
+
'watchMyLiquidationsForSymbols': True,
|
35
|
+
'watchBidsAsks': True,
|
25
36
|
'watchMyTrades': True,
|
26
37
|
'watchOHLCV': True,
|
27
|
-
'watchOHLCVForSymbols':
|
38
|
+
'watchOHLCVForSymbols': True,
|
28
39
|
'watchOrderBook': True,
|
29
40
|
'watchOrderBookForSymbols': True,
|
30
41
|
'watchOrders': True,
|
@@ -32,6 +43,8 @@ class binance(ccxt.async_support.binance):
|
|
32
43
|
'watchPositions': True,
|
33
44
|
'watchTicker': True,
|
34
45
|
'watchTickers': True,
|
46
|
+
'watchMarkPrices': True,
|
47
|
+
'watchMarkPrice': True,
|
35
48
|
'watchTrades': True,
|
36
49
|
'watchTradesForSymbols': True,
|
37
50
|
'createOrderWs': True,
|
@@ -44,9 +57,14 @@ class binance(ccxt.async_support.binance):
|
|
44
57
|
'fetchMarketsWs': False,
|
45
58
|
'fetchMyTradesWs': True,
|
46
59
|
'fetchOHLCVWs': True,
|
60
|
+
'fetchOrderBookWs': True,
|
47
61
|
'fetchOpenOrdersWs': True,
|
48
62
|
'fetchOrderWs': True,
|
49
63
|
'fetchOrdersWs': True,
|
64
|
+
'fetchPositionWs': True,
|
65
|
+
'fetchPositionForSymbolWs': True,
|
66
|
+
'fetchPositionsWs': True,
|
67
|
+
'fetchTickerWs': True,
|
50
68
|
'fetchTradesWs': True,
|
51
69
|
'fetchTradingFeesWs': False,
|
52
70
|
'fetchWithdrawalsWs': False,
|
@@ -58,7 +76,10 @@ class binance(ccxt.async_support.binance):
|
|
58
76
|
'margin': 'wss://testnet.binance.vision/ws',
|
59
77
|
'future': 'wss://fstream.binancefuture.com/ws',
|
60
78
|
'delivery': 'wss://dstream.binancefuture.com/ws',
|
61
|
-
'ws':
|
79
|
+
'ws-api': {
|
80
|
+
'spot': 'wss://testnet.binance.vision/ws-api/v3',
|
81
|
+
'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
|
82
|
+
},
|
62
83
|
},
|
63
84
|
},
|
64
85
|
'api': {
|
@@ -67,10 +88,14 @@ class binance(ccxt.async_support.binance):
|
|
67
88
|
'margin': 'wss://stream.binance.com:9443/ws',
|
68
89
|
'future': 'wss://fstream.binance.com/ws',
|
69
90
|
'delivery': 'wss://dstream.binance.com/ws',
|
70
|
-
'ws':
|
91
|
+
'ws-api': {
|
92
|
+
'spot': 'wss://ws-api.binance.com:443/ws-api/v3',
|
93
|
+
'future': 'wss://ws-fapi.binance.com/ws-fapi/v1',
|
94
|
+
},
|
71
95
|
'papi': 'wss://fstream.binance.com/pm/ws',
|
72
96
|
},
|
73
97
|
},
|
98
|
+
'doc': 'https://developers.binance.com/en',
|
74
99
|
},
|
75
100
|
'streaming': {
|
76
101
|
'keepAlive': 180000,
|
@@ -89,35 +114,41 @@ class binance(ccxt.async_support.binance):
|
|
89
114
|
'future': 200,
|
90
115
|
'delivery': 200,
|
91
116
|
},
|
92
|
-
'streamBySubscriptionsHash':
|
117
|
+
'streamBySubscriptionsHash': self.create_safe_dictionary(),
|
93
118
|
'streamIndex': -1,
|
94
119
|
# get updates every 1000ms or 100ms
|
95
120
|
# or every 0ms in real-time for futures
|
96
121
|
'watchOrderBookRate': 100,
|
122
|
+
'liquidationsLimit': 1000,
|
123
|
+
'myLiquidationsLimit': 1000,
|
97
124
|
'tradesLimit': 1000,
|
98
125
|
'ordersLimit': 1000,
|
99
126
|
'OHLCVLimit': 1000,
|
100
|
-
'requestId':
|
127
|
+
'requestId': self.create_safe_dictionary(),
|
101
128
|
'watchOrderBookLimit': 1000, # default limit
|
102
129
|
'watchTrades': {
|
103
130
|
'name': 'trade', # 'trade' or 'aggTrade'
|
104
131
|
},
|
105
132
|
'watchTicker': {
|
106
|
-
'name': 'ticker', # ticker
|
133
|
+
'name': 'ticker', # ticker or miniTicker or ticker_<window_size>
|
107
134
|
},
|
108
135
|
'watchTickers': {
|
109
|
-
'name': 'ticker', # ticker or miniTicker or
|
136
|
+
'name': 'ticker', # ticker or miniTicker or ticker_<window_size>
|
110
137
|
},
|
111
138
|
'watchOHLCV': {
|
112
139
|
'name': 'kline', # or indexPriceKline or markPriceKline(coin-m futures)
|
113
140
|
},
|
114
141
|
'watchOrderBook': {
|
115
142
|
'maxRetries': 3,
|
143
|
+
'checksum': True,
|
116
144
|
},
|
117
145
|
'watchBalance': {
|
118
146
|
'fetchBalanceSnapshot': False, # or True
|
119
147
|
'awaitBalanceSnapshot': True, # whether to wait for the balance snapshot before providing updates
|
120
148
|
},
|
149
|
+
'watchLiquidationsForSymbols': {
|
150
|
+
'defaultType': 'swap',
|
151
|
+
},
|
121
152
|
'watchPositions': {
|
122
153
|
'fetchPositionsSnapshot': True, # or False
|
123
154
|
'awaitPositionsSnapshot': True, # whether to wait for the positions snapshot before providing updates
|
@@ -127,18 +158,28 @@ class binance(ccxt.async_support.binance):
|
|
127
158
|
'ws': {
|
128
159
|
'cost': 5,
|
129
160
|
},
|
161
|
+
'tickerChannelsMap': {
|
162
|
+
'24hrTicker': 'ticker',
|
163
|
+
'24hrMiniTicker': 'miniTicker',
|
164
|
+
'markPriceUpdate': 'markPrice',
|
165
|
+
# rolling window tickers
|
166
|
+
'1hTicker': 'ticker_1h',
|
167
|
+
'4hTicker': 'ticker_4h',
|
168
|
+
'1dTicker': 'ticker_1d',
|
169
|
+
'bookTicker': 'bookTicker',
|
170
|
+
},
|
130
171
|
},
|
131
|
-
}
|
172
|
+
}
|
132
173
|
|
133
174
|
def request_id(self, url):
|
134
|
-
options = self.
|
175
|
+
options = self.safe_dict(self.options, 'requestId', self.create_safe_dictionary())
|
135
176
|
previousValue = self.safe_integer(options, url, 0)
|
136
177
|
newValue = self.sum(previousValue, 1)
|
137
178
|
self.options['requestId'][url] = newValue
|
138
179
|
return newValue
|
139
180
|
|
140
|
-
def stream(self, type, subscriptionHash, numSubscriptions=1):
|
141
|
-
streamBySubscriptionsHash = self.
|
181
|
+
def stream(self, type: Str, subscriptionHash: Str, numSubscriptions=1):
|
182
|
+
streamBySubscriptionsHash = self.safe_dict(self.options, 'streamBySubscriptionsHash', self.create_safe_dictionary())
|
142
183
|
stream = self.safe_string(streamBySubscriptionsHash, subscriptionHash)
|
143
184
|
if stream is None:
|
144
185
|
streamIndex = self.safe_integer(self.options, 'streamIndex', -1)
|
@@ -151,7 +192,7 @@ class binance(ccxt.async_support.binance):
|
|
151
192
|
self.options['streamBySubscriptionsHash'][subscriptionHash] = stream
|
152
193
|
subscriptionsByStreams = self.safe_value(self.options, 'numSubscriptionsByStream')
|
153
194
|
if subscriptionsByStreams is None:
|
154
|
-
self.options['numSubscriptionsByStream'] =
|
195
|
+
self.options['numSubscriptionsByStream'] = self.create_safe_dictionary()
|
155
196
|
subscriptionsByStream = self.safe_integer(self.options['numSubscriptionsByStream'], stream, 0)
|
156
197
|
newNumSubscriptions = subscriptionsByStream + numSubscriptions
|
157
198
|
subscriptionLimitByStream = self.safe_integer(self.options['subscriptionLimitByStream'], type, 200)
|
@@ -160,8 +201,342 @@ class binance(ccxt.async_support.binance):
|
|
160
201
|
self.options['numSubscriptionsByStream'][stream] = subscriptionsByStream + numSubscriptions
|
161
202
|
return stream
|
162
203
|
|
204
|
+
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
205
|
+
"""
|
206
|
+
watch the public liquidations of a trading pair
|
207
|
+
|
208
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Liquidation-Order-Streams
|
209
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/Liquidation-Order-Streams
|
210
|
+
|
211
|
+
:param str symbol: unified CCXT market symbol
|
212
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
213
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
214
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
215
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
216
|
+
"""
|
217
|
+
return await self.watch_liquidations_for_symbols([symbol], since, limit, params)
|
218
|
+
|
219
|
+
async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
220
|
+
"""
|
221
|
+
watch the public liquidations of a trading pair
|
222
|
+
|
223
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Liquidation-Order-Streams
|
224
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Market-Liquidation-Order-Streams
|
225
|
+
|
226
|
+
:param str[] symbols: list of unified market symbols
|
227
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
228
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
229
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
230
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
231
|
+
"""
|
232
|
+
await self.load_markets()
|
233
|
+
subscriptionHashes = []
|
234
|
+
messageHashes = []
|
235
|
+
streamHash = 'liquidations'
|
236
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
237
|
+
if self.is_empty(symbols):
|
238
|
+
subscriptionHashes.append('!' + 'forceOrder@arr')
|
239
|
+
messageHashes.append('liquidations')
|
240
|
+
else:
|
241
|
+
for i in range(0, len(symbols)):
|
242
|
+
market = self.market(symbols[i])
|
243
|
+
subscriptionHashes.append(market['lowercaseId'] + '@forceOrder')
|
244
|
+
messageHashes.append('liquidations::' + symbols[i])
|
245
|
+
streamHash += '::' + ','.join(symbols)
|
246
|
+
firstMarket = self.get_market_from_symbols(symbols)
|
247
|
+
type = None
|
248
|
+
type, params = self.handle_market_type_and_params('watchLiquidationsForSymbols', firstMarket, params)
|
249
|
+
if type == 'spot':
|
250
|
+
raise BadRequest(self.id + 'watchLiquidationsForSymbols is not supported for spot symbols')
|
251
|
+
subType = None
|
252
|
+
subType, params = self.handle_sub_type_and_params('watchLiquidationsForSymbols', firstMarket, params)
|
253
|
+
if self.isLinear(type, subType):
|
254
|
+
type = 'future'
|
255
|
+
elif self.isInverse(type, subType):
|
256
|
+
type = 'delivery'
|
257
|
+
numSubscriptions = len(subscriptionHashes)
|
258
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, numSubscriptions)
|
259
|
+
requestId = self.request_id(url)
|
260
|
+
request = {
|
261
|
+
'method': 'SUBSCRIBE',
|
262
|
+
'params': subscriptionHashes,
|
263
|
+
'id': requestId,
|
264
|
+
}
|
265
|
+
subscribe = {
|
266
|
+
'id': requestId,
|
267
|
+
}
|
268
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, self.extend(request, params), subscriptionHashes, subscribe)
|
269
|
+
if self.newUpdates:
|
270
|
+
return newLiquidations
|
271
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
272
|
+
|
273
|
+
def handle_liquidation(self, client: Client, message):
|
274
|
+
#
|
275
|
+
# future
|
276
|
+
# {
|
277
|
+
# "e":"forceOrder",
|
278
|
+
# "E":1698871323061,
|
279
|
+
# "o":{
|
280
|
+
# "s":"BTCUSDT",
|
281
|
+
# "S":"BUY",
|
282
|
+
# "o":"LIMIT",
|
283
|
+
# "f":"IOC",
|
284
|
+
# "q":"1.437",
|
285
|
+
# "p":"35100.81",
|
286
|
+
# "ap":"34959.70",
|
287
|
+
# "X":"FILLED",
|
288
|
+
# "l":"1.437",
|
289
|
+
# "z":"1.437",
|
290
|
+
# "T":1698871323059
|
291
|
+
# }
|
292
|
+
# }
|
293
|
+
# delivery
|
294
|
+
# {
|
295
|
+
# "e":"forceOrder", # Event Type
|
296
|
+
# "E": 1591154240950, # Event Time
|
297
|
+
# "o":{
|
298
|
+
# "s":"BTCUSD_200925", # Symbol
|
299
|
+
# "ps": "BTCUSD", # Pair
|
300
|
+
# "S":"SELL", # Side
|
301
|
+
# "o":"LIMIT", # Order Type
|
302
|
+
# "f":"IOC", # Time in Force
|
303
|
+
# "q":"1", # Original Quantity
|
304
|
+
# "p":"9425.5", # Price
|
305
|
+
# "ap":"9496.5", # Average Price
|
306
|
+
# "X":"FILLED", # Order Status
|
307
|
+
# "l":"1", # Order Last Filled Quantity
|
308
|
+
# "z":"1", # Order Filled Accumulated Quantity
|
309
|
+
# "T": 1591154240949, # Order Trade Time
|
310
|
+
# }
|
311
|
+
# }
|
312
|
+
#
|
313
|
+
rawLiquidation = self.safe_value(message, 'o', {})
|
314
|
+
marketId = self.safe_string(rawLiquidation, 's')
|
315
|
+
market = self.safe_market(marketId, None, '', 'contract')
|
316
|
+
symbol = market['symbol']
|
317
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation, market)
|
318
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
319
|
+
if liquidations is None:
|
320
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
321
|
+
liquidations = ArrayCache(limit)
|
322
|
+
liquidations.append(liquidation)
|
323
|
+
self.liquidations[symbol] = liquidations
|
324
|
+
client.resolve([liquidation], 'liquidations')
|
325
|
+
client.resolve([liquidation], 'liquidations::' + symbol)
|
326
|
+
|
327
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
328
|
+
#
|
329
|
+
# future
|
330
|
+
# {
|
331
|
+
# "s":"BTCUSDT",
|
332
|
+
# "S":"BUY",
|
333
|
+
# "o":"LIMIT",
|
334
|
+
# "f":"IOC",
|
335
|
+
# "q":"1.437",
|
336
|
+
# "p":"35100.81",
|
337
|
+
# "ap":"34959.70",
|
338
|
+
# "X":"FILLED",
|
339
|
+
# "l":"1.437",
|
340
|
+
# "z":"1.437",
|
341
|
+
# "T":1698871323059
|
342
|
+
# }
|
343
|
+
# delivery
|
344
|
+
# {
|
345
|
+
# "s":"BTCUSD_200925", # Symbol
|
346
|
+
# "ps": "BTCUSD", # Pair
|
347
|
+
# "S":"SELL", # Side
|
348
|
+
# "o":"LIMIT", # Order Type
|
349
|
+
# "f":"IOC", # Time in Force
|
350
|
+
# "q":"1", # Original Quantity
|
351
|
+
# "p":"9425.5", # Price
|
352
|
+
# "ap":"9496.5", # Average Price
|
353
|
+
# "X":"FILLED", # Order Status
|
354
|
+
# "l":"1", # Order Last Filled Quantity
|
355
|
+
# "z":"1", # Order Filled Accumulated Quantity
|
356
|
+
# "T": 1591154240949, # Order Trade Time
|
357
|
+
# }
|
358
|
+
# myLiquidation
|
359
|
+
# {
|
360
|
+
# "s":"BTCUSDT", # Symbol
|
361
|
+
# "c":"TEST", # Client Order Id
|
362
|
+
# # special client order id:
|
363
|
+
# # starts with "autoclose-": liquidation order
|
364
|
+
# # "adl_autoclose": ADL auto close order
|
365
|
+
# # "settlement_autoclose-": settlement order for delisting or delivery
|
366
|
+
# "S":"SELL", # Side
|
367
|
+
# "o":"TRAILING_STOP_MARKET", # Order Type
|
368
|
+
# "f":"GTC", # Time in Force
|
369
|
+
# "q":"0.001", # Original Quantity
|
370
|
+
# "p":"0", # Original Price
|
371
|
+
# "ap":"0", # Average Price
|
372
|
+
# "sp":"7103.04", # Stop Price. Please ignore with TRAILING_STOP_MARKET order
|
373
|
+
# "x":"NEW", # Execution Type
|
374
|
+
# "X":"NEW", # Order Status
|
375
|
+
# "i":8886774, # Order Id
|
376
|
+
# "l":"0", # Order Last Filled Quantity
|
377
|
+
# "z":"0", # Order Filled Accumulated Quantity
|
378
|
+
# "L":"0", # Last Filled Price
|
379
|
+
# "N":"USDT", # Commission Asset, will not push if no commission
|
380
|
+
# "n":"0", # Commission, will not push if no commission
|
381
|
+
# "T":1568879465650, # Order Trade Time
|
382
|
+
# "t":0, # Trade Id
|
383
|
+
# "b":"0", # Bids Notional
|
384
|
+
# "a":"9.91", # Ask Notional
|
385
|
+
# "m":false, # Is self trade the maker side?
|
386
|
+
# "R":false, # Is self reduce only
|
387
|
+
# "wt":"CONTRACT_PRICE", # Stop Price Working Type
|
388
|
+
# "ot":"TRAILING_STOP_MARKET",// Original Order Type
|
389
|
+
# "ps":"LONG", # Position Side
|
390
|
+
# "cp":false, # If Close-All, pushed with conditional order
|
391
|
+
# "AP":"7476.89", # Activation Price, only puhed with TRAILING_STOP_MARKET order
|
392
|
+
# "cr":"5.0", # Callback Rate, only puhed with TRAILING_STOP_MARKET order
|
393
|
+
# "pP": False, # If price protection is turned on
|
394
|
+
# "si": 0, # ignore
|
395
|
+
# "ss": 0, # ignore
|
396
|
+
# "rp":"0", # Realized Profit of the trade
|
397
|
+
# "V":"EXPIRE_TAKER", # STP mode
|
398
|
+
# "pm":"OPPONENT", # Price match mode
|
399
|
+
# "gtd":0 # TIF GTD order auto cancel time
|
400
|
+
# }
|
401
|
+
#
|
402
|
+
marketId = self.safe_string(liquidation, 's')
|
403
|
+
market = self.safe_market(marketId, market)
|
404
|
+
timestamp = self.safe_integer(liquidation, 'T')
|
405
|
+
return self.safe_liquidation({
|
406
|
+
'info': liquidation,
|
407
|
+
'symbol': self.safe_symbol(marketId, market),
|
408
|
+
'contracts': self.safe_number(liquidation, 'l'),
|
409
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
410
|
+
'price': self.safe_number(liquidation, 'ap'),
|
411
|
+
'baseValue': None,
|
412
|
+
'quoteValue': None,
|
413
|
+
'timestamp': timestamp,
|
414
|
+
'datetime': self.iso8601(timestamp),
|
415
|
+
})
|
416
|
+
|
417
|
+
async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
418
|
+
"""
|
419
|
+
watch the private liquidations of a trading pair
|
420
|
+
|
421
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Order-Update
|
422
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/user-data-streams/Event-Order-Update
|
423
|
+
|
424
|
+
:param str symbol: unified CCXT market symbol
|
425
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
426
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
427
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
428
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
429
|
+
"""
|
430
|
+
return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
|
431
|
+
|
432
|
+
async def watch_my_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
433
|
+
"""
|
434
|
+
watch the private liquidations of a trading pair
|
435
|
+
|
436
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Order-Update
|
437
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/user-data-streams/Event-Order-Update
|
438
|
+
|
439
|
+
:param str[] symbols: list of unified market symbols
|
440
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
441
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
442
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
443
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
444
|
+
"""
|
445
|
+
await self.load_markets()
|
446
|
+
symbols = self.market_symbols(symbols, None, True, True, True)
|
447
|
+
market = self.get_market_from_symbols(symbols)
|
448
|
+
messageHashes = ['myLiquidations']
|
449
|
+
if not self.is_empty(symbols):
|
450
|
+
for i in range(0, len(symbols)):
|
451
|
+
symbol = symbols[i]
|
452
|
+
messageHashes.append('myLiquidations::' + symbol)
|
453
|
+
type = None
|
454
|
+
type, params = self.handle_market_type_and_params('watchMyLiquidationsForSymbols', market, params)
|
455
|
+
subType = None
|
456
|
+
subType, params = self.handle_sub_type_and_params('watchMyLiquidationsForSymbols', market, params)
|
457
|
+
if self.isLinear(type, subType):
|
458
|
+
type = 'future'
|
459
|
+
elif self.isInverse(type, subType):
|
460
|
+
type = 'delivery'
|
461
|
+
await self.authenticate(params)
|
462
|
+
url = self.urls['api']['ws'][type] + '/' + self.options[type]['listenKey']
|
463
|
+
message = None
|
464
|
+
newLiquidations = await self.watch_multiple(url, messageHashes, message, [type])
|
465
|
+
if self.newUpdates:
|
466
|
+
return newLiquidations
|
467
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit)
|
468
|
+
|
469
|
+
def handle_my_liquidation(self, client: Client, message):
|
470
|
+
#
|
471
|
+
# {
|
472
|
+
# "s":"BTCUSDT", # Symbol
|
473
|
+
# "c":"TEST", # Client Order Id
|
474
|
+
# # special client order id:
|
475
|
+
# # starts with "autoclose-": liquidation order
|
476
|
+
# # "adl_autoclose": ADL auto close order
|
477
|
+
# # "settlement_autoclose-": settlement order for delisting or delivery
|
478
|
+
# "S":"SELL", # Side
|
479
|
+
# "o":"TRAILING_STOP_MARKET", # Order Type
|
480
|
+
# "f":"GTC", # Time in Force
|
481
|
+
# "q":"0.001", # Original Quantity
|
482
|
+
# "p":"0", # Original Price
|
483
|
+
# "ap":"0", # Average Price
|
484
|
+
# "sp":"7103.04", # Stop Price. Please ignore with TRAILING_STOP_MARKET order
|
485
|
+
# "x":"NEW", # Execution Type
|
486
|
+
# "X":"NEW", # Order Status
|
487
|
+
# "i":8886774, # Order Id
|
488
|
+
# "l":"0", # Order Last Filled Quantity
|
489
|
+
# "z":"0", # Order Filled Accumulated Quantity
|
490
|
+
# "L":"0", # Last Filled Price
|
491
|
+
# "N":"USDT", # Commission Asset, will not push if no commission
|
492
|
+
# "n":"0", # Commission, will not push if no commission
|
493
|
+
# "T":1568879465650, # Order Trade Time
|
494
|
+
# "t":0, # Trade Id
|
495
|
+
# "b":"0", # Bids Notional
|
496
|
+
# "a":"9.91", # Ask Notional
|
497
|
+
# "m":false, # Is self trade the maker side?
|
498
|
+
# "R":false, # Is self reduce only
|
499
|
+
# "wt":"CONTRACT_PRICE", # Stop Price Working Type
|
500
|
+
# "ot":"TRAILING_STOP_MARKET",// Original Order Type
|
501
|
+
# "ps":"LONG", # Position Side
|
502
|
+
# "cp":false, # If Close-All, pushed with conditional order
|
503
|
+
# "AP":"7476.89", # Activation Price, only puhed with TRAILING_STOP_MARKET order
|
504
|
+
# "cr":"5.0", # Callback Rate, only puhed with TRAILING_STOP_MARKET order
|
505
|
+
# "pP": False, # If price protection is turned on
|
506
|
+
# "si": 0, # ignore
|
507
|
+
# "ss": 0, # ignore
|
508
|
+
# "rp":"0", # Realized Profit of the trade
|
509
|
+
# "V":"EXPIRE_TAKER", # STP mode
|
510
|
+
# "pm":"OPPONENT", # Price match mode
|
511
|
+
# "gtd":0 # TIF GTD order auto cancel time
|
512
|
+
# }
|
513
|
+
#
|
514
|
+
orderType = self.safe_string(message, 'o')
|
515
|
+
if orderType != 'LIQUIDATION':
|
516
|
+
return
|
517
|
+
marketId = self.safe_string(message, 's')
|
518
|
+
market = self.safe_market(marketId)
|
519
|
+
symbol = self.safe_symbol(marketId)
|
520
|
+
liquidation = self.parse_ws_liquidation(message, market)
|
521
|
+
myLiquidations = self.safe_value(self.myLiquidations, symbol)
|
522
|
+
if myLiquidations is None:
|
523
|
+
limit = self.safe_integer(self.options, 'myLiquidationsLimit', 1000)
|
524
|
+
myLiquidations = ArrayCache(limit)
|
525
|
+
myLiquidations.append(liquidation)
|
526
|
+
self.myLiquidations[symbol] = myLiquidations
|
527
|
+
client.resolve([liquidation], 'myLiquidations')
|
528
|
+
client.resolve([liquidation], 'myLiquidations::' + symbol)
|
529
|
+
|
163
530
|
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
164
531
|
"""
|
532
|
+
|
533
|
+
https://binance-docs.github.io/apidocs/spot/en/#partial-book-depth-streams
|
534
|
+
https://binance-docs.github.io/apidocs/spot/en/#diff-depth-stream
|
535
|
+
https://binance-docs.github.io/apidocs/futures/en/#partial-book-depth-streams
|
536
|
+
https://binance-docs.github.io/apidocs/futures/en/#diff-book-depth-streams
|
537
|
+
https://binance-docs.github.io/apidocs/delivery/en/#partial-book-depth-streams
|
538
|
+
https://binance-docs.github.io/apidocs/delivery/en/#diff-book-depth-streams
|
539
|
+
|
165
540
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
166
541
|
:param str symbol: unified symbol of the market to fetch the order book for
|
167
542
|
:param int [limit]: the maximum amount of order book entries to return
|
@@ -209,6 +584,14 @@ class binance(ccxt.async_support.binance):
|
|
209
584
|
|
210
585
|
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}) -> OrderBook:
|
211
586
|
"""
|
587
|
+
|
588
|
+
https://binance-docs.github.io/apidocs/spot/en/#partial-book-depth-streams
|
589
|
+
https://binance-docs.github.io/apidocs/spot/en/#diff-depth-stream
|
590
|
+
https://binance-docs.github.io/apidocs/futures/en/#partial-book-depth-streams
|
591
|
+
https://binance-docs.github.io/apidocs/futures/en/#diff-book-depth-streams
|
592
|
+
https://binance-docs.github.io/apidocs/delivery/en/#partial-book-depth-streams
|
593
|
+
https://binance-docs.github.io/apidocs/delivery/en/#diff-book-depth-streams
|
594
|
+
|
212
595
|
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
213
596
|
:param str[] symbols: unified array of symbols
|
214
597
|
:param int [limit]: the maximum amount of order book entries to return
|
@@ -234,19 +617,19 @@ class binance(ccxt.async_support.binance):
|
|
234
617
|
for i in range(0, len(symbols)):
|
235
618
|
symbol = symbols[i]
|
236
619
|
market = self.market(symbol)
|
237
|
-
|
238
|
-
|
239
|
-
symbolHash =
|
620
|
+
messageHashes.append('orderbook::' + symbol)
|
621
|
+
subscriptionHash = market['lowercaseId'] + '@' + name
|
622
|
+
symbolHash = subscriptionHash + '@' + watchOrderBookRate + 'ms'
|
240
623
|
subParams.append(symbolHash)
|
241
624
|
messageHashesLength = len(messageHashes)
|
242
625
|
url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, messageHashesLength)
|
243
626
|
requestId = self.request_id(url)
|
244
|
-
request = {
|
627
|
+
request: dict = {
|
245
628
|
'method': 'SUBSCRIBE',
|
246
629
|
'params': subParams,
|
247
630
|
'id': requestId,
|
248
631
|
}
|
249
|
-
subscription = {
|
632
|
+
subscription: dict = {
|
250
633
|
'id': str(requestId),
|
251
634
|
'name': name,
|
252
635
|
'symbols': symbols,
|
@@ -255,15 +638,156 @@ class binance(ccxt.async_support.binance):
|
|
255
638
|
'type': type,
|
256
639
|
'params': params,
|
257
640
|
}
|
258
|
-
|
259
|
-
orderbook = await self.watch_multiple(url, messageHashes, message, messageHashes, subscription)
|
641
|
+
orderbook = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscription)
|
260
642
|
return orderbook.limit()
|
261
643
|
|
644
|
+
async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}) -> Any:
|
645
|
+
"""
|
646
|
+
|
647
|
+
https://binance-docs.github.io/apidocs/spot/en/#partial-book-depth-streams
|
648
|
+
https://binance-docs.github.io/apidocs/spot/en/#diff-depth-stream
|
649
|
+
https://binance-docs.github.io/apidocs/futures/en/#partial-book-depth-streams
|
650
|
+
https://binance-docs.github.io/apidocs/futures/en/#diff-book-depth-streams
|
651
|
+
https://binance-docs.github.io/apidocs/delivery/en/#partial-book-depth-streams
|
652
|
+
https://binance-docs.github.io/apidocs/delivery/en/#diff-book-depth-streams
|
653
|
+
|
654
|
+
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
655
|
+
:param str[] symbols: unified array of symbols
|
656
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
657
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
658
|
+
"""
|
659
|
+
await self.load_markets()
|
660
|
+
symbols = self.market_symbols(symbols, None, False, True, True)
|
661
|
+
firstMarket = self.market(symbols[0])
|
662
|
+
type = firstMarket['type']
|
663
|
+
if firstMarket['contract']:
|
664
|
+
type = 'future' if firstMarket['linear'] else 'delivery'
|
665
|
+
name = 'depth'
|
666
|
+
streamHash = 'multipleOrderbook'
|
667
|
+
if symbols is not None:
|
668
|
+
streamHash += '::' + ','.join(symbols)
|
669
|
+
watchOrderBookRate = self.safe_string(self.options, 'watchOrderBookRate', '100')
|
670
|
+
subParams = []
|
671
|
+
subMessageHashes = []
|
672
|
+
messageHashes = []
|
673
|
+
for i in range(0, len(symbols)):
|
674
|
+
symbol = symbols[i]
|
675
|
+
market = self.market(symbol)
|
676
|
+
subMessageHashes.append('orderbook::' + symbol)
|
677
|
+
messageHashes.append('unsubscribe:orderbook:' + symbol)
|
678
|
+
subscriptionHash = market['lowercaseId'] + '@' + name
|
679
|
+
symbolHash = subscriptionHash + '@' + watchOrderBookRate + 'ms'
|
680
|
+
subParams.append(symbolHash)
|
681
|
+
messageHashesLength = len(subMessageHashes)
|
682
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, messageHashesLength)
|
683
|
+
requestId = self.request_id(url)
|
684
|
+
request: dict = {
|
685
|
+
'method': 'UNSUBSCRIBE',
|
686
|
+
'params': subParams,
|
687
|
+
'id': requestId,
|
688
|
+
}
|
689
|
+
subscription: dict = {
|
690
|
+
'unsubscribe': True,
|
691
|
+
'id': str(requestId),
|
692
|
+
'symbols': symbols,
|
693
|
+
'subMessageHashes': subMessageHashes,
|
694
|
+
'messageHashes': messageHashes,
|
695
|
+
'topic': 'orderbook',
|
696
|
+
}
|
697
|
+
return await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscription)
|
698
|
+
|
699
|
+
async def un_watch_order_book(self, symbol: str, params={}) -> Any:
|
700
|
+
"""
|
701
|
+
|
702
|
+
https://binance-docs.github.io/apidocs/spot/en/#partial-book-depth-streams
|
703
|
+
https://binance-docs.github.io/apidocs/spot/en/#diff-depth-stream
|
704
|
+
https://binance-docs.github.io/apidocs/futures/en/#partial-book-depth-streams
|
705
|
+
https://binance-docs.github.io/apidocs/futures/en/#diff-book-depth-streams
|
706
|
+
https://binance-docs.github.io/apidocs/delivery/en/#partial-book-depth-streams
|
707
|
+
https://binance-docs.github.io/apidocs/delivery/en/#diff-book-depth-streams
|
708
|
+
|
709
|
+
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
710
|
+
:param str symbol: unified array of symbols
|
711
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
712
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
713
|
+
"""
|
714
|
+
return await self.un_watch_order_book_for_symbols([symbol], params)
|
715
|
+
|
716
|
+
async def fetch_order_book_ws(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
717
|
+
"""
|
718
|
+
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
719
|
+
|
720
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#order-book
|
721
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/websocket-api/Order-Book
|
722
|
+
|
723
|
+
:param str symbol: unified symbol of the market to fetch the order book for
|
724
|
+
:param int [limit]: the maximum amount of order book entries to return
|
725
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
726
|
+
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
727
|
+
"""
|
728
|
+
await self.load_markets()
|
729
|
+
market = self.market(symbol)
|
730
|
+
payload: dict = {
|
731
|
+
'symbol': market['id'],
|
732
|
+
}
|
733
|
+
if limit is not None:
|
734
|
+
payload['limit'] = limit
|
735
|
+
marketType = self.get_market_type('fetchOrderBookWs', market, params)
|
736
|
+
if marketType != 'future':
|
737
|
+
raise BadRequest(self.id + ' fetchOrderBookWs only supports swap markets')
|
738
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
739
|
+
requestId = self.request_id(url)
|
740
|
+
messageHash = str(requestId)
|
741
|
+
returnRateLimits = False
|
742
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'createOrderWs', 'returnRateLimits', False)
|
743
|
+
payload['returnRateLimits'] = returnRateLimits
|
744
|
+
params = self.omit(params, 'test')
|
745
|
+
message: dict = {
|
746
|
+
'id': messageHash,
|
747
|
+
'method': 'depth',
|
748
|
+
'params': self.sign_params(self.extend(payload, params)),
|
749
|
+
}
|
750
|
+
subscription: dict = {
|
751
|
+
'method': self.handle_fetch_order_book,
|
752
|
+
}
|
753
|
+
orderbook = await self.watch(url, messageHash, message, messageHash, subscription)
|
754
|
+
orderbook['symbol'] = market['symbol']
|
755
|
+
return orderbook
|
756
|
+
|
757
|
+
def handle_fetch_order_book(self, client: Client, message):
|
758
|
+
#
|
759
|
+
# {
|
760
|
+
# "id":"51e2affb-0aba-4821-ba75-f2625006eb43",
|
761
|
+
# "status":200,
|
762
|
+
# "result":{
|
763
|
+
# "lastUpdateId":1027024,
|
764
|
+
# "E":1589436922972,
|
765
|
+
# "T":1589436922959,
|
766
|
+
# "bids":[
|
767
|
+
# [
|
768
|
+
# "4.00000000",
|
769
|
+
# "431.00000000"
|
770
|
+
# ]
|
771
|
+
# ],
|
772
|
+
# "asks":[
|
773
|
+
# [
|
774
|
+
# "4.00000200",
|
775
|
+
# "12.00000000"
|
776
|
+
# ]
|
777
|
+
# ]
|
778
|
+
# }
|
779
|
+
# }
|
780
|
+
#
|
781
|
+
messageHash = self.safe_string(message, 'id')
|
782
|
+
result = self.safe_dict(message, 'result')
|
783
|
+
timestamp = self.safe_integer(result, 'T')
|
784
|
+
orderbook = self.parse_order_book(result, None, timestamp)
|
785
|
+
orderbook['nonce'] = self.safe_integer_2(result, 'lastUpdateId', 'u')
|
786
|
+
client.resolve(orderbook, messageHash)
|
787
|
+
|
262
788
|
async def fetch_order_book_snapshot(self, client, message, subscription):
|
263
|
-
name = self.safe_string(subscription, 'name')
|
264
789
|
symbol = self.safe_string(subscription, 'symbol')
|
265
|
-
|
266
|
-
messageHash = market['lowercaseId'] + '@' + name
|
790
|
+
messageHash = 'orderbook::' + symbol
|
267
791
|
try:
|
268
792
|
defaultLimit = self.safe_integer(self.options, 'watchOrderBookLimit', 1000)
|
269
793
|
type = self.safe_value(subscription, 'type')
|
@@ -273,10 +797,10 @@ class binance(ccxt.async_support.binance):
|
|
273
797
|
# todo: self is a synch blocking call - make it async
|
274
798
|
# default 100, max 1000, valid limits 5, 10, 20, 50, 100, 500, 1000
|
275
799
|
snapshot = await self.fetch_rest_order_book_safe(symbol, limit, params)
|
276
|
-
|
277
|
-
if orderbook is None:
|
800
|
+
if self.safe_value(self.orderbooks, symbol) is None:
|
278
801
|
# if the orderbook is dropped before the snapshot is received
|
279
802
|
return
|
803
|
+
orderbook = self.orderbooks[symbol]
|
280
804
|
orderbook.reset(snapshot)
|
281
805
|
# unroll the accumulated deltas
|
282
806
|
messages = orderbook.cache
|
@@ -350,10 +874,8 @@ class binance(ccxt.async_support.binance):
|
|
350
874
|
marketId = self.safe_string(message, 's')
|
351
875
|
market = self.safe_market(marketId, None, None, marketType)
|
352
876
|
symbol = market['symbol']
|
353
|
-
|
354
|
-
|
355
|
-
orderbook = self.safe_value(self.orderbooks, symbol)
|
356
|
-
if orderbook is None:
|
877
|
+
messageHash = 'orderbook::' + symbol
|
878
|
+
if not (symbol in self.orderbooks):
|
357
879
|
#
|
358
880
|
# https://github.com/ccxt/ccxt/issues/6672
|
359
881
|
#
|
@@ -363,6 +885,7 @@ class binance(ccxt.async_support.binance):
|
|
363
885
|
# therefore it is safe to drop these premature messages.
|
364
886
|
#
|
365
887
|
return
|
888
|
+
orderbook = self.orderbooks[symbol]
|
366
889
|
nonce = self.safe_integer(orderbook, 'nonce')
|
367
890
|
if nonce is None:
|
368
891
|
# 2. Buffer the events you receive from the stream.
|
@@ -389,8 +912,10 @@ class binance(ccxt.async_support.binance):
|
|
389
912
|
if nonce < orderbook['nonce']:
|
390
913
|
client.resolve(orderbook, messageHash)
|
391
914
|
else:
|
392
|
-
|
393
|
-
|
915
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
916
|
+
if checksum:
|
917
|
+
# todo: client.reject from handleOrderBookMessage properly
|
918
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
394
919
|
else:
|
395
920
|
# future
|
396
921
|
# 4. Drop any event where u is < lastUpdateId in the snapshot
|
@@ -402,8 +927,10 @@ class binance(ccxt.async_support.binance):
|
|
402
927
|
if nonce <= orderbook['nonce']:
|
403
928
|
client.resolve(orderbook, messageHash)
|
404
929
|
else:
|
405
|
-
|
406
|
-
|
930
|
+
checksum = self.handle_option('watchOrderBook', 'checksum', True)
|
931
|
+
if checksum:
|
932
|
+
# todo: client.reject from handleOrderBookMessage properly
|
933
|
+
raise ChecksumError(self.id + ' ' + self.orderbook_checksum_message(symbol))
|
407
934
|
except Exception as e:
|
408
935
|
del self.orderbooks[symbol]
|
409
936
|
del client.subscriptions[messageHash]
|
@@ -438,15 +965,34 @@ class binance(ccxt.async_support.binance):
|
|
438
965
|
method = self.safe_value(subscription, 'method')
|
439
966
|
if method is not None:
|
440
967
|
method(client, message, subscription)
|
968
|
+
isUnSubMessage = self.safe_bool(subscription, 'unsubscribe', False)
|
969
|
+
if isUnSubMessage:
|
970
|
+
self.handle_un_subscription(client, subscription)
|
441
971
|
return message
|
442
972
|
|
973
|
+
def handle_un_subscription(self, client: Client, subscription: dict):
|
974
|
+
messageHashes = self.safe_list(subscription, 'messageHashes', [])
|
975
|
+
subMessageHashes = self.safe_list(subscription, 'subMessageHashes', [])
|
976
|
+
for j in range(0, len(messageHashes)):
|
977
|
+
unsubHash = messageHashes[j]
|
978
|
+
subHash = subMessageHashes[j]
|
979
|
+
self.clean_unsubscription(client, subHash, unsubHash)
|
980
|
+
self.clean_cache(subscription)
|
981
|
+
|
443
982
|
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
444
983
|
"""
|
445
984
|
get the list of most recent trades for a list of symbols
|
985
|
+
|
986
|
+
https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams
|
987
|
+
https://binance-docs.github.io/apidocs/spot/en/#trade-streams
|
988
|
+
https://binance-docs.github.io/apidocs/futures/en/#aggregate-trade-streams
|
989
|
+
https://binance-docs.github.io/apidocs/delivery/en/#aggregate-trade-streams
|
990
|
+
|
446
991
|
:param str[] symbols: unified symbol of the market to fetch trades for
|
447
992
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
448
993
|
:param int [limit]: the maximum amount of trades to fetch
|
449
994
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
995
|
+
:param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
|
450
996
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
451
997
|
"""
|
452
998
|
await self.load_markets()
|
@@ -457,46 +1003,132 @@ class binance(ccxt.async_support.binance):
|
|
457
1003
|
if symbolsLength > 200:
|
458
1004
|
raise BadRequest(self.id + ' watchTradesForSymbols() accepts 200 symbols at most. To watch more symbols call watchTradesForSymbols() multiple times')
|
459
1005
|
streamHash += '::' + ','.join(symbols)
|
460
|
-
|
461
|
-
name = self.
|
1006
|
+
name = None
|
1007
|
+
name, params = self.handle_option_and_params(params, 'watchTradesForSymbols', 'name', 'trade')
|
1008
|
+
params = self.omit(params, 'callerMethodName')
|
462
1009
|
firstMarket = self.market(symbols[0])
|
463
1010
|
type = firstMarket['type']
|
464
1011
|
if firstMarket['contract']:
|
465
1012
|
type = 'future' if firstMarket['linear'] else 'delivery'
|
1013
|
+
messageHashes = []
|
466
1014
|
subParams = []
|
467
1015
|
for i in range(0, len(symbols)):
|
468
1016
|
symbol = symbols[i]
|
469
1017
|
market = self.market(symbol)
|
470
|
-
|
471
|
-
|
1018
|
+
messageHashes.append('trade::' + symbol)
|
1019
|
+
rawHash = market['lowercaseId'] + '@' + name
|
1020
|
+
subParams.append(rawHash)
|
472
1021
|
query = self.omit(params, 'type')
|
473
1022
|
subParamsLength = len(subParams)
|
474
1023
|
url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, subParamsLength)
|
475
1024
|
requestId = self.request_id(url)
|
476
|
-
request = {
|
1025
|
+
request: dict = {
|
477
1026
|
'method': 'SUBSCRIBE',
|
478
1027
|
'params': subParams,
|
479
1028
|
'id': requestId,
|
480
1029
|
}
|
481
|
-
subscribe = {
|
1030
|
+
subscribe: dict = {
|
482
1031
|
'id': requestId,
|
483
1032
|
}
|
484
|
-
trades = await self.watch_multiple(url,
|
1033
|
+
trades = await self.watch_multiple(url, messageHashes, self.extend(request, query), messageHashes, subscribe)
|
485
1034
|
if self.newUpdates:
|
486
1035
|
first = self.safe_value(trades, 0)
|
487
1036
|
tradeSymbol = self.safe_string(first, 'symbol')
|
488
1037
|
limit = trades.getLimit(tradeSymbol, limit)
|
489
1038
|
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
|
490
1039
|
|
1040
|
+
async def un_watch_trades_for_symbols(self, symbols: List[str], params={}) -> Any:
|
1041
|
+
"""
|
1042
|
+
unsubscribes from the trades channel
|
1043
|
+
|
1044
|
+
https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams
|
1045
|
+
https://binance-docs.github.io/apidocs/spot/en/#trade-streams
|
1046
|
+
https://binance-docs.github.io/apidocs/futures/en/#aggregate-trade-streams
|
1047
|
+
https://binance-docs.github.io/apidocs/delivery/en/#aggregate-trade-streams
|
1048
|
+
|
1049
|
+
:param str[] symbols: unified symbol of the market to fetch trades for
|
1050
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1051
|
+
:param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
|
1052
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
1053
|
+
"""
|
1054
|
+
await self.load_markets()
|
1055
|
+
symbols = self.market_symbols(symbols, None, False, True, True)
|
1056
|
+
streamHash = 'multipleTrades'
|
1057
|
+
if symbols is not None:
|
1058
|
+
symbolsLength = len(symbols)
|
1059
|
+
if symbolsLength > 200:
|
1060
|
+
raise BadRequest(self.id + ' watchTradesForSymbols() accepts 200 symbols at most. To watch more symbols call watchTradesForSymbols() multiple times')
|
1061
|
+
streamHash += '::' + ','.join(symbols)
|
1062
|
+
name = None
|
1063
|
+
name, params = self.handle_option_and_params(params, 'watchTradesForSymbols', 'name', 'trade')
|
1064
|
+
params = self.omit(params, 'callerMethodName')
|
1065
|
+
firstMarket = self.market(symbols[0])
|
1066
|
+
type = firstMarket['type']
|
1067
|
+
if firstMarket['contract']:
|
1068
|
+
type = 'future' if firstMarket['linear'] else 'delivery'
|
1069
|
+
subMessageHashes = []
|
1070
|
+
subParams = []
|
1071
|
+
messageHashes = []
|
1072
|
+
for i in range(0, len(symbols)):
|
1073
|
+
symbol = symbols[i]
|
1074
|
+
market = self.market(symbol)
|
1075
|
+
subMessageHashes.append('trade::' + symbol)
|
1076
|
+
messageHashes.append('unsubscribe:trade:' + symbol)
|
1077
|
+
rawHash = market['lowercaseId'] + '@' + name
|
1078
|
+
subParams.append(rawHash)
|
1079
|
+
query = self.omit(params, 'type')
|
1080
|
+
subParamsLength = len(subParams)
|
1081
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, streamHash, subParamsLength)
|
1082
|
+
requestId = self.request_id(url)
|
1083
|
+
request: dict = {
|
1084
|
+
'method': 'UNSUBSCRIBE',
|
1085
|
+
'params': subParams,
|
1086
|
+
'id': requestId,
|
1087
|
+
}
|
1088
|
+
subscription: dict = {
|
1089
|
+
'unsubscribe': True,
|
1090
|
+
'id': str(requestId),
|
1091
|
+
'subMessageHashes': subMessageHashes,
|
1092
|
+
'messageHashes': messageHashes,
|
1093
|
+
'symbols': symbols,
|
1094
|
+
'topic': 'trades',
|
1095
|
+
}
|
1096
|
+
return await self.watch_multiple(url, messageHashes, self.extend(request, query), messageHashes, subscription)
|
1097
|
+
|
1098
|
+
async def un_watch_trades(self, symbol: str, params={}) -> Any:
|
1099
|
+
"""
|
1100
|
+
unsubscribes from the trades channel
|
1101
|
+
|
1102
|
+
https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams
|
1103
|
+
https://binance-docs.github.io/apidocs/spot/en/#trade-streams
|
1104
|
+
https://binance-docs.github.io/apidocs/futures/en/#aggregate-trade-streams
|
1105
|
+
https://binance-docs.github.io/apidocs/delivery/en/#aggregate-trade-streams
|
1106
|
+
|
1107
|
+
:param str symbol: unified symbol of the market to fetch trades for
|
1108
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1109
|
+
:param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
|
1110
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
1111
|
+
"""
|
1112
|
+
await self.load_markets()
|
1113
|
+
return await self.un_watch_trades_for_symbols([symbol], params)
|
1114
|
+
|
491
1115
|
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
492
1116
|
"""
|
493
1117
|
get the list of most recent trades for a particular symbol
|
1118
|
+
|
1119
|
+
https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams
|
1120
|
+
https://binance-docs.github.io/apidocs/spot/en/#trade-streams
|
1121
|
+
https://binance-docs.github.io/apidocs/futures/en/#aggregate-trade-streams
|
1122
|
+
https://binance-docs.github.io/apidocs/delivery/en/#aggregate-trade-streams
|
1123
|
+
|
494
1124
|
:param str symbol: unified symbol of the market to fetch trades for
|
495
1125
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
496
1126
|
:param int [limit]: the maximum amount of trades to fetch
|
497
1127
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1128
|
+
:param str [params.name]: the name of the method to call, 'trade' or 'aggTrade', default is 'trade'
|
498
1129
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
|
499
1130
|
"""
|
1131
|
+
params['callerMethodName'] = 'watchTrades'
|
500
1132
|
return await self.watch_trades_for_symbols([symbol], since, limit, params)
|
501
1133
|
|
502
1134
|
def parse_ws_trade(self, trade, market=None) -> Trade:
|
@@ -662,9 +1294,7 @@ class binance(ccxt.async_support.binance):
|
|
662
1294
|
marketId = self.safe_string(message, 's')
|
663
1295
|
market = self.safe_market(marketId, None, None, marketType)
|
664
1296
|
symbol = market['symbol']
|
665
|
-
|
666
|
-
event = self.safe_string(message, 'e')
|
667
|
-
messageHash = lowerCaseId + '@' + event
|
1297
|
+
messageHash = 'trade::' + symbol
|
668
1298
|
trade = self.parse_ws_trade(message, market)
|
669
1299
|
tradesArray = self.safe_value(self.trades, symbol)
|
670
1300
|
if tradesArray is None:
|
@@ -677,44 +1307,171 @@ class binance(ccxt.async_support.binance):
|
|
677
1307
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
678
1308
|
"""
|
679
1309
|
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
1310
|
+
|
1311
|
+
https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
1312
|
+
https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
|
1313
|
+
https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
|
1314
|
+
|
680
1315
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
681
1316
|
:param str timeframe: the length of time each candle represents
|
682
1317
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
683
1318
|
:param int [limit]: the maximum amount of candles to fetch
|
684
1319
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1320
|
+
:param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
|
685
1321
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
686
1322
|
"""
|
687
1323
|
await self.load_markets()
|
688
1324
|
market = self.market(symbol)
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
1325
|
+
symbol = market['symbol']
|
1326
|
+
params['callerMethodName'] = 'watchOHLCV'
|
1327
|
+
result = await self.watch_ohlcv_for_symbols([[symbol, timeframe]], since, limit, params)
|
1328
|
+
return result[symbol][timeframe]
|
1329
|
+
|
1330
|
+
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
|
1331
|
+
"""
|
1332
|
+
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
1333
|
+
|
1334
|
+
https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
1335
|
+
https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
|
1336
|
+
https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
|
1337
|
+
|
1338
|
+
:param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
1339
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1340
|
+
:param int [limit]: the maximum amount of candles to fetch
|
1341
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1342
|
+
:param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
|
1343
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1344
|
+
"""
|
1345
|
+
await self.load_markets()
|
1346
|
+
klineType = None
|
1347
|
+
klineType, params = self.handle_param_string_2(params, 'channel', 'name', 'kline')
|
1348
|
+
symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
|
1349
|
+
marketSymbols = self.market_symbols(symbols, None, False, False, True)
|
1350
|
+
firstMarket = self.market(marketSymbols[0])
|
1351
|
+
type = firstMarket['type']
|
1352
|
+
if firstMarket['contract']:
|
1353
|
+
type = 'future' if firstMarket['linear'] else 'delivery'
|
1354
|
+
isSpot = (type == 'spot')
|
1355
|
+
timezone = None
|
1356
|
+
timezone, params = self.handle_param_string(params, 'timezone', None)
|
1357
|
+
isUtc8 = (timezone is not None) and ((timezone == '+08:00') or Precise.string_eq(timezone, '8'))
|
1358
|
+
rawHashes = []
|
1359
|
+
messageHashes = []
|
1360
|
+
for i in range(0, len(symbolsAndTimeframes)):
|
1361
|
+
symAndTf = symbolsAndTimeframes[i]
|
1362
|
+
symbolString = symAndTf[0]
|
1363
|
+
timeframeString = symAndTf[1]
|
1364
|
+
interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
|
1365
|
+
market = self.market(symbolString)
|
1366
|
+
marketId = market['lowercaseId']
|
1367
|
+
if klineType == 'indexPriceKline':
|
1368
|
+
# weird behavior for index price kline we can't use the perp suffix
|
1369
|
+
marketId = marketId.replace('_perp', '')
|
1370
|
+
shouldUseUTC8 = (isUtc8 and isSpot)
|
1371
|
+
suffix = '@+08:00'
|
1372
|
+
utcSuffix = suffix if shouldUseUTC8 else ''
|
1373
|
+
rawHashes.append(marketId + '@' + klineType + '_' + interval + utcSuffix)
|
1374
|
+
messageHashes.append('ohlcv::' + market['symbol'] + '::' + timeframeString)
|
1375
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
|
703
1376
|
requestId = self.request_id(url)
|
704
1377
|
request = {
|
705
1378
|
'method': 'SUBSCRIBE',
|
706
|
-
'params':
|
707
|
-
messageHash,
|
708
|
-
],
|
1379
|
+
'params': rawHashes,
|
709
1380
|
'id': requestId,
|
710
1381
|
}
|
711
1382
|
subscribe = {
|
712
1383
|
'id': requestId,
|
713
1384
|
}
|
714
|
-
|
1385
|
+
params = self.omit(params, 'callerMethodName')
|
1386
|
+
symbol, timeframe, candles = await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscribe)
|
715
1387
|
if self.newUpdates:
|
716
|
-
limit =
|
717
|
-
|
1388
|
+
limit = candles.getLimit(symbol, limit)
|
1389
|
+
filtered = self.filter_by_since_limit(candles, since, limit, 0, True)
|
1390
|
+
return self.create_ohlcv_object(symbol, timeframe, filtered)
|
1391
|
+
|
1392
|
+
async def un_watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], params={}) -> Any:
|
1393
|
+
"""
|
1394
|
+
unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
1395
|
+
|
1396
|
+
https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
1397
|
+
https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
|
1398
|
+
https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
|
1399
|
+
|
1400
|
+
:param str[][] symbolsAndTimeframes: array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
|
1401
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1402
|
+
:param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
|
1403
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1404
|
+
"""
|
1405
|
+
await self.load_markets()
|
1406
|
+
klineType = None
|
1407
|
+
klineType, params = self.handle_param_string_2(params, 'channel', 'name', 'kline')
|
1408
|
+
symbols = self.get_list_from_object_values(symbolsAndTimeframes, 0)
|
1409
|
+
marketSymbols = self.market_symbols(symbols, None, False, False, True)
|
1410
|
+
firstMarket = self.market(marketSymbols[0])
|
1411
|
+
type = firstMarket['type']
|
1412
|
+
if firstMarket['contract']:
|
1413
|
+
type = 'future' if firstMarket['linear'] else 'delivery'
|
1414
|
+
isSpot = (type == 'spot')
|
1415
|
+
timezone = None
|
1416
|
+
timezone, params = self.handle_param_string(params, 'timezone', None)
|
1417
|
+
isUtc8 = (timezone is not None) and ((timezone == '+08:00') or Precise.string_eq(timezone, '8'))
|
1418
|
+
rawHashes = []
|
1419
|
+
subMessageHashes = []
|
1420
|
+
messageHashes = []
|
1421
|
+
for i in range(0, len(symbolsAndTimeframes)):
|
1422
|
+
symAndTf = symbolsAndTimeframes[i]
|
1423
|
+
symbolString = symAndTf[0]
|
1424
|
+
timeframeString = symAndTf[1]
|
1425
|
+
interval = self.safe_string(self.timeframes, timeframeString, timeframeString)
|
1426
|
+
market = self.market(symbolString)
|
1427
|
+
marketId = market['lowercaseId']
|
1428
|
+
if klineType == 'indexPriceKline':
|
1429
|
+
# weird behavior for index price kline we can't use the perp suffix
|
1430
|
+
marketId = marketId.replace('_perp', '')
|
1431
|
+
shouldUseUTC8 = (isUtc8 and isSpot)
|
1432
|
+
suffix = '@+08:00'
|
1433
|
+
utcSuffix = suffix if shouldUseUTC8 else ''
|
1434
|
+
rawHashes.append(marketId + '@' + klineType + '_' + interval + utcSuffix)
|
1435
|
+
subMessageHashes.append('ohlcv::' + market['symbol'] + '::' + timeframeString)
|
1436
|
+
messageHashes.append('unsubscribe::ohlcv::' + market['symbol'] + '::' + timeframeString)
|
1437
|
+
url = self.urls['api']['ws'][type] + '/' + self.stream(type, 'multipleOHLCV')
|
1438
|
+
requestId = self.request_id(url)
|
1439
|
+
request = {
|
1440
|
+
'method': 'UNSUBSCRIBE',
|
1441
|
+
'params': rawHashes,
|
1442
|
+
'id': requestId,
|
1443
|
+
}
|
1444
|
+
subscribe = {
|
1445
|
+
'unsubscribe': True,
|
1446
|
+
'id': str(requestId),
|
1447
|
+
'symbols': symbols,
|
1448
|
+
'symbolsAndTimeframes': symbolsAndTimeframes,
|
1449
|
+
'subMessageHashes': subMessageHashes,
|
1450
|
+
'messageHashes': messageHashes,
|
1451
|
+
'topic': 'ohlcv',
|
1452
|
+
}
|
1453
|
+
params = self.omit(params, 'callerMethodName')
|
1454
|
+
return await self.watch_multiple(url, messageHashes, self.extend(request, params), messageHashes, subscribe)
|
1455
|
+
|
1456
|
+
async def un_watch_ohlcv(self, symbol: str, timeframe='1m', params={}) -> Any:
|
1457
|
+
"""
|
1458
|
+
unWatches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
1459
|
+
|
1460
|
+
https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
1461
|
+
https://binance-docs.github.io/apidocs/futures/en/#kline-candlestick-data
|
1462
|
+
https://binance-docs.github.io/apidocs/delivery/en/#kline-candlestick-data
|
1463
|
+
|
1464
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
1465
|
+
:param str timeframe: the length of time each candle represents
|
1466
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1467
|
+
:param dict [params.timezone]: if provided, kline intervals are interpreted in that timezone instead of UTC, example '+08:00'
|
1468
|
+
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
1469
|
+
"""
|
1470
|
+
await self.load_markets()
|
1471
|
+
market = self.market(symbol)
|
1472
|
+
symbol = market['symbol']
|
1473
|
+
params['callerMethodName'] = 'watchOHLCV'
|
1474
|
+
return await self.un_watch_ohlcv_for_symbols([[symbol, timeframe]], params)
|
718
1475
|
|
719
1476
|
def handle_ohlcv(self, client: Client, message):
|
720
1477
|
#
|
@@ -744,7 +1501,7 @@ class binance(ccxt.async_support.binance):
|
|
744
1501
|
# }
|
745
1502
|
#
|
746
1503
|
event = self.safe_string(message, 'e')
|
747
|
-
eventMap = {
|
1504
|
+
eventMap: dict = {
|
748
1505
|
'indexPrice_kline': 'indexPriceKline',
|
749
1506
|
'markPrice_kline': 'markPriceKline',
|
750
1507
|
}
|
@@ -754,11 +1511,9 @@ class binance(ccxt.async_support.binance):
|
|
754
1511
|
if event == 'indexPriceKline':
|
755
1512
|
# indexPriceKline doesn't have the _PERP suffix
|
756
1513
|
marketId = self.safe_string(message, 'ps')
|
757
|
-
lowercaseMarketId = marketId.lower()
|
758
1514
|
interval = self.safe_string(kline, 'i')
|
759
1515
|
# use a reverse lookup in a static map instead
|
760
|
-
|
761
|
-
messageHash = lowercaseMarketId + '@' + event + '_' + interval
|
1516
|
+
unifiedTimeframe = self.find_timeframe(interval)
|
762
1517
|
parsed = [
|
763
1518
|
self.safe_integer(kline, 't'),
|
764
1519
|
self.safe_float(kline, 'o'),
|
@@ -770,38 +1525,82 @@ class binance(ccxt.async_support.binance):
|
|
770
1525
|
isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
|
771
1526
|
marketType = 'spot' if (isSpot) else 'contract'
|
772
1527
|
symbol = self.safe_symbol(marketId, None, None, marketType)
|
1528
|
+
messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe
|
773
1529
|
self.ohlcvs[symbol] = self.safe_value(self.ohlcvs, symbol, {})
|
774
|
-
stored = self.safe_value(self.ohlcvs[symbol],
|
1530
|
+
stored = self.safe_value(self.ohlcvs[symbol], unifiedTimeframe)
|
775
1531
|
if stored is None:
|
776
1532
|
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
|
777
1533
|
stored = ArrayCacheByTimestamp(limit)
|
778
|
-
self.ohlcvs[symbol][
|
1534
|
+
self.ohlcvs[symbol][unifiedTimeframe] = stored
|
779
1535
|
stored.append(parsed)
|
780
|
-
|
1536
|
+
resolveData = [symbol, unifiedTimeframe, stored]
|
1537
|
+
client.resolve(resolveData, messageHash)
|
1538
|
+
|
1539
|
+
async def fetch_ticker_ws(self, symbol: str, params={}) -> Ticker:
|
1540
|
+
"""
|
1541
|
+
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
1542
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
1543
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1544
|
+
:param str [params.method]: method to use can be ticker.price or ticker.book
|
1545
|
+
:param boolean [params.returnRateLimits]: return the rate limits for the exchange
|
1546
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1547
|
+
"""
|
1548
|
+
await self.load_markets()
|
1549
|
+
market = self.market(symbol)
|
1550
|
+
payload: dict = {
|
1551
|
+
'symbol': market['id'],
|
1552
|
+
}
|
1553
|
+
type = self.get_market_type('fetchTickerWs', market, params)
|
1554
|
+
if type != 'future':
|
1555
|
+
raise BadRequest(self.id + ' fetchTickerWs only supports swap markets')
|
1556
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1557
|
+
requestId = self.request_id(url)
|
1558
|
+
messageHash = str(requestId)
|
1559
|
+
subscription: dict = {
|
1560
|
+
'method': self.handle_ticker_ws,
|
1561
|
+
}
|
1562
|
+
returnRateLimits = False
|
1563
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'fetchTickerWs', 'returnRateLimits', False)
|
1564
|
+
payload['returnRateLimits'] = returnRateLimits
|
1565
|
+
params = self.omit(params, 'test')
|
1566
|
+
method = None
|
1567
|
+
method, params = self.handle_option_and_params(params, 'fetchTickerWs', 'method', 'ticker.book')
|
1568
|
+
message: dict = {
|
1569
|
+
'id': messageHash,
|
1570
|
+
'method': method,
|
1571
|
+
'params': self.sign_params(self.extend(payload, params)),
|
1572
|
+
}
|
1573
|
+
ticker = await self.watch(url, messageHash, message, messageHash, subscription)
|
1574
|
+
return ticker
|
781
1575
|
|
782
1576
|
async def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
783
1577
|
"""
|
784
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#klines
|
785
1578
|
query historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
1579
|
+
|
1580
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#klines
|
1581
|
+
|
786
1582
|
:param str symbol: unified symbol of the market to query OHLCV data for
|
787
1583
|
:param str timeframe: the length of time each candle represents
|
788
1584
|
:param int since: timestamp in ms of the earliest candle to fetch
|
789
1585
|
:param int limit: the maximum amount of candles to fetch
|
790
1586
|
:param dict params: extra parameters specific to the exchange API endpoint
|
791
1587
|
:param int params['until']: timestamp in ms of the earliest candle to fetch
|
792
|
-
|
793
|
-
|
1588
|
+
|
1589
|
+
EXCHANGE SPECIFIC PARAMETERS
|
794
1590
|
:param str params['timeZone']: default=0(UTC)
|
795
1591
|
:returns int[][]: A list of candles ordered, open, high, low, close, volume
|
796
1592
|
"""
|
797
1593
|
await self.load_markets()
|
798
|
-
self.
|
799
|
-
|
1594
|
+
market = self.market(symbol)
|
1595
|
+
marketType = self.get_market_type('fetchOHLCVWs', market, params)
|
1596
|
+
if marketType != 'spot' and marketType != 'future':
|
1597
|
+
raise BadRequest(self.id + ' fetchOHLCVWs only supports spot or swap markets')
|
1598
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
800
1599
|
requestId = self.request_id(url)
|
801
1600
|
messageHash = str(requestId)
|
802
1601
|
returnRateLimits = False
|
803
1602
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchOHLCVWs', 'returnRateLimits', False)
|
804
|
-
payload = {
|
1603
|
+
payload: dict = {
|
805
1604
|
'symbol': self.market_id(symbol),
|
806
1605
|
'returnRateLimits': returnRateLimits,
|
807
1606
|
'interval': self.timeframes[timeframe],
|
@@ -814,12 +1613,12 @@ class binance(ccxt.async_support.binance):
|
|
814
1613
|
payload['limit'] = limit
|
815
1614
|
if until is not None:
|
816
1615
|
payload['endTime'] = until
|
817
|
-
message = {
|
1616
|
+
message: dict = {
|
818
1617
|
'id': messageHash,
|
819
1618
|
'method': 'klines',
|
820
1619
|
'params': self.extend(payload, params),
|
821
1620
|
}
|
822
|
-
subscription = {
|
1621
|
+
subscription: dict = {
|
823
1622
|
'method': self.handle_fetch_ohlcv,
|
824
1623
|
}
|
825
1624
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
@@ -864,92 +1663,281 @@ class binance(ccxt.async_support.binance):
|
|
864
1663
|
|
865
1664
|
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
|
866
1665
|
"""
|
1666
|
+
|
1667
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-mini-ticker-stream
|
1668
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-ticker-streams
|
1669
|
+
https://binance-docs.github.io/apidocs/futures/en/#all-market-mini-tickers-stream
|
1670
|
+
https://binance-docs.github.io/apidocs/futures/en/#individual-symbol-ticker-streams
|
1671
|
+
https://binance-docs.github.io/apidocs/delivery/en/#all-market-mini-tickers-stream
|
1672
|
+
https://binance-docs.github.io/apidocs/delivery/en/#individual-symbol-ticker-streams
|
1673
|
+
|
867
1674
|
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
868
1675
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
869
1676
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
870
|
-
:param str [params.name]: stream to use can be ticker or
|
1677
|
+
:param str [params.name]: stream to use can be ticker or miniTicker
|
871
1678
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
872
1679
|
"""
|
873
1680
|
await self.load_markets()
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
1681
|
+
symbol = self.symbol(symbol)
|
1682
|
+
tickers = await self.watch_tickers([symbol], self.extend(params, {'callerMethodName': 'watchTicker'}))
|
1683
|
+
return tickers[symbol]
|
1684
|
+
|
1685
|
+
async def watch_mark_price(self, symbol: str, params={}) -> Ticker:
|
1686
|
+
"""
|
1687
|
+
|
1688
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream
|
1689
|
+
|
1690
|
+
watches a mark price for a specific market
|
1691
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
1692
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1693
|
+
:param boolean [params.use1sFreq]: *default is True* if set to True, the mark price will be updated every second, otherwise every 3 seconds
|
1694
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1695
|
+
"""
|
1696
|
+
await self.load_markets()
|
1697
|
+
symbol = self.symbol(symbol)
|
1698
|
+
tickers = await self.watch_mark_prices([symbol], self.extend(params, {'callerMethodName': 'watchMarkPrice'}))
|
1699
|
+
return tickers[symbol]
|
1700
|
+
|
1701
|
+
async def watch_mark_prices(self, symbols: Strings = None, params={}) -> Tickers:
|
1702
|
+
"""
|
1703
|
+
|
1704
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream-for-All-market
|
1705
|
+
|
1706
|
+
watches the mark price for all markets
|
1707
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
1708
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1709
|
+
:param boolean [params.use1sFreq]: *default is True* if set to True, the mark price will be updated every second, otherwise every 3 seconds
|
1710
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1711
|
+
"""
|
1712
|
+
channelName = None
|
1713
|
+
# for now watchmarkPrice uses the same messageHash
|
1714
|
+
# so it's impossible to watch both at the same time
|
1715
|
+
# refactor self to use different messageHashes
|
1716
|
+
channelName, params = self.handle_option_and_params(params, 'watchMarkPrices', 'name', 'markPrice')
|
1717
|
+
newTickers = await self.watch_multi_ticker_helper('watchMarkPrices', channelName, symbols, params)
|
1718
|
+
if self.newUpdates:
|
1719
|
+
return newTickers
|
1720
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
1721
|
+
|
1722
|
+
async def watch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
1723
|
+
"""
|
1724
|
+
|
1725
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-mini-ticker-stream
|
1726
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-ticker-streams
|
1727
|
+
https://binance-docs.github.io/apidocs/futures/en/#all-market-mini-tickers-stream
|
1728
|
+
https://binance-docs.github.io/apidocs/futures/en/#individual-symbol-ticker-streams
|
1729
|
+
https://binance-docs.github.io/apidocs/delivery/en/#all-market-mini-tickers-stream
|
1730
|
+
https://binance-docs.github.io/apidocs/delivery/en/#individual-symbol-ticker-streams
|
1731
|
+
|
1732
|
+
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
1733
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
1734
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1735
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1736
|
+
"""
|
1737
|
+
channelName = None
|
1738
|
+
channelName, params = self.handle_option_and_params(params, 'watchTickers', 'name', 'ticker')
|
1739
|
+
if channelName == 'bookTicker':
|
1740
|
+
raise BadRequest(self.id + ' deprecation notice - to subscribe for bids-asks, use watch_bids_asks() method instead')
|
1741
|
+
newTickers = await self.watch_multi_ticker_helper('watchTickers', channelName, symbols, params)
|
1742
|
+
if self.newUpdates:
|
1743
|
+
return newTickers
|
1744
|
+
return self.filter_by_array(self.tickers, 'symbol', symbols)
|
1745
|
+
|
1746
|
+
async def un_watch_tickers(self, symbols: Strings = None, params={}) -> Any:
|
1747
|
+
"""
|
1748
|
+
|
1749
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-mini-ticker-stream
|
1750
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-ticker-streams
|
1751
|
+
https://binance-docs.github.io/apidocs/futures/en/#all-market-mini-tickers-stream
|
1752
|
+
https://binance-docs.github.io/apidocs/futures/en/#individual-symbol-ticker-streams
|
1753
|
+
https://binance-docs.github.io/apidocs/delivery/en/#all-market-mini-tickers-stream
|
1754
|
+
https://binance-docs.github.io/apidocs/delivery/en/#individual-symbol-ticker-streams
|
1755
|
+
|
1756
|
+
unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
1757
|
+
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
1758
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1759
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1760
|
+
"""
|
1761
|
+
channelName = None
|
1762
|
+
channelName, params = self.handle_option_and_params(params, 'watchTickers', 'name', 'ticker')
|
1763
|
+
if channelName == 'bookTicker':
|
1764
|
+
raise BadRequest(self.id + ' deprecation notice - to subscribe for bids-asks, use watch_bids_asks() method instead')
|
1765
|
+
await self.load_markets()
|
1766
|
+
methodName = 'watchTickers'
|
1767
|
+
symbols = self.market_symbols(symbols, None, True, False, True)
|
1768
|
+
firstMarket = None
|
1769
|
+
marketType = None
|
1770
|
+
symbolsDefined = (symbols is not None)
|
1771
|
+
if symbolsDefined:
|
1772
|
+
firstMarket = self.market(symbols[0])
|
1773
|
+
marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params)
|
1774
|
+
subType = None
|
1775
|
+
subType, params = self.handle_sub_type_and_params(methodName, firstMarket, params)
|
1776
|
+
rawMarketType = None
|
1777
|
+
if self.isLinear(marketType, subType):
|
1778
|
+
rawMarketType = 'future'
|
1779
|
+
elif self.isInverse(marketType, subType):
|
1780
|
+
rawMarketType = 'delivery'
|
1781
|
+
elif marketType == 'spot':
|
1782
|
+
rawMarketType = marketType
|
1783
|
+
else:
|
1784
|
+
raise NotSupported(self.id + ' ' + methodName + '() does not support options markets')
|
1785
|
+
isBidAsk = (channelName == 'bookTicker')
|
1786
|
+
subscriptionArgs = []
|
1787
|
+
subMessageHashes = []
|
1788
|
+
messageHashes = []
|
1789
|
+
if symbolsDefined:
|
1790
|
+
for i in range(0, len(symbols)):
|
1791
|
+
symbol = symbols[i]
|
1792
|
+
market = self.market(symbol)
|
1793
|
+
subscriptionArgs.append(market['lowercaseId'] + '@' + channelName)
|
1794
|
+
subMessageHashes.append(self.get_message_hash(channelName, market['symbol'], isBidAsk))
|
1795
|
+
messageHashes.append('unsubscribe:ticker:' + symbol)
|
1796
|
+
else:
|
1797
|
+
if isBidAsk:
|
1798
|
+
if marketType == 'spot':
|
1799
|
+
raise ArgumentsRequired(self.id + ' ' + methodName + '() requires symbols for self channel for spot markets')
|
1800
|
+
subscriptionArgs.append('!' + channelName)
|
1801
|
+
else:
|
1802
|
+
subscriptionArgs.append('!' + channelName + '@arr')
|
1803
|
+
subMessageHashes.append(self.get_message_hash(channelName, None, isBidAsk))
|
1804
|
+
messageHashes.append('unsubscribe:ticker')
|
1805
|
+
streamHash = channelName
|
1806
|
+
if symbolsDefined:
|
1807
|
+
streamHash = channelName + '::' + ','.join(symbols)
|
1808
|
+
url = self.urls['api']['ws'][rawMarketType] + '/' + self.stream(rawMarketType, streamHash)
|
885
1809
|
requestId = self.request_id(url)
|
886
|
-
request = {
|
887
|
-
'method': '
|
888
|
-
'params':
|
889
|
-
messageHash,
|
890
|
-
],
|
1810
|
+
request: dict = {
|
1811
|
+
'method': 'UNSUBSCRIBE',
|
1812
|
+
'params': subscriptionArgs,
|
891
1813
|
'id': requestId,
|
892
1814
|
}
|
893
|
-
|
894
|
-
'
|
1815
|
+
subscription: dict = {
|
1816
|
+
'unsubscribe': True,
|
1817
|
+
'id': str(requestId),
|
1818
|
+
'subMessageHashes': subMessageHashes,
|
1819
|
+
'messageHashes': subMessageHashes,
|
1820
|
+
'symbols': symbols,
|
1821
|
+
'topic': 'ticker',
|
895
1822
|
}
|
896
|
-
return await self.
|
1823
|
+
return await self.watch_multiple(url, subMessageHashes, self.extend(request, params), subMessageHashes, subscription)
|
897
1824
|
|
898
|
-
async def
|
1825
|
+
async def un_watch_ticker(self, symbol: str, params={}) -> Any:
|
899
1826
|
"""
|
900
|
-
|
1827
|
+
|
1828
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-mini-ticker-stream
|
1829
|
+
https://binance-docs.github.io/apidocs/spot/en/#individual-symbol-ticker-streams
|
1830
|
+
https://binance-docs.github.io/apidocs/futures/en/#all-market-mini-tickers-stream
|
1831
|
+
https://binance-docs.github.io/apidocs/futures/en/#individual-symbol-ticker-streams
|
1832
|
+
https://binance-docs.github.io/apidocs/delivery/en/#all-market-mini-tickers-stream
|
1833
|
+
https://binance-docs.github.io/apidocs/delivery/en/#individual-symbol-ticker-streams
|
1834
|
+
|
1835
|
+
unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
|
1836
|
+
:param str symbol: unified symbol of the market to fetch the ticker for
|
1837
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1838
|
+
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
1839
|
+
"""
|
1840
|
+
return await self.un_watch_tickers([symbol], params)
|
1841
|
+
|
1842
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
1843
|
+
"""
|
1844
|
+
watches best bid & ask for symbols
|
1845
|
+
|
1846
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#symbol-order-book-ticker
|
1847
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Book-Tickers-Stream
|
1848
|
+
https://developers.binance.com/docs/derivatives/coin-margined-futures/websocket-market-streams/All-Book-Tickers-Stream
|
1849
|
+
|
901
1850
|
:param str[] symbols: unified symbol of the market to fetch the ticker for
|
902
1851
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
903
1852
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
904
1853
|
"""
|
905
1854
|
await self.load_markets()
|
906
|
-
symbols = self.market_symbols(symbols, None, True,
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
1855
|
+
symbols = self.market_symbols(symbols, None, True, False, True)
|
1856
|
+
result = await self.watch_multi_ticker_helper('watchBidsAsks', 'bookTicker', symbols, params)
|
1857
|
+
if self.newUpdates:
|
1858
|
+
return result
|
1859
|
+
return self.filter_by_array(self.bidsasks, 'symbol', symbols)
|
1860
|
+
|
1861
|
+
async def watch_multi_ticker_helper(self, methodName, channelName: str, symbols: Strings = None, params={}):
|
1862
|
+
await self.load_markets()
|
1863
|
+
symbols = self.market_symbols(symbols, None, True, False, True)
|
1864
|
+
isBidAsk = (channelName == 'bookTicker')
|
1865
|
+
isMarkPrice = (channelName == 'markPrice')
|
1866
|
+
use1sFreq = self.safe_bool(params, 'use1sFreq', True)
|
1867
|
+
firstMarket = None
|
1868
|
+
marketType = None
|
1869
|
+
symbolsDefined = (symbols is not None)
|
1870
|
+
if symbolsDefined:
|
1871
|
+
firstMarket = self.market(symbols[0])
|
1872
|
+
defaultMarket = 'swap' if (isMarkPrice) else None
|
1873
|
+
marketType, params = self.handle_market_type_and_params(methodName, firstMarket, params, defaultMarket)
|
913
1874
|
subType = None
|
914
|
-
subType, params = self.handle_sub_type_and_params(
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
if
|
928
|
-
if
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
1875
|
+
subType, params = self.handle_sub_type_and_params(methodName, firstMarket, params)
|
1876
|
+
rawMarketType = None
|
1877
|
+
if self.isLinear(marketType, subType):
|
1878
|
+
rawMarketType = 'future'
|
1879
|
+
elif self.isInverse(marketType, subType):
|
1880
|
+
rawMarketType = 'delivery'
|
1881
|
+
elif marketType == 'spot':
|
1882
|
+
rawMarketType = marketType
|
1883
|
+
else:
|
1884
|
+
raise NotSupported(self.id + ' ' + methodName + '() does not support options markets')
|
1885
|
+
subscriptionArgs = []
|
1886
|
+
messageHashes = []
|
1887
|
+
suffix = ''
|
1888
|
+
if isMarkPrice:
|
1889
|
+
suffix = '@1s' if (use1sFreq) else ''
|
1890
|
+
if symbolsDefined:
|
1891
|
+
for i in range(0, len(symbols)):
|
1892
|
+
symbol = symbols[i]
|
1893
|
+
market = self.market(symbol)
|
1894
|
+
subscriptionArgs.append(market['lowercaseId'] + '@' + channelName + suffix)
|
1895
|
+
messageHashes.append(self.get_message_hash(channelName, market['symbol'], isBidAsk))
|
933
1896
|
else:
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
1897
|
+
if isBidAsk:
|
1898
|
+
if marketType == 'spot':
|
1899
|
+
raise ArgumentsRequired(self.id + ' ' + methodName + '() requires symbols for self channel for spot markets')
|
1900
|
+
subscriptionArgs.append('!' + channelName)
|
1901
|
+
elif isMarkPrice:
|
1902
|
+
subscriptionArgs.append('!' + channelName + '@arr' + suffix)
|
1903
|
+
else:
|
1904
|
+
subscriptionArgs.append('!' + channelName + '@arr')
|
1905
|
+
messageHashes.append(self.get_message_hash(channelName, None, isBidAsk))
|
1906
|
+
streamHash = channelName
|
1907
|
+
if symbolsDefined:
|
1908
|
+
streamHash = channelName + '::' + ','.join(symbols)
|
1909
|
+
url = self.urls['api']['ws'][rawMarketType] + '/' + self.stream(rawMarketType, streamHash)
|
938
1910
|
requestId = self.request_id(url)
|
939
|
-
request = {
|
1911
|
+
request: dict = {
|
940
1912
|
'method': 'SUBSCRIBE',
|
941
|
-
'params':
|
1913
|
+
'params': subscriptionArgs,
|
942
1914
|
'id': requestId,
|
943
1915
|
}
|
944
|
-
subscribe = {
|
1916
|
+
subscribe: dict = {
|
945
1917
|
'id': requestId,
|
946
1918
|
}
|
947
|
-
|
948
|
-
if
|
949
|
-
|
950
|
-
|
1919
|
+
result = await self.watch_multiple(url, messageHashes, self.deep_extend(request, params), subscriptionArgs, subscribe)
|
1920
|
+
# for efficiency, we have two type of returned structure here - if symbols array was provided, then individual
|
1921
|
+
# ticker dict comes in, otherwise all-tickers dict comes in
|
1922
|
+
if not symbolsDefined:
|
1923
|
+
return result
|
1924
|
+
else:
|
1925
|
+
newDict: dict = {}
|
1926
|
+
newDict[result['symbol']] = result
|
1927
|
+
return newDict
|
951
1928
|
|
952
1929
|
def parse_ws_ticker(self, message, marketType):
|
1930
|
+
# markPrice
|
1931
|
+
# {
|
1932
|
+
# "e": "markPriceUpdate", # Event type
|
1933
|
+
# "E": 1562305380000, # Event time
|
1934
|
+
# "s": "BTCUSDT", # Symbol
|
1935
|
+
# "p": "11794.15000000", # Mark price
|
1936
|
+
# "i": "11784.62659091", # Index price
|
1937
|
+
# "P": "11784.25641265", # Estimated Settle Price, only useful in the last hour before the settlement starts
|
1938
|
+
# "r": "0.00038167", # Funding rate
|
1939
|
+
# "T": 1562306400000 # Next funding time
|
1940
|
+
# }
|
953
1941
|
#
|
954
1942
|
# ticker
|
955
1943
|
# {
|
@@ -990,31 +1978,57 @@ class binance(ccxt.async_support.binance):
|
|
990
1978
|
# "v": "2109995.32000000",
|
991
1979
|
# "q": "2019254.05788000"
|
992
1980
|
# }
|
993
|
-
#
|
1981
|
+
# fetchTickerWs
|
1982
|
+
# {
|
1983
|
+
# "symbol":"BTCUSDT",
|
1984
|
+
# "price":"72606.70",
|
1985
|
+
# "time":1712526204284
|
1986
|
+
# }
|
1987
|
+
# fetchTickerWs - ticker.book
|
1988
|
+
# {
|
1989
|
+
# "lastUpdateId":1027024,
|
1990
|
+
# "symbol":"BTCUSDT",
|
1991
|
+
# "bidPrice":"4.00000000",
|
1992
|
+
# "bidQty":"431.00000000",
|
1993
|
+
# "askPrice":"4.00000200",
|
1994
|
+
# "askQty":"9.00000000",
|
1995
|
+
# "time":1589437530011,
|
1996
|
+
# }
|
1997
|
+
#
|
1998
|
+
marketId = self.safe_string_2(message, 's', 'symbol')
|
1999
|
+
symbol = self.safe_symbol(marketId, None, None, marketType)
|
994
2000
|
event = self.safe_string(message, 'e', 'bookTicker')
|
995
2001
|
if event == '24hrTicker':
|
996
2002
|
event = 'ticker'
|
2003
|
+
if event == 'markPriceUpdate':
|
2004
|
+
# handle self separately because some fields clash with the ticker fields
|
2005
|
+
return self.safe_ticker({
|
2006
|
+
'symbol': symbol,
|
2007
|
+
'timestamp': self.safe_integer(message, 'E'),
|
2008
|
+
'datetime': self.iso8601(self.safe_integer(message, 'E')),
|
2009
|
+
'info': message,
|
2010
|
+
'markPrice': self.safe_string(message, 'p'),
|
2011
|
+
'indexPrice': self.safe_string(message, 'i'),
|
2012
|
+
})
|
997
2013
|
timestamp = None
|
998
2014
|
if event == 'bookTicker':
|
999
2015
|
# take the event timestamp, if available, for spot tickers it is not
|
1000
|
-
timestamp = self.
|
2016
|
+
timestamp = self.safe_integer_2(message, 'E', 'time')
|
1001
2017
|
else:
|
1002
2018
|
# take the timestamp of the closing price for candlestick streams
|
1003
|
-
timestamp = self.
|
1004
|
-
marketId = self.safe_string(message, 's')
|
1005
|
-
symbol = self.safe_symbol(marketId, None, None, marketType)
|
2019
|
+
timestamp = self.safe_integer_n(message, ['C', 'E', 'time'])
|
1006
2020
|
market = self.safe_market(marketId, None, None, marketType)
|
1007
|
-
last = self.
|
2021
|
+
last = self.safe_string_2(message, 'c', 'price')
|
1008
2022
|
return self.safe_ticker({
|
1009
2023
|
'symbol': symbol,
|
1010
2024
|
'timestamp': timestamp,
|
1011
2025
|
'datetime': self.iso8601(timestamp),
|
1012
2026
|
'high': self.safe_string(message, 'h'),
|
1013
2027
|
'low': self.safe_string(message, 'l'),
|
1014
|
-
'bid': self.
|
1015
|
-
'bidVolume': self.
|
1016
|
-
'ask': self.
|
1017
|
-
'askVolume': self.
|
2028
|
+
'bid': self.safe_string_2(message, 'b', 'bidPrice'),
|
2029
|
+
'bidVolume': self.safe_string_2(message, 'B', 'bidQty'),
|
2030
|
+
'ask': self.safe_string_2(message, 'a', 'askPrice'),
|
2031
|
+
'askVolume': self.safe_string_2(message, 'A', 'askQty'),
|
1018
2032
|
'vwap': self.safe_string(message, 'w'),
|
1019
2033
|
'open': self.safe_string(message, 'o'),
|
1020
2034
|
'close': last,
|
@@ -1028,11 +2042,56 @@ class binance(ccxt.async_support.binance):
|
|
1028
2042
|
'info': message,
|
1029
2043
|
}, market)
|
1030
2044
|
|
1031
|
-
def
|
2045
|
+
def handle_ticker_ws(self, client: Client, message):
|
2046
|
+
#
|
2047
|
+
# ticker.price
|
2048
|
+
# {
|
2049
|
+
# "id":"1",
|
2050
|
+
# "status":200,
|
2051
|
+
# "result":{
|
2052
|
+
# "symbol":"BTCUSDT",
|
2053
|
+
# "price":"73178.50",
|
2054
|
+
# "time":1712527052374
|
2055
|
+
# }
|
2056
|
+
# }
|
2057
|
+
# ticker.book
|
2058
|
+
# {
|
2059
|
+
# "id":"9d32157c-a556-4d27-9866-66760a174b57",
|
2060
|
+
# "status":200,
|
2061
|
+
# "result":{
|
2062
|
+
# "lastUpdateId":1027024,
|
2063
|
+
# "symbol":"BTCUSDT",
|
2064
|
+
# "bidPrice":"4.00000000",
|
2065
|
+
# "bidQty":"431.00000000",
|
2066
|
+
# "askPrice":"4.00000200",
|
2067
|
+
# "askQty":"9.00000000",
|
2068
|
+
# "time":1589437530011 # Transaction time
|
2069
|
+
# }
|
2070
|
+
# }
|
2071
|
+
#
|
2072
|
+
messageHash = self.safe_string(message, 'id')
|
2073
|
+
result = self.safe_value(message, 'result', {})
|
2074
|
+
ticker = self.parse_ws_ticker(result, 'future')
|
2075
|
+
client.resolve(ticker, messageHash)
|
2076
|
+
|
2077
|
+
def handle_bids_asks(self, client: Client, message):
|
2078
|
+
#
|
2079
|
+
# arrives one symbol dict or array of symbol dicts
|
2080
|
+
#
|
2081
|
+
# {
|
2082
|
+
# "u": 7488717758,
|
2083
|
+
# "s": "BTCUSDT",
|
2084
|
+
# "b": "28621.74000000",
|
2085
|
+
# "B": "1.43278800",
|
2086
|
+
# "a": "28621.75000000",
|
2087
|
+
# "A": "2.52500800"
|
2088
|
+
# }
|
2089
|
+
#
|
2090
|
+
self.handle_tickers_and_bids_asks(client, message, 'bidasks')
|
2091
|
+
|
2092
|
+
def handle_tickers(self, client: Client, message):
|
1032
2093
|
#
|
1033
|
-
#
|
1034
|
-
# These are NOT the statistics of the UTC day, but a 24hr rolling window for the previous 24hrs
|
1035
|
-
# Update Speed 1000ms
|
2094
|
+
# arrives one symbol dict or array of symbol dicts
|
1036
2095
|
#
|
1037
2096
|
# {
|
1038
2097
|
# "e": "24hrTicker", # event type
|
@@ -1060,58 +2119,50 @@ class binance(ccxt.async_support.binance):
|
|
1060
2119
|
# "n": 163222, # total number of trades
|
1061
2120
|
# }
|
1062
2121
|
#
|
1063
|
-
|
1064
|
-
if event == '24hrTicker':
|
1065
|
-
event = 'ticker'
|
1066
|
-
elif event == '24hrMiniTicker':
|
1067
|
-
event = 'miniTicker'
|
1068
|
-
wsMarketId = self.safe_string_lower(message, 's')
|
1069
|
-
messageHash = wsMarketId + '@' + event
|
1070
|
-
isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
|
1071
|
-
marketType = 'spot' if (isSpot) else 'contract'
|
1072
|
-
result = self.parse_ws_ticker(message, marketType)
|
1073
|
-
symbol = result['symbol']
|
1074
|
-
self.tickers[symbol] = result
|
1075
|
-
client.resolve(result, messageHash)
|
1076
|
-
if event == 'bookTicker':
|
1077
|
-
# watch bookTickers
|
1078
|
-
client.resolve(result, '!' + 'bookTicker@arr')
|
1079
|
-
messageHashes = self.find_message_hashes(client, 'tickers::')
|
1080
|
-
for i in range(0, len(messageHashes)):
|
1081
|
-
currentMessageHash = messageHashes[i]
|
1082
|
-
parts = currentMessageHash.split('::')
|
1083
|
-
symbolsString = parts[1]
|
1084
|
-
symbols = symbolsString.split(',')
|
1085
|
-
if self.in_array(symbol, symbols):
|
1086
|
-
client.resolve(result, currentMessageHash)
|
2122
|
+
self.handle_tickers_and_bids_asks(client, message, 'tickers')
|
1087
2123
|
|
1088
|
-
def
|
2124
|
+
def handle_tickers_and_bids_asks(self, client: Client, message, methodType):
|
1089
2125
|
isSpot = ((client.url.find('/stream') > -1) or (client.url.find('/testnet.binance') > -1))
|
1090
2126
|
marketType = 'spot' if (isSpot) else 'contract'
|
2127
|
+
isBidAsk = (methodType == 'bidasks')
|
2128
|
+
channelName = None
|
2129
|
+
resolvedMessageHashes = []
|
1091
2130
|
rawTickers = []
|
1092
|
-
newTickers = {}
|
2131
|
+
newTickers: dict = {}
|
1093
2132
|
if isinstance(message, list):
|
1094
2133
|
rawTickers = message
|
1095
2134
|
else:
|
1096
2135
|
rawTickers.append(message)
|
1097
2136
|
for i in range(0, len(rawTickers)):
|
1098
2137
|
ticker = rawTickers[i]
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
2138
|
+
event = self.safe_string(ticker, 'e')
|
2139
|
+
if isBidAsk:
|
2140
|
+
event = 'bookTicker' # in `handleMessage`, bookTicker doesn't have identifier, so manually set here
|
2141
|
+
channelName = self.safe_string(self.options['tickerChannelsMap'], event, event)
|
2142
|
+
if channelName is None:
|
2143
|
+
continue
|
2144
|
+
parsedTicker = self.parse_ws_ticker(ticker, marketType)
|
2145
|
+
symbol = parsedTicker['symbol']
|
2146
|
+
newTickers[symbol] = parsedTicker
|
2147
|
+
if isBidAsk:
|
2148
|
+
self.bidsasks[symbol] = parsedTicker
|
2149
|
+
else:
|
2150
|
+
self.tickers[symbol] = parsedTicker
|
2151
|
+
messageHash = self.get_message_hash(channelName, symbol, isBidAsk)
|
2152
|
+
resolvedMessageHashes.append(messageHash)
|
2153
|
+
client.resolve(parsedTicker, messageHash)
|
2154
|
+
# resolve batch endpoint
|
2155
|
+
length = len(resolvedMessageHashes)
|
2156
|
+
if length > 0:
|
2157
|
+
batchMessageHash = self.get_message_hash(channelName, None, isBidAsk)
|
2158
|
+
client.resolve(newTickers, batchMessageHash)
|
2159
|
+
|
2160
|
+
def get_message_hash(self, channelName: str, symbol: Str, isBidAsk: bool):
|
2161
|
+
prefix = 'bidask' if isBidAsk else 'ticker'
|
2162
|
+
if symbol is not None:
|
2163
|
+
return prefix + ':' + channelName + '@' + symbol
|
2164
|
+
else:
|
2165
|
+
return prefix + 's' + ':' + channelName
|
1115
2166
|
|
1116
2167
|
def sign_params(self, params={}):
|
1117
2168
|
self.check_required_credentials()
|
@@ -1201,7 +2252,7 @@ class binance(ccxt.async_support.binance):
|
|
1201
2252
|
if listenKey is None:
|
1202
2253
|
# A network error happened: we can't renew a listen key that does not exist.
|
1203
2254
|
return
|
1204
|
-
request = {}
|
2255
|
+
request: dict = {}
|
1205
2256
|
symbol = self.safe_string(params, 'symbol')
|
1206
2257
|
params = self.omit(params, ['type', 'symbol'])
|
1207
2258
|
time = self.milliseconds()
|
@@ -1264,7 +2315,7 @@ class binance(ccxt.async_support.binance):
|
|
1264
2315
|
self.balance[type] = {}
|
1265
2316
|
|
1266
2317
|
async def load_balance_snapshot(self, client, messageHash, type, isPortfolioMargin):
|
1267
|
-
params = {
|
2318
|
+
params: dict = {
|
1268
2319
|
'type': type,
|
1269
2320
|
}
|
1270
2321
|
if isPortfolioMargin:
|
@@ -1279,34 +2330,59 @@ class binance(ccxt.async_support.binance):
|
|
1279
2330
|
async def fetch_balance_ws(self, params={}) -> Balances:
|
1280
2331
|
"""
|
1281
2332
|
fetch balance and get the amount of funds available for trading or funds locked in orders
|
1282
|
-
|
2333
|
+
|
2334
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/account/websocket-api/Futures-Account-Balance
|
2335
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#account-information-user_data
|
2336
|
+
|
1283
2337
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1284
2338
|
:param str|None [params.type]: 'future', 'delivery', 'savings', 'funding', or 'spot'
|
1285
2339
|
:param str|None [params.marginMode]: 'cross' or 'isolated', for margin trading, uses self.options.defaultMarginMode if not passed, defaults to None/None/None
|
1286
2340
|
:param str[]|None [params.symbols]: unified market symbols, only used in isolated margin mode
|
2341
|
+
:param str|None [params.method]: method to use. Can be account.balance, account.status, v2/account.balance or v2/account.status
|
1287
2342
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
1288
2343
|
"""
|
1289
2344
|
await self.load_markets()
|
1290
|
-
|
2345
|
+
type = self.get_market_type('fetchBalanceWs', None, params)
|
2346
|
+
if type != 'spot' and type != 'future':
|
2347
|
+
raise BadRequest(self.id + ' fetchBalanceWs only supports spot or swap markets')
|
2348
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1291
2349
|
requestId = self.request_id(url)
|
1292
2350
|
messageHash = str(requestId)
|
1293
2351
|
returnRateLimits = False
|
1294
|
-
returnRateLimits, params = self.handle_option_and_params(params, '
|
1295
|
-
payload = {
|
2352
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'fetchBalanceWs', 'returnRateLimits', False)
|
2353
|
+
payload: dict = {
|
1296
2354
|
'returnRateLimits': returnRateLimits,
|
1297
2355
|
}
|
1298
|
-
|
2356
|
+
method = None
|
2357
|
+
method, params = self.handle_option_and_params(params, 'fetchBalanceWs', 'method', 'account.status')
|
2358
|
+
message: dict = {
|
1299
2359
|
'id': messageHash,
|
1300
|
-
'method':
|
2360
|
+
'method': method,
|
1301
2361
|
'params': self.sign_params(self.extend(payload, params)),
|
1302
2362
|
}
|
1303
|
-
subscription = {
|
1304
|
-
'method': self.handle_balance_ws,
|
2363
|
+
subscription: dict = {
|
2364
|
+
'method': self.handle_account_status_ws if (method == 'account.status') else self.handle_balance_ws,
|
1305
2365
|
}
|
1306
2366
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
1307
2367
|
|
1308
2368
|
def handle_balance_ws(self, client: Client, message):
|
1309
2369
|
#
|
2370
|
+
#
|
2371
|
+
messageHash = self.safe_string(message, 'id')
|
2372
|
+
rawBalance = None
|
2373
|
+
if isinstance(message['result'], list):
|
2374
|
+
# account.balance
|
2375
|
+
rawBalance = self.safe_list(message, 'result', [])
|
2376
|
+
else:
|
2377
|
+
# account.status
|
2378
|
+
result = self.safe_dict(message, 'result', {})
|
2379
|
+
rawBalance = self.safe_list(result, 'assets', [])
|
2380
|
+
parsedBalances = self.parseBalanceCustom(rawBalance)
|
2381
|
+
client.resolve(parsedBalances, messageHash)
|
2382
|
+
|
2383
|
+
def handle_account_status_ws(self, client: Client, message):
|
2384
|
+
#
|
2385
|
+
# spot
|
1310
2386
|
# {
|
1311
2387
|
# "id": "605a6d20-6588-4cb9-afa0-b0ab087507ba",
|
1312
2388
|
# "status": 200,
|
@@ -1349,12 +2425,104 @@ class binance(ccxt.async_support.binance):
|
|
1349
2425
|
# ]
|
1350
2426
|
# }
|
1351
2427
|
# }
|
2428
|
+
# swap
|
1352
2429
|
#
|
1353
2430
|
messageHash = self.safe_string(message, 'id')
|
1354
|
-
result = self.
|
1355
|
-
parsedBalances = self.
|
2431
|
+
result = self.safe_dict(message, 'result', {})
|
2432
|
+
parsedBalances = self.parseBalanceCustom(result)
|
1356
2433
|
client.resolve(parsedBalances, messageHash)
|
1357
2434
|
|
2435
|
+
async def fetch_position_ws(self, symbol: str, params={}) -> List[Position]:
|
2436
|
+
"""
|
2437
|
+
|
2438
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Position-Information
|
2439
|
+
|
2440
|
+
fetch data on an open position
|
2441
|
+
:param str symbol: unified market symbol of the market the position is held in
|
2442
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2443
|
+
:returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
2444
|
+
"""
|
2445
|
+
return await self.fetch_positions_ws([symbol], params)
|
2446
|
+
|
2447
|
+
async def fetch_positions_ws(self, symbols: Strings = None, params={}) -> List[Position]:
|
2448
|
+
"""
|
2449
|
+
fetch all open positions
|
2450
|
+
|
2451
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Position-Information
|
2452
|
+
|
2453
|
+
:param str[] [symbols]: list of unified market symbols
|
2454
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2455
|
+
:param boolean [params.returnRateLimits]: set to True to return rate limit informations, defaults to False.
|
2456
|
+
:param str|None [params.method]: method to use. Can be account.position or v2/account.position
|
2457
|
+
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
2458
|
+
"""
|
2459
|
+
await self.load_markets()
|
2460
|
+
symbols = self.market_symbols(symbols, 'swap', True, True, True)
|
2461
|
+
url = self.urls['api']['ws']['ws-api']['future']
|
2462
|
+
requestId = self.request_id(url)
|
2463
|
+
messageHash = str(requestId)
|
2464
|
+
payload: dict = {}
|
2465
|
+
if symbols is not None:
|
2466
|
+
symbolsLength = len(symbols)
|
2467
|
+
if symbolsLength == 1:
|
2468
|
+
payload['symbol'] = self.market_id(symbols[0])
|
2469
|
+
returnRateLimits = False
|
2470
|
+
returnRateLimits, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'returnRateLimits', False)
|
2471
|
+
payload['returnRateLimits'] = returnRateLimits
|
2472
|
+
method = None
|
2473
|
+
method, params = self.handle_option_and_params(params, 'fetchPositionsWs', 'method', 'account.position')
|
2474
|
+
message: dict = {
|
2475
|
+
'id': messageHash,
|
2476
|
+
'method': method,
|
2477
|
+
'params': self.sign_params(self.extend(payload, params)),
|
2478
|
+
}
|
2479
|
+
subscription: dict = {
|
2480
|
+
'method': self.handle_positions_ws,
|
2481
|
+
}
|
2482
|
+
result = await self.watch(url, messageHash, message, messageHash, subscription)
|
2483
|
+
return self.filter_by_array_positions(result, 'symbol', symbols, False)
|
2484
|
+
|
2485
|
+
def handle_positions_ws(self, client: Client, message):
|
2486
|
+
#
|
2487
|
+
# {
|
2488
|
+
# id: '1',
|
2489
|
+
# status: 200,
|
2490
|
+
# result: [
|
2491
|
+
# {
|
2492
|
+
# symbol: 'BTCUSDT',
|
2493
|
+
# positionAmt: '-0.014',
|
2494
|
+
# entryPrice: '42901.1',
|
2495
|
+
# breakEvenPrice: '30138.83333142',
|
2496
|
+
# markPrice: '71055.98470333',
|
2497
|
+
# unRealizedProfit: '-394.16838584',
|
2498
|
+
# liquidationPrice: '137032.02272908',
|
2499
|
+
# leverage: '123',
|
2500
|
+
# maxNotionalValue: '50000',
|
2501
|
+
# marginType: 'cross',
|
2502
|
+
# isolatedMargin: '0.00000000',
|
2503
|
+
# isAutoAddMargin: 'false',
|
2504
|
+
# positionSide: 'BOTH',
|
2505
|
+
# notional: '-994.78378584',
|
2506
|
+
# isolatedWallet: '0',
|
2507
|
+
# updateTime: 1708906343111,
|
2508
|
+
# isolated: False,
|
2509
|
+
# adlQuantile: 2
|
2510
|
+
# },
|
2511
|
+
# ...
|
2512
|
+
# ]
|
2513
|
+
# }
|
2514
|
+
#
|
2515
|
+
#
|
2516
|
+
messageHash = self.safe_string(message, 'id')
|
2517
|
+
result = self.safe_list(message, 'result', [])
|
2518
|
+
positions = []
|
2519
|
+
for i in range(0, len(result)):
|
2520
|
+
parsed = self.parse_position_risk(result[i])
|
2521
|
+
entryPrice = self.safe_string(parsed, 'entryPrice')
|
2522
|
+
if (entryPrice != '0') and (entryPrice != '0.0') and (entryPrice != '0.00000000'):
|
2523
|
+
positions.append(parsed)
|
2524
|
+
client.resolve(positions, messageHash)
|
2525
|
+
|
1358
2526
|
async def watch_balance(self, params={}) -> Balances:
|
1359
2527
|
"""
|
1360
2528
|
watch balance and get the amount of funds available for trading or funds locked in orders
|
@@ -1370,18 +2538,18 @@ class binance(ccxt.async_support.binance):
|
|
1370
2538
|
subType, params = self.handle_sub_type_and_params('watchBalance', None, params)
|
1371
2539
|
isPortfolioMargin = None
|
1372
2540
|
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'watchBalance', 'papi', 'portfolioMargin', False)
|
1373
|
-
urlType = type
|
1374
|
-
if isPortfolioMargin:
|
1375
|
-
urlType = 'papi'
|
1376
2541
|
if self.isLinear(type, subType):
|
1377
2542
|
type = 'future'
|
1378
2543
|
elif self.isInverse(type, subType):
|
1379
2544
|
type = 'delivery'
|
2545
|
+
urlType = type
|
2546
|
+
if isPortfolioMargin:
|
2547
|
+
urlType = 'papi'
|
1380
2548
|
url = self.urls['api']['ws'][urlType] + '/' + self.options[type]['listenKey']
|
1381
2549
|
client = self.client(url)
|
1382
2550
|
self.set_balance_cache(client, type, isPortfolioMargin)
|
1383
2551
|
self.set_positions_cache(client, type, None, isPortfolioMargin)
|
1384
|
-
options = self.
|
2552
|
+
options = self.safe_dict(self.options, 'watchBalance')
|
1385
2553
|
fetchBalanceSnapshot = self.safe_bool(options, 'fetchBalanceSnapshot', False)
|
1386
2554
|
awaitBalanceSnapshot = self.safe_bool(options, 'awaitBalanceSnapshot', True)
|
1387
2555
|
if fetchBalanceSnapshot and awaitBalanceSnapshot:
|
@@ -1448,7 +2616,7 @@ class binance(ccxt.async_support.binance):
|
|
1448
2616
|
# }
|
1449
2617
|
# }
|
1450
2618
|
#
|
1451
|
-
wallet = self.
|
2619
|
+
wallet = self.safe_string(self.options, 'wallet', 'wb') # cw for cross wallet
|
1452
2620
|
# each account is connected to a different endpoint
|
1453
2621
|
# and has exactly one subscriptionhash which is the account type
|
1454
2622
|
subscriptions = list(client.subscriptions.keys())
|
@@ -1472,8 +2640,8 @@ class binance(ccxt.async_support.binance):
|
|
1472
2640
|
account['free'] = delta
|
1473
2641
|
self.balance[accountType][code] = account
|
1474
2642
|
else:
|
1475
|
-
message = self.
|
1476
|
-
B = self.
|
2643
|
+
message = self.safe_dict(message, 'a', message)
|
2644
|
+
B = self.safe_list(message, 'B')
|
1477
2645
|
for i in range(0, len(B)):
|
1478
2646
|
entry = B[i]
|
1479
2647
|
currencyId = self.safe_string(entry, 'a')
|
@@ -1489,42 +2657,43 @@ class binance(ccxt.async_support.binance):
|
|
1489
2657
|
self.balance[accountType] = self.safe_balance(self.balance[accountType])
|
1490
2658
|
client.resolve(self.balance[accountType], messageHash)
|
1491
2659
|
|
1492
|
-
def
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
type =
|
1501
|
-
|
1502
|
-
if defaultType == 'spot':
|
1503
|
-
return
|
1504
|
-
raise BadRequest(self.id + ' ' + method + ' only supports spot markets')
|
1505
|
-
market = self.market(symbol)
|
1506
|
-
if not market['spot']:
|
1507
|
-
raise BadRequest(self.id + ' ' + method + ' only supports spot markets')
|
2660
|
+
def get_market_type(self, method, market, params={}):
|
2661
|
+
type = None
|
2662
|
+
type, params = self.handle_market_type_and_params(method, market, params)
|
2663
|
+
subType = None
|
2664
|
+
subType, params = self.handle_sub_type_and_params(method, market, params)
|
2665
|
+
if self.isLinear(type, subType):
|
2666
|
+
type = 'future'
|
2667
|
+
elif self.isInverse(type, subType):
|
2668
|
+
type = 'delivery'
|
2669
|
+
return type
|
1508
2670
|
|
1509
2671
|
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
1510
2672
|
"""
|
1511
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#place-new-order-trade
|
1512
2673
|
create a trade order
|
2674
|
+
|
2675
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#place-new-order-trade
|
2676
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/New-Order
|
2677
|
+
|
1513
2678
|
:param str symbol: unified symbol of the market to create an order in
|
1514
2679
|
:param str type: 'market' or 'limit'
|
1515
2680
|
:param str side: 'buy' or 'sell'
|
1516
2681
|
:param float amount: how much of currency you want to trade in units of base currency
|
1517
|
-
:param float|None [price]: the price at which the order is to be
|
2682
|
+
:param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1518
2683
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1519
2684
|
:param boolean params['test']: test order, default False
|
2685
|
+
:param boolean params['returnRateLimits']: set to True to return rate limit information, default False
|
1520
2686
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1521
2687
|
"""
|
1522
2688
|
await self.load_markets()
|
1523
|
-
self.
|
1524
|
-
|
2689
|
+
market = self.market(symbol)
|
2690
|
+
marketType = self.get_market_type('createOrderWs', market, params)
|
2691
|
+
if marketType != 'spot' and marketType != 'future':
|
2692
|
+
raise BadRequest(self.id + ' createOrderWs only supports spot or swap markets')
|
2693
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
1525
2694
|
requestId = self.request_id(url)
|
1526
2695
|
messageHash = str(requestId)
|
1527
|
-
sor = self.
|
2696
|
+
sor = self.safe_bool_2(params, 'sor', 'SOR', False)
|
1528
2697
|
params = self.omit(params, 'sor', 'SOR')
|
1529
2698
|
payload = self.create_order_request(symbol, type, side, amount, price, params)
|
1530
2699
|
returnRateLimits = False
|
@@ -1532,7 +2701,7 @@ class binance(ccxt.async_support.binance):
|
|
1532
2701
|
payload['returnRateLimits'] = returnRateLimits
|
1533
2702
|
test = self.safe_bool(params, 'test', False)
|
1534
2703
|
params = self.omit(params, 'test')
|
1535
|
-
message = {
|
2704
|
+
message: dict = {
|
1536
2705
|
'id': messageHash,
|
1537
2706
|
'method': 'order.place',
|
1538
2707
|
'params': self.sign_params(self.extend(payload, params)),
|
@@ -1542,7 +2711,7 @@ class binance(ccxt.async_support.binance):
|
|
1542
2711
|
message['method'] = 'sor.order.test'
|
1543
2712
|
else:
|
1544
2713
|
message['method'] = 'order.test'
|
1545
|
-
subscription = {
|
2714
|
+
subscription: dict = {
|
1546
2715
|
'method': self.handle_order_ws,
|
1547
2716
|
}
|
1548
2717
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
@@ -1596,7 +2765,7 @@ class binance(ccxt.async_support.binance):
|
|
1596
2765
|
# }
|
1597
2766
|
#
|
1598
2767
|
messageHash = self.safe_string(message, 'id')
|
1599
|
-
result = self.
|
2768
|
+
result = self.safe_dict(message, 'result', {})
|
1600
2769
|
order = self.parse_order(result)
|
1601
2770
|
client.resolve(order, messageHash)
|
1602
2771
|
|
@@ -1639,44 +2808,55 @@ class binance(ccxt.async_support.binance):
|
|
1639
2808
|
# }
|
1640
2809
|
#
|
1641
2810
|
messageHash = self.safe_string(message, 'id')
|
1642
|
-
result = self.
|
2811
|
+
result = self.safe_list(message, 'result', [])
|
1643
2812
|
orders = self.parse_orders(result)
|
1644
2813
|
client.resolve(orders, messageHash)
|
1645
2814
|
|
1646
|
-
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount:
|
2815
|
+
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
|
1647
2816
|
"""
|
1648
2817
|
edit a trade order
|
1649
|
-
|
2818
|
+
|
2819
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-and-replace-order-trade
|
2820
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Modify-Order
|
2821
|
+
|
1650
2822
|
:param str id: order id
|
1651
2823
|
:param str symbol: unified symbol of the market to create an order in
|
1652
2824
|
:param str type: 'market' or 'limit'
|
1653
2825
|
:param str side: 'buy' or 'sell'
|
1654
2826
|
:param float amount: how much of the currency you want to trade in units of the base currency
|
1655
|
-
:param float|None [price]: the price at which the order is to be
|
2827
|
+
:param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
1656
2828
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1657
2829
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1658
2830
|
"""
|
1659
2831
|
await self.load_markets()
|
1660
|
-
self.
|
1661
|
-
|
2832
|
+
market = self.market(symbol)
|
2833
|
+
marketType = self.get_market_type('editOrderWs', market, params)
|
2834
|
+
if marketType != 'spot' and marketType != 'future':
|
2835
|
+
raise BadRequest(self.id + ' editOrderWs only supports spot or swap markets')
|
2836
|
+
url = self.urls['api']['ws']['ws-api'][marketType]
|
1662
2837
|
requestId = self.request_id(url)
|
1663
2838
|
messageHash = str(requestId)
|
1664
|
-
payload =
|
2839
|
+
payload = None
|
2840
|
+
if marketType == 'spot':
|
2841
|
+
payload = self.editSpotOrderRequest(id, symbol, type, side, amount, price, params)
|
2842
|
+
elif marketType == 'future':
|
2843
|
+
payload = self.editContractOrderRequest(id, symbol, type, side, amount, price, params)
|
1665
2844
|
returnRateLimits = False
|
1666
2845
|
returnRateLimits, params = self.handle_option_and_params(params, 'editOrderWs', 'returnRateLimits', False)
|
1667
2846
|
payload['returnRateLimits'] = returnRateLimits
|
1668
|
-
message = {
|
2847
|
+
message: dict = {
|
1669
2848
|
'id': messageHash,
|
1670
|
-
'method': 'order.cancelReplace',
|
2849
|
+
'method': 'order.modify' if (marketType == 'future') else 'order.cancelReplace',
|
1671
2850
|
'params': self.sign_params(self.extend(payload, params)),
|
1672
2851
|
}
|
1673
|
-
subscription = {
|
2852
|
+
subscription: dict = {
|
1674
2853
|
'method': self.handle_edit_order_ws,
|
1675
2854
|
}
|
1676
2855
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
1677
2856
|
|
1678
2857
|
def handle_edit_order_ws(self, client: Client, message):
|
1679
2858
|
#
|
2859
|
+
# spot
|
1680
2860
|
# {
|
1681
2861
|
# "id": 1,
|
1682
2862
|
# "status": 200,
|
@@ -1741,19 +2921,57 @@ class binance(ccxt.async_support.binance):
|
|
1741
2921
|
# }
|
1742
2922
|
# ]
|
1743
2923
|
# }
|
2924
|
+
# swap
|
2925
|
+
# {
|
2926
|
+
# "id":"1",
|
2927
|
+
# "status":200,
|
2928
|
+
# "result":{
|
2929
|
+
# "orderId":667061487,
|
2930
|
+
# "symbol":"LTCUSDT",
|
2931
|
+
# "status":"NEW",
|
2932
|
+
# "clientOrderId":"x-xcKtGhcu91a74c818749ee42c0f70",
|
2933
|
+
# "price":"82.00",
|
2934
|
+
# "avgPrice":"0.00",
|
2935
|
+
# "origQty":"1.000",
|
2936
|
+
# "executedQty":"0.000",
|
2937
|
+
# "cumQty":"0.000",
|
2938
|
+
# "cumQuote":"0.00000",
|
2939
|
+
# "timeInForce":"GTC",
|
2940
|
+
# "type":"LIMIT",
|
2941
|
+
# "reduceOnly":false,
|
2942
|
+
# "closePosition":false,
|
2943
|
+
# "side":"BUY",
|
2944
|
+
# "positionSide":"BOTH",
|
2945
|
+
# "stopPrice":"0.00",
|
2946
|
+
# "workingType":"CONTRACT_PRICE",
|
2947
|
+
# "priceProtect":false,
|
2948
|
+
# "origType":"LIMIT",
|
2949
|
+
# "priceMatch":"NONE",
|
2950
|
+
# "selfTradePreventionMode":"NONE",
|
2951
|
+
# "goodTillDate":0,
|
2952
|
+
# "updateTime":1712918927511
|
2953
|
+
# }
|
2954
|
+
# }
|
1744
2955
|
#
|
1745
2956
|
messageHash = self.safe_string(message, 'id')
|
1746
|
-
result = self.
|
1747
|
-
|
1748
|
-
order =
|
2957
|
+
result = self.safe_dict(message, 'result', {})
|
2958
|
+
newSpotOrder = self.safe_dict(result, 'newOrderResponse')
|
2959
|
+
order = None
|
2960
|
+
if newSpotOrder is not None:
|
2961
|
+
order = self.parse_order(newSpotOrder)
|
2962
|
+
else:
|
2963
|
+
order = self.parse_order(result)
|
1749
2964
|
client.resolve(order, messageHash)
|
1750
2965
|
|
1751
2966
|
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
1752
2967
|
"""
|
1753
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#cancel-order-trade
|
1754
2968
|
cancel multiple orders
|
2969
|
+
|
2970
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-order-trade
|
2971
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Cancel-Order
|
2972
|
+
|
1755
2973
|
:param str id: order id
|
1756
|
-
:param str symbol: unified market symbol, default is None
|
2974
|
+
:param str [symbol]: unified market symbol, default is None
|
1757
2975
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1758
2976
|
:param str|None [params.cancelRestrictions]: Supported values: ONLY_NEW - Cancel will succeed if the order status is NEW. ONLY_PARTIALLY_FILLED - Cancel will succeed if order status is PARTIALLY_FILLED.
|
1759
2977
|
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
@@ -1761,100 +2979,116 @@ class binance(ccxt.async_support.binance):
|
|
1761
2979
|
await self.load_markets()
|
1762
2980
|
if symbol is None:
|
1763
2981
|
raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
|
1764
|
-
self.
|
1765
|
-
|
2982
|
+
market = self.market(symbol)
|
2983
|
+
type = self.get_market_type('cancelOrderWs', market, params)
|
2984
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1766
2985
|
requestId = self.request_id(url)
|
1767
2986
|
messageHash = str(requestId)
|
1768
2987
|
returnRateLimits = False
|
1769
2988
|
returnRateLimits, params = self.handle_option_and_params(params, 'cancelOrderWs', 'returnRateLimits', False)
|
1770
|
-
payload = {
|
2989
|
+
payload: dict = {
|
1771
2990
|
'symbol': self.market_id(symbol),
|
1772
2991
|
'returnRateLimits': returnRateLimits,
|
1773
2992
|
}
|
1774
|
-
clientOrderId = self.
|
2993
|
+
clientOrderId = self.safe_string_2(params, 'origClientOrderId', 'clientOrderId')
|
1775
2994
|
if clientOrderId is not None:
|
1776
2995
|
payload['origClientOrderId'] = clientOrderId
|
1777
2996
|
else:
|
1778
2997
|
payload['orderId'] = self.parse_to_int(id)
|
1779
2998
|
params = self.omit(params, ['origClientOrderId', 'clientOrderId'])
|
1780
|
-
message = {
|
2999
|
+
message: dict = {
|
1781
3000
|
'id': messageHash,
|
1782
3001
|
'method': 'order.cancel',
|
1783
3002
|
'params': self.sign_params(self.extend(payload, params)),
|
1784
3003
|
}
|
1785
|
-
subscription = {
|
3004
|
+
subscription: dict = {
|
1786
3005
|
'method': self.handle_order_ws,
|
1787
3006
|
}
|
1788
3007
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
1789
3008
|
|
1790
3009
|
async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
|
1791
3010
|
"""
|
1792
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#current-open-orders-user_data
|
1793
3011
|
cancel all open orders in a market
|
1794
|
-
|
3012
|
+
|
3013
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#cancel-open-orders-trade
|
3014
|
+
|
3015
|
+
:param str [symbol]: unified market symbol of the market to cancel orders in
|
1795
3016
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1796
3017
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1797
3018
|
"""
|
1798
3019
|
await self.load_markets()
|
1799
|
-
|
3020
|
+
market = self.market(symbol)
|
3021
|
+
type = self.get_market_type('cancelAllOrdersWs', market, params)
|
3022
|
+
if type != 'spot' and type != 'future':
|
3023
|
+
raise BadRequest(self.id + ' cancelAllOrdersWs only supports spot or swap markets')
|
3024
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1800
3025
|
requestId = self.request_id(url)
|
1801
3026
|
messageHash = str(requestId)
|
1802
3027
|
returnRateLimits = False
|
1803
3028
|
returnRateLimits, params = self.handle_option_and_params(params, 'cancelAllOrdersWs', 'returnRateLimits', False)
|
1804
|
-
payload = {
|
3029
|
+
payload: dict = {
|
1805
3030
|
'symbol': self.market_id(symbol),
|
1806
3031
|
'returnRateLimits': returnRateLimits,
|
1807
3032
|
}
|
1808
|
-
message = {
|
3033
|
+
message: dict = {
|
1809
3034
|
'id': messageHash,
|
1810
3035
|
'method': 'order.cancel',
|
1811
3036
|
'params': self.sign_params(self.extend(payload, params)),
|
1812
3037
|
}
|
1813
|
-
subscription = {
|
3038
|
+
subscription: dict = {
|
1814
3039
|
'method': self.handle_orders_ws,
|
1815
3040
|
}
|
1816
3041
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
1817
3042
|
|
1818
3043
|
async def fetch_order_ws(self, id: str, symbol: Str = None, params={}) -> Order:
|
1819
3044
|
"""
|
1820
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#query-order-user_data
|
1821
3045
|
fetches information on an order made by the user
|
1822
|
-
|
1823
|
-
|
3046
|
+
|
3047
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#query-order-user_data
|
3048
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/websocket-api/Query-Order
|
3049
|
+
|
3050
|
+
:param str id: order id
|
3051
|
+
:param str [symbol]: unified symbol of the market the order was made in
|
3052
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1824
3053
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1825
3054
|
"""
|
1826
3055
|
await self.load_markets()
|
1827
3056
|
if symbol is None:
|
1828
3057
|
raise BadRequest(self.id + ' cancelOrderWs requires a symbol')
|
1829
|
-
self.
|
1830
|
-
|
3058
|
+
market = self.market(symbol)
|
3059
|
+
type = self.get_market_type('fetchOrderWs', market, params)
|
3060
|
+
if type != 'spot' and type != 'future':
|
3061
|
+
raise BadRequest(self.id + ' fetchOrderWs only supports spot or swap markets')
|
3062
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1831
3063
|
requestId = self.request_id(url)
|
1832
3064
|
messageHash = str(requestId)
|
1833
3065
|
returnRateLimits = False
|
1834
3066
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchOrderWs', 'returnRateLimits', False)
|
1835
|
-
payload = {
|
3067
|
+
payload: dict = {
|
1836
3068
|
'symbol': self.market_id(symbol),
|
1837
3069
|
'returnRateLimits': returnRateLimits,
|
1838
3070
|
}
|
1839
|
-
clientOrderId = self.
|
3071
|
+
clientOrderId = self.safe_string_2(params, 'origClientOrderId', 'clientOrderId')
|
1840
3072
|
if clientOrderId is not None:
|
1841
3073
|
payload['origClientOrderId'] = clientOrderId
|
1842
3074
|
else:
|
1843
3075
|
payload['orderId'] = self.parse_to_int(id)
|
1844
|
-
message = {
|
3076
|
+
message: dict = {
|
1845
3077
|
'id': messageHash,
|
1846
3078
|
'method': 'order.status',
|
1847
3079
|
'params': self.sign_params(self.extend(payload, params)),
|
1848
3080
|
}
|
1849
|
-
subscription = {
|
3081
|
+
subscription: dict = {
|
1850
3082
|
'method': self.handle_order_ws,
|
1851
3083
|
}
|
1852
3084
|
return await self.watch(url, messageHash, message, messageHash, subscription)
|
1853
3085
|
|
1854
3086
|
async def fetch_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1855
3087
|
"""
|
1856
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-order-history-user_data
|
1857
3088
|
fetches information on multiple orders made by the user
|
3089
|
+
|
3090
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#query-order-list-user_data
|
3091
|
+
|
1858
3092
|
:param str symbol: unified market symbol of the market orders were made in
|
1859
3093
|
:param int|None [since]: the earliest time in ms to fetch orders for
|
1860
3094
|
:param int|None [limit]: the maximum number of order structures to retrieve
|
@@ -1868,22 +3102,25 @@ class binance(ccxt.async_support.binance):
|
|
1868
3102
|
await self.load_markets()
|
1869
3103
|
if symbol is None:
|
1870
3104
|
raise BadRequest(self.id + ' fetchOrdersWs requires a symbol')
|
1871
|
-
self.
|
1872
|
-
|
3105
|
+
market = self.market(symbol)
|
3106
|
+
type = self.get_market_type('fetchOrdersWs', market, params)
|
3107
|
+
if type != 'spot':
|
3108
|
+
raise BadRequest(self.id + ' fetchOrdersWs only supports spot markets')
|
3109
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1873
3110
|
requestId = self.request_id(url)
|
1874
3111
|
messageHash = str(requestId)
|
1875
3112
|
returnRateLimits = False
|
1876
3113
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchOrderWs', 'returnRateLimits', False)
|
1877
|
-
payload = {
|
3114
|
+
payload: dict = {
|
1878
3115
|
'symbol': self.market_id(symbol),
|
1879
3116
|
'returnRateLimits': returnRateLimits,
|
1880
3117
|
}
|
1881
|
-
message = {
|
3118
|
+
message: dict = {
|
1882
3119
|
'id': messageHash,
|
1883
3120
|
'method': 'allOrders',
|
1884
3121
|
'params': self.sign_params(self.extend(payload, params)),
|
1885
3122
|
}
|
1886
|
-
subscription = {
|
3123
|
+
subscription: dict = {
|
1887
3124
|
'method': self.handle_orders_ws,
|
1888
3125
|
}
|
1889
3126
|
orders = await self.watch(url, messageHash, message, messageHash, subscription)
|
@@ -1891,8 +3128,10 @@ class binance(ccxt.async_support.binance):
|
|
1891
3128
|
|
1892
3129
|
async def fetch_closed_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1893
3130
|
"""
|
1894
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-order-history-user_data
|
1895
3131
|
fetch closed orders
|
3132
|
+
|
3133
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#query-order-list-user_data
|
3134
|
+
|
1896
3135
|
:param str symbol: unified market symbol
|
1897
3136
|
:param int [since]: the earliest time in ms to fetch open orders for
|
1898
3137
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
@@ -1909,8 +3148,10 @@ class binance(ccxt.async_support.binance):
|
|
1909
3148
|
|
1910
3149
|
async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1911
3150
|
"""
|
1912
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#current-open-orders-user_data
|
1913
3151
|
fetch all unfilled currently open orders
|
3152
|
+
|
3153
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#current-open-orders-user_data
|
3154
|
+
|
1914
3155
|
:param str symbol: unified market symbol
|
1915
3156
|
:param int|None [since]: the earliest time in ms to fetch open orders for
|
1916
3157
|
:param int|None [limit]: the maximum number of open orders structures to retrieve
|
@@ -1918,23 +3159,26 @@ class binance(ccxt.async_support.binance):
|
|
1918
3159
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1919
3160
|
"""
|
1920
3161
|
await self.load_markets()
|
1921
|
-
self.
|
1922
|
-
|
3162
|
+
market = self.market(symbol)
|
3163
|
+
type = self.get_market_type('fetchOpenOrdersWs', market, params)
|
3164
|
+
if type != 'spot' and type != 'future':
|
3165
|
+
raise BadRequest(self.id + ' fetchOpenOrdersWs only supports spot or swap markets')
|
3166
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
1923
3167
|
requestId = self.request_id(url)
|
1924
3168
|
messageHash = str(requestId)
|
1925
3169
|
returnRateLimits = False
|
1926
3170
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchOrderWs', 'returnRateLimits', False)
|
1927
|
-
payload = {
|
3171
|
+
payload: dict = {
|
1928
3172
|
'returnRateLimits': returnRateLimits,
|
1929
3173
|
}
|
1930
3174
|
if symbol is not None:
|
1931
3175
|
payload['symbol'] = self.market_id(symbol)
|
1932
|
-
message = {
|
3176
|
+
message: dict = {
|
1933
3177
|
'id': messageHash,
|
1934
3178
|
'method': 'openOrders.status',
|
1935
3179
|
'params': self.sign_params(self.extend(payload, params)),
|
1936
3180
|
}
|
1937
|
-
subscription = {
|
3181
|
+
subscription: dict = {
|
1938
3182
|
'method': self.handle_orders_ws,
|
1939
3183
|
}
|
1940
3184
|
orders = await self.watch(url, messageHash, message, messageHash, subscription)
|
@@ -1943,9 +3187,11 @@ class binance(ccxt.async_support.binance):
|
|
1943
3187
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1944
3188
|
"""
|
1945
3189
|
watches information on multiple orders made by the user
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
3190
|
+
|
3191
|
+
https://developers.binance.com/docs/binance-spot-api-docs/user-data-stream#order-update
|
3192
|
+
https://developers.binance.com/docs/margin_trading/trade-data-stream/Event-Order-Update
|
3193
|
+
https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Order-Update
|
3194
|
+
|
1949
3195
|
:param str symbol: unified market symbol of the market the orders were made in
|
1950
3196
|
:param int [since]: the earliest time in ms to fetch orders for
|
1951
3197
|
:param int [limit]: the maximum number of order structures to retrieve
|
@@ -2120,7 +3366,7 @@ class binance(ccxt.async_support.binance):
|
|
2120
3366
|
'type': type,
|
2121
3367
|
'timeInForce': timeInForce,
|
2122
3368
|
'postOnly': None,
|
2123
|
-
'reduceOnly': self.
|
3369
|
+
'reduceOnly': self.safe_bool(order, 'R'),
|
2124
3370
|
'side': side,
|
2125
3371
|
'price': price,
|
2126
3372
|
'stopPrice': stopPrice,
|
@@ -2219,14 +3465,17 @@ class binance(ccxt.async_support.binance):
|
|
2219
3465
|
#
|
2220
3466
|
e = self.safe_string(message, 'e')
|
2221
3467
|
if e == 'ORDER_TRADE_UPDATE':
|
2222
|
-
message = self.
|
3468
|
+
message = self.safe_dict(message, 'o', message)
|
2223
3469
|
self.handle_my_trade(client, message)
|
2224
3470
|
self.handle_order(client, message)
|
3471
|
+
self.handle_my_liquidation(client, message)
|
2225
3472
|
|
2226
3473
|
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
2227
3474
|
"""
|
2228
3475
|
watch all open positions
|
2229
3476
|
:param str[]|None symbols: list of unified market symbols
|
3477
|
+
:param number [since]: since timestamp
|
3478
|
+
:param number [limit]: limit
|
2230
3479
|
:param dict params: extra parameters specific to the exchange API endpoint
|
2231
3480
|
:param boolean [params.portfolioMargin]: set to True if you would like to watch positions in a portfolio margin account
|
2232
3481
|
:returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
|
@@ -2238,11 +3487,6 @@ class binance(ccxt.async_support.binance):
|
|
2238
3487
|
if not self.is_empty(symbols):
|
2239
3488
|
market = self.get_market_from_symbols(symbols)
|
2240
3489
|
messageHash = '::' + ','.join(symbols)
|
2241
|
-
marketTypeObject = {}
|
2242
|
-
if market is not None:
|
2243
|
-
marketTypeObject['type'] = market['type']
|
2244
|
-
marketTypeObject['subType'] = market['subType']
|
2245
|
-
await self.authenticate(self.extend(marketTypeObject, params))
|
2246
3490
|
type = None
|
2247
3491
|
type, params = self.handle_market_type_and_params('watchPositions', market, params)
|
2248
3492
|
if type == 'spot' or type == 'margin':
|
@@ -2253,6 +3497,10 @@ class binance(ccxt.async_support.binance):
|
|
2253
3497
|
type = 'future'
|
2254
3498
|
elif self.isInverse(type, subType):
|
2255
3499
|
type = 'delivery'
|
3500
|
+
marketTypeObject: dict = {}
|
3501
|
+
marketTypeObject['type'] = type
|
3502
|
+
marketTypeObject['subType'] = subType
|
3503
|
+
await self.authenticate(self.extend(marketTypeObject, params))
|
2256
3504
|
messageHash = type + ':positions' + messageHash
|
2257
3505
|
isPortfolioMargin = None
|
2258
3506
|
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'watchPositions', 'papi', 'portfolioMargin', False)
|
@@ -2264,7 +3512,7 @@ class binance(ccxt.async_support.binance):
|
|
2264
3512
|
self.set_balance_cache(client, type, isPortfolioMargin)
|
2265
3513
|
self.set_positions_cache(client, type, symbols, isPortfolioMargin)
|
2266
3514
|
fetchPositionsSnapshot = self.handle_option('watchPositions', 'fetchPositionsSnapshot', True)
|
2267
|
-
awaitPositionsSnapshot = self.
|
3515
|
+
awaitPositionsSnapshot = self.handle_option('watchPositions', 'awaitPositionsSnapshot', True)
|
2268
3516
|
cache = self.safe_value(self.positions, type)
|
2269
3517
|
if fetchPositionsSnapshot and awaitPositionsSnapshot and cache is None:
|
2270
3518
|
snapshot = await client.future(type + ':fetchPositionsSnapshot')
|
@@ -2291,7 +3539,7 @@ class binance(ccxt.async_support.binance):
|
|
2291
3539
|
self.positions[type] = ArrayCacheBySymbolBySide()
|
2292
3540
|
|
2293
3541
|
async def load_positions_snapshot(self, client, messageHash, type, isPortfolioMargin):
|
2294
|
-
params = {
|
3542
|
+
params: dict = {
|
2295
3543
|
'type': type,
|
2296
3544
|
}
|
2297
3545
|
if isPortfolioMargin:
|
@@ -2346,8 +3594,8 @@ class binance(ccxt.async_support.binance):
|
|
2346
3594
|
if not (accountType in self.positions):
|
2347
3595
|
self.positions[accountType] = ArrayCacheBySymbolBySide()
|
2348
3596
|
cache = self.positions[accountType]
|
2349
|
-
data = self.
|
2350
|
-
rawPositions = self.
|
3597
|
+
data = self.safe_dict(message, 'a', {})
|
3598
|
+
rawPositions = self.safe_list(data, 'P', [])
|
2351
3599
|
newPositions = []
|
2352
3600
|
for i in range(0, len(rawPositions)):
|
2353
3601
|
rawPosition = rawPositions[i]
|
@@ -2421,8 +3669,10 @@ class binance(ccxt.async_support.binance):
|
|
2421
3669
|
|
2422
3670
|
async def fetch_my_trades_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
2423
3671
|
"""
|
2424
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#account-trade-history-user_data
|
2425
3672
|
fetch all trades made by the user
|
3673
|
+
|
3674
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#account-trade-history-user_data
|
3675
|
+
|
2426
3676
|
:param str symbol: unified market symbol
|
2427
3677
|
:param int|None [since]: the earliest time in ms to fetch trades for
|
2428
3678
|
:param int|None [limit]: the maximum number of trades structures to retrieve
|
@@ -2434,13 +3684,16 @@ class binance(ccxt.async_support.binance):
|
|
2434
3684
|
await self.load_markets()
|
2435
3685
|
if symbol is None:
|
2436
3686
|
raise BadRequest(self.id + ' fetchMyTradesWs requires a symbol')
|
2437
|
-
self.
|
2438
|
-
|
3687
|
+
market = self.market(symbol)
|
3688
|
+
type = self.get_market_type('fetchMyTradesWs', market, params)
|
3689
|
+
if type != 'spot' and type != 'future':
|
3690
|
+
raise BadRequest(self.id + ' fetchMyTradesWs does not support ' + type + ' markets')
|
3691
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
2439
3692
|
requestId = self.request_id(url)
|
2440
3693
|
messageHash = str(requestId)
|
2441
3694
|
returnRateLimits = False
|
2442
3695
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchMyTradesWs', 'returnRateLimits', False)
|
2443
|
-
payload = {
|
3696
|
+
payload: dict = {
|
2444
3697
|
'symbol': self.market_id(symbol),
|
2445
3698
|
'returnRateLimits': returnRateLimits,
|
2446
3699
|
}
|
@@ -2451,12 +3704,12 @@ class binance(ccxt.async_support.binance):
|
|
2451
3704
|
fromId = self.safe_integer(params, 'fromId')
|
2452
3705
|
if fromId is not None and since is not None:
|
2453
3706
|
raise BadRequest(self.id + 'fetchMyTradesWs does not support fetching by both fromId and since parameters at the same time')
|
2454
|
-
message = {
|
3707
|
+
message: dict = {
|
2455
3708
|
'id': messageHash,
|
2456
3709
|
'method': 'myTrades',
|
2457
3710
|
'params': self.sign_params(self.extend(payload, params)),
|
2458
3711
|
}
|
2459
|
-
subscription = {
|
3712
|
+
subscription: dict = {
|
2460
3713
|
'method': self.handle_trades_ws,
|
2461
3714
|
}
|
2462
3715
|
trades = await self.watch(url, messageHash, message, messageHash, subscription)
|
@@ -2464,38 +3717,43 @@ class binance(ccxt.async_support.binance):
|
|
2464
3717
|
|
2465
3718
|
async def fetch_trades_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
2466
3719
|
"""
|
2467
|
-
:see: https://binance-docs.github.io/apidocs/websocket_api/en/#recent-trades
|
2468
3720
|
fetch all trades made by the user
|
3721
|
+
|
3722
|
+
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api#recent-trades
|
3723
|
+
|
2469
3724
|
:param str symbol: unified market symbol
|
2470
3725
|
:param int [since]: the earliest time in ms to fetch trades for
|
2471
3726
|
:param int [limit]: the maximum number of trades structures to retrieve, default=500, max=1000
|
2472
3727
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2473
|
-
|
2474
|
-
|
3728
|
+
|
3729
|
+
EXCHANGE SPECIFIC PARAMETERS
|
2475
3730
|
:param int [params.fromId]: trade ID to begin at
|
2476
3731
|
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
2477
3732
|
"""
|
2478
3733
|
await self.load_markets()
|
2479
3734
|
if symbol is None:
|
2480
3735
|
raise BadRequest(self.id + ' fetchTradesWs() requires a symbol argument')
|
2481
|
-
self.
|
2482
|
-
|
3736
|
+
market = self.market(symbol)
|
3737
|
+
type = self.get_market_type('fetchTradesWs', market, params)
|
3738
|
+
if type != 'spot' and type != 'future':
|
3739
|
+
raise BadRequest(self.id + ' fetchTradesWs does not support ' + type + ' markets')
|
3740
|
+
url = self.urls['api']['ws']['ws-api'][type]
|
2483
3741
|
requestId = self.request_id(url)
|
2484
3742
|
messageHash = str(requestId)
|
2485
3743
|
returnRateLimits = False
|
2486
3744
|
returnRateLimits, params = self.handle_option_and_params(params, 'fetchTradesWs', 'returnRateLimits', False)
|
2487
|
-
payload = {
|
3745
|
+
payload: dict = {
|
2488
3746
|
'symbol': self.market_id(symbol),
|
2489
3747
|
'returnRateLimits': returnRateLimits,
|
2490
3748
|
}
|
2491
3749
|
if limit is not None:
|
2492
3750
|
payload['limit'] = limit
|
2493
|
-
message = {
|
3751
|
+
message: dict = {
|
2494
3752
|
'id': messageHash,
|
2495
3753
|
'method': 'trades.historical',
|
2496
3754
|
'params': self.extend(payload, params),
|
2497
3755
|
}
|
2498
|
-
subscription = {
|
3756
|
+
subscription: dict = {
|
2499
3757
|
'method': self.handle_trades_ws,
|
2500
3758
|
}
|
2501
3759
|
trades = await self.watch(url, messageHash, message, messageHash, subscription)
|
@@ -2548,7 +3806,7 @@ class binance(ccxt.async_support.binance):
|
|
2548
3806
|
# }
|
2549
3807
|
#
|
2550
3808
|
messageHash = self.safe_string(message, 'id')
|
2551
|
-
result = self.
|
3809
|
+
result = self.safe_list(message, 'result', [])
|
2552
3810
|
trades = self.parse_trades(result)
|
2553
3811
|
client.resolve(trades, messageHash)
|
2554
3812
|
|
@@ -2560,7 +3818,7 @@ class binance(ccxt.async_support.binance):
|
|
2560
3818
|
:param int [limit]: the maximum number of order structures to retrieve
|
2561
3819
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
2562
3820
|
:param boolean [params.portfolioMargin]: set to True if you would like to watch trades in a portfolio margin account
|
2563
|
-
:returns dict[]: a list of
|
3821
|
+
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
2564
3822
|
"""
|
2565
3823
|
await self.load_markets()
|
2566
3824
|
type = None
|
@@ -2604,7 +3862,7 @@ class binance(ccxt.async_support.binance):
|
|
2604
3862
|
if executionType == 'TRADE':
|
2605
3863
|
trade = self.parse_ws_trade(message)
|
2606
3864
|
orderId = self.safe_string(trade, 'order')
|
2607
|
-
tradeFee = self.
|
3865
|
+
tradeFee = self.safe_dict(trade, 'fee', {})
|
2608
3866
|
tradeFee = self.extend({}, tradeFee)
|
2609
3867
|
symbol = self.safe_string(trade, 'symbol')
|
2610
3868
|
if orderId is not None and tradeFee is not None and symbol is not None:
|
@@ -2639,7 +3897,7 @@ class binance(ccxt.async_support.binance):
|
|
2639
3897
|
else:
|
2640
3898
|
order['fee'] = tradeFee
|
2641
3899
|
# save self trade in the order
|
2642
|
-
orderTrades = self.
|
3900
|
+
orderTrades = self.safe_list(order, 'trades', [])
|
2643
3901
|
orderTrades.append(trade)
|
2644
3902
|
order['trades'] = orderTrades
|
2645
3903
|
# don't append twice cause it breaks newUpdates mode
|
@@ -2698,7 +3956,7 @@ class binance(ccxt.async_support.binance):
|
|
2698
3956
|
#
|
2699
3957
|
id = self.safe_string(message, 'id')
|
2700
3958
|
rejected = False
|
2701
|
-
error = self.
|
3959
|
+
error = self.safe_dict(message, 'error', {})
|
2702
3960
|
code = self.safe_integer(error, 'code')
|
2703
3961
|
msg = self.safe_string(error, 'msg')
|
2704
3962
|
try:
|
@@ -2707,7 +3965,7 @@ class binance(ccxt.async_support.binance):
|
|
2707
3965
|
rejected = True
|
2708
3966
|
# private endpoint uses id
|
2709
3967
|
client.reject(e, id)
|
2710
|
-
# public endpoint stores messageHash in
|
3968
|
+
# public endpoint stores messageHash in subscriptions
|
2711
3969
|
subscriptionKeys = list(client.subscriptions.keys())
|
2712
3970
|
for i in range(0, len(subscriptionKeys)):
|
2713
3971
|
subscriptionHash = subscriptionKeys[i]
|
@@ -2717,7 +3975,8 @@ class binance(ccxt.async_support.binance):
|
|
2717
3975
|
if not rejected:
|
2718
3976
|
client.reject(message, id)
|
2719
3977
|
# reset connection if 5xx error
|
2720
|
-
|
3978
|
+
codeString = self.safe_string(error, 'code')
|
3979
|
+
if (codeString is not None) and (codeString[0] == '5'):
|
2721
3980
|
client.reset(message)
|
2722
3981
|
|
2723
3982
|
def handle_message(self, client: Client, message):
|
@@ -2734,23 +3993,32 @@ class binance(ccxt.async_support.binance):
|
|
2734
3993
|
method(client, message)
|
2735
3994
|
return
|
2736
3995
|
# handle other APIs
|
2737
|
-
methods = {
|
3996
|
+
methods: dict = {
|
2738
3997
|
'depthUpdate': self.handle_order_book,
|
2739
3998
|
'trade': self.handle_trade,
|
2740
3999
|
'aggTrade': self.handle_trade,
|
2741
4000
|
'kline': self.handle_ohlcv,
|
2742
4001
|
'markPrice_kline': self.handle_ohlcv,
|
2743
4002
|
'indexPrice_kline': self.handle_ohlcv,
|
4003
|
+
'1hTicker@arr': self.handle_tickers,
|
4004
|
+
'4hTicker@arr': self.handle_tickers,
|
4005
|
+
'1dTicker@arr': self.handle_tickers,
|
2744
4006
|
'24hrTicker@arr': self.handle_tickers,
|
2745
4007
|
'24hrMiniTicker@arr': self.handle_tickers,
|
2746
|
-
'
|
2747
|
-
'
|
2748
|
-
'
|
4008
|
+
'1hTicker': self.handle_tickers,
|
4009
|
+
'4hTicker': self.handle_tickers,
|
4010
|
+
'1dTicker': self.handle_tickers,
|
4011
|
+
'24hrTicker': self.handle_tickers,
|
4012
|
+
'24hrMiniTicker': self.handle_tickers,
|
4013
|
+
'markPriceUpdate': self.handle_tickers,
|
4014
|
+
'markPriceUpdate@arr': self.handle_tickers,
|
4015
|
+
'bookTicker': self.handle_bids_asks, # there is no "bookTicker@arr" endpoint
|
2749
4016
|
'outboundAccountPosition': self.handle_balance,
|
2750
4017
|
'balanceUpdate': self.handle_balance,
|
2751
4018
|
'ACCOUNT_UPDATE': self.handle_acount_update,
|
2752
4019
|
'executionReport': self.handle_order_update,
|
2753
4020
|
'ORDER_TRADE_UPDATE': self.handle_order_update,
|
4021
|
+
'forceOrder': self.handle_liquidation,
|
2754
4022
|
}
|
2755
4023
|
event = self.safe_string(message, 'e')
|
2756
4024
|
if isinstance(message, list):
|
@@ -2773,8 +4041,7 @@ class binance(ccxt.async_support.binance):
|
|
2773
4041
|
# "A": "2.52500800"
|
2774
4042
|
# }
|
2775
4043
|
#
|
2776
|
-
if event is None:
|
2777
|
-
self.
|
2778
|
-
self.handle_tickers(client, message)
|
4044
|
+
if event is None and ('a' in message) and ('b' in message):
|
4045
|
+
self.handle_bids_asks(client, message)
|
2779
4046
|
else:
|
2780
4047
|
method(client, message)
|