coinex-api 0.0.13__py3-none-any.whl → 0.0.14__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.
- coinex/__init__.py +7 -0
- coinex/ccxt/__init__.py +101 -0
- coinex/ccxt/abstract/coinex.py +237 -0
- coinex/ccxt/async_support/__init__.py +80 -0
- coinex/ccxt/async_support/base/__init__.py +1 -0
- coinex/ccxt/async_support/base/exchange.py +2100 -0
- coinex/ccxt/async_support/base/throttler.py +50 -0
- coinex/ccxt/async_support/base/ws/__init__.py +38 -0
- coinex/ccxt/async_support/base/ws/aiohttp_client.py +147 -0
- coinex/ccxt/async_support/base/ws/cache.py +213 -0
- coinex/ccxt/async_support/base/ws/client.py +214 -0
- coinex/ccxt/async_support/base/ws/fast_client.py +97 -0
- coinex/ccxt/async_support/base/ws/functions.py +59 -0
- coinex/ccxt/async_support/base/ws/future.py +69 -0
- coinex/ccxt/async_support/base/ws/order_book.py +78 -0
- coinex/ccxt/async_support/base/ws/order_book_side.py +174 -0
- coinex/ccxt/async_support/coinex.py +5833 -0
- coinex/ccxt/base/__init__.py +27 -0
- coinex/ccxt/base/decimal_to_precision.py +174 -0
- coinex/ccxt/base/errors.py +267 -0
- coinex/ccxt/base/exchange.py +6769 -0
- coinex/ccxt/base/precise.py +297 -0
- coinex/ccxt/base/types.py +577 -0
- coinex/ccxt/coinex.py +5832 -0
- coinex/ccxt/pro/__init__.py +21 -0
- coinex/ccxt/pro/coinex.py +1366 -0
- coinex/ccxt/static_dependencies/README.md +1 -0
- coinex/ccxt/static_dependencies/__init__.py +1 -0
- coinex/ccxt/static_dependencies/ecdsa/__init__.py +14 -0
- coinex/ccxt/static_dependencies/ecdsa/_version.py +520 -0
- coinex/ccxt/static_dependencies/ecdsa/curves.py +56 -0
- coinex/ccxt/static_dependencies/ecdsa/der.py +221 -0
- coinex/ccxt/static_dependencies/ecdsa/ecdsa.py +310 -0
- coinex/ccxt/static_dependencies/ecdsa/ellipticcurve.py +197 -0
- coinex/ccxt/static_dependencies/ecdsa/keys.py +332 -0
- coinex/ccxt/static_dependencies/ecdsa/numbertheory.py +531 -0
- coinex/ccxt/static_dependencies/ecdsa/rfc6979.py +100 -0
- coinex/ccxt/static_dependencies/ecdsa/util.py +266 -0
- coinex/ccxt/static_dependencies/ethereum/__init__.py +7 -0
- coinex/ccxt/static_dependencies/ethereum/abi/__init__.py +16 -0
- coinex/ccxt/static_dependencies/ethereum/abi/abi.py +19 -0
- coinex/ccxt/static_dependencies/ethereum/abi/base.py +152 -0
- coinex/ccxt/static_dependencies/ethereum/abi/codec.py +217 -0
- coinex/ccxt/static_dependencies/ethereum/abi/constants.py +3 -0
- coinex/ccxt/static_dependencies/ethereum/abi/decoding.py +565 -0
- coinex/ccxt/static_dependencies/ethereum/abi/encoding.py +720 -0
- coinex/ccxt/static_dependencies/ethereum/abi/exceptions.py +139 -0
- coinex/ccxt/static_dependencies/ethereum/abi/grammar.py +443 -0
- coinex/ccxt/static_dependencies/ethereum/abi/packed.py +13 -0
- coinex/ccxt/static_dependencies/ethereum/abi/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/abi/registry.py +643 -0
- coinex/ccxt/static_dependencies/ethereum/abi/tools/__init__.py +3 -0
- coinex/ccxt/static_dependencies/ethereum/abi/tools/_strategies.py +230 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/__init__.py +0 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/numeric.py +83 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/padding.py +27 -0
- coinex/ccxt/static_dependencies/ethereum/abi/utils/string.py +19 -0
- coinex/ccxt/static_dependencies/ethereum/account/__init__.py +3 -0
- coinex/ccxt/static_dependencies/ethereum/account/encode_typed_data/__init__.py +4 -0
- coinex/ccxt/static_dependencies/ethereum/account/encode_typed_data/encoding_and_hashing.py +239 -0
- coinex/ccxt/static_dependencies/ethereum/account/encode_typed_data/helpers.py +40 -0
- coinex/ccxt/static_dependencies/ethereum/account/messages.py +263 -0
- coinex/ccxt/static_dependencies/ethereum/account/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/__init__.py +5 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/_utils.py +54 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/main.py +65 -0
- coinex/ccxt/static_dependencies/ethereum/hexbytes/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/typing/__init__.py +63 -0
- coinex/ccxt/static_dependencies/ethereum/typing/abi.py +6 -0
- coinex/ccxt/static_dependencies/ethereum/typing/bls.py +7 -0
- coinex/ccxt/static_dependencies/ethereum/typing/discovery.py +5 -0
- coinex/ccxt/static_dependencies/ethereum/typing/encoding.py +7 -0
- coinex/ccxt/static_dependencies/ethereum/typing/enums.py +17 -0
- coinex/ccxt/static_dependencies/ethereum/typing/ethpm.py +9 -0
- coinex/ccxt/static_dependencies/ethereum/typing/evm.py +20 -0
- coinex/ccxt/static_dependencies/ethereum/typing/networks.py +1122 -0
- coinex/ccxt/static_dependencies/ethereum/typing/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/utils/__init__.py +115 -0
- coinex/ccxt/static_dependencies/ethereum/utils/abi.py +72 -0
- coinex/ccxt/static_dependencies/ethereum/utils/address.py +171 -0
- coinex/ccxt/static_dependencies/ethereum/utils/applicators.py +151 -0
- coinex/ccxt/static_dependencies/ethereum/utils/conversions.py +190 -0
- coinex/ccxt/static_dependencies/ethereum/utils/currency.py +107 -0
- coinex/ccxt/static_dependencies/ethereum/utils/curried/__init__.py +269 -0
- coinex/ccxt/static_dependencies/ethereum/utils/debug.py +20 -0
- coinex/ccxt/static_dependencies/ethereum/utils/decorators.py +132 -0
- coinex/ccxt/static_dependencies/ethereum/utils/encoding.py +6 -0
- coinex/ccxt/static_dependencies/ethereum/utils/exceptions.py +4 -0
- coinex/ccxt/static_dependencies/ethereum/utils/functional.py +75 -0
- coinex/ccxt/static_dependencies/ethereum/utils/hexadecimal.py +74 -0
- coinex/ccxt/static_dependencies/ethereum/utils/humanize.py +188 -0
- coinex/ccxt/static_dependencies/ethereum/utils/logging.py +159 -0
- coinex/ccxt/static_dependencies/ethereum/utils/module_loading.py +31 -0
- coinex/ccxt/static_dependencies/ethereum/utils/numeric.py +43 -0
- coinex/ccxt/static_dependencies/ethereum/utils/py.typed +0 -0
- coinex/ccxt/static_dependencies/ethereum/utils/toolz.py +76 -0
- coinex/ccxt/static_dependencies/ethereum/utils/types.py +54 -0
- coinex/ccxt/static_dependencies/ethereum/utils/typing/__init__.py +18 -0
- coinex/ccxt/static_dependencies/ethereum/utils/typing/misc.py +14 -0
- coinex/ccxt/static_dependencies/ethereum/utils/units.py +31 -0
- coinex/ccxt/static_dependencies/keccak/__init__.py +3 -0
- coinex/ccxt/static_dependencies/keccak/keccak.py +197 -0
- coinex/ccxt/static_dependencies/lark/__init__.py +38 -0
- coinex/ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- coinex/ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- coinex/ccxt/static_dependencies/lark/ast_utils.py +59 -0
- coinex/ccxt/static_dependencies/lark/common.py +86 -0
- coinex/ccxt/static_dependencies/lark/exceptions.py +292 -0
- coinex/ccxt/static_dependencies/lark/grammar.py +130 -0
- coinex/ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- coinex/ccxt/static_dependencies/lark/grammars/common.lark +59 -0
- coinex/ccxt/static_dependencies/lark/grammars/lark.lark +62 -0
- coinex/ccxt/static_dependencies/lark/grammars/python.lark +302 -0
- coinex/ccxt/static_dependencies/lark/grammars/unicode.lark +7 -0
- coinex/ccxt/static_dependencies/lark/indenter.py +143 -0
- coinex/ccxt/static_dependencies/lark/lark.py +658 -0
- coinex/ccxt/static_dependencies/lark/lexer.py +678 -0
- coinex/ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- coinex/ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- coinex/ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- coinex/ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- coinex/ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- coinex/ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- coinex/ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- coinex/ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- coinex/ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- coinex/ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- coinex/ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- coinex/ccxt/static_dependencies/lark/py.typed +0 -0
- coinex/ccxt/static_dependencies/lark/reconstruct.py +107 -0
- coinex/ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- coinex/ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- coinex/ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- coinex/ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- coinex/ccxt/static_dependencies/lark/tree.py +267 -0
- coinex/ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- coinex/ccxt/static_dependencies/lark/tree_templates.py +180 -0
- coinex/ccxt/static_dependencies/lark/utils.py +343 -0
- coinex/ccxt/static_dependencies/lark/visitors.py +596 -0
- coinex/ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- coinex/ccxt/static_dependencies/marshmallow/base.py +65 -0
- coinex/ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- coinex/ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- coinex/ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- coinex/ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- coinex/ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- coinex/ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- coinex/ccxt/static_dependencies/marshmallow/py.typed +0 -0
- coinex/ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- coinex/ccxt/static_dependencies/marshmallow/types.py +12 -0
- coinex/ccxt/static_dependencies/marshmallow/utils.py +378 -0
- coinex/ccxt/static_dependencies/marshmallow/validate.py +678 -0
- coinex/ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- coinex/ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- coinex/ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- coinex/ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- coinex/ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- coinex/ccxt/static_dependencies/msgpack/__init__.py +55 -0
- coinex/ccxt/static_dependencies/msgpack/_cmsgpack.pyx +11 -0
- coinex/ccxt/static_dependencies/msgpack/_packer.pyx +374 -0
- coinex/ccxt/static_dependencies/msgpack/_unpacker.pyx +547 -0
- coinex/ccxt/static_dependencies/msgpack/buff_converter.h +8 -0
- coinex/ccxt/static_dependencies/msgpack/exceptions.py +48 -0
- coinex/ccxt/static_dependencies/msgpack/ext.py +168 -0
- coinex/ccxt/static_dependencies/msgpack/fallback.py +951 -0
- coinex/ccxt/static_dependencies/msgpack/pack.h +89 -0
- coinex/ccxt/static_dependencies/msgpack/pack_template.h +820 -0
- coinex/ccxt/static_dependencies/msgpack/sysdep.h +194 -0
- coinex/ccxt/static_dependencies/msgpack/unpack.h +391 -0
- coinex/ccxt/static_dependencies/msgpack/unpack_define.h +95 -0
- coinex/ccxt/static_dependencies/msgpack/unpack_template.h +464 -0
- coinex/ccxt/static_dependencies/parsimonious/__init__.py +10 -0
- coinex/ccxt/static_dependencies/parsimonious/exceptions.py +105 -0
- coinex/ccxt/static_dependencies/parsimonious/expressions.py +479 -0
- coinex/ccxt/static_dependencies/parsimonious/grammar.py +487 -0
- coinex/ccxt/static_dependencies/parsimonious/nodes.py +325 -0
- coinex/ccxt/static_dependencies/parsimonious/utils.py +40 -0
- coinex/ccxt/static_dependencies/starknet/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/__init__.py +2 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/model.py +44 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/parser.py +216 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/schemas.py +72 -0
- coinex/ccxt/static_dependencies/starknet/abi/v0/shape.py +63 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/__init__.py +2 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/core_structures.json +14 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/model.py +39 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/parser.py +220 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/parser_transformer.py +179 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/schemas.py +66 -0
- coinex/ccxt/static_dependencies/starknet/abi/v1/shape.py +47 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/__init__.py +2 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/model.py +89 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/parser.py +293 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/parser_transformer.py +192 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/schemas.py +132 -0
- coinex/ccxt/static_dependencies/starknet/abi/v2/shape.py +107 -0
- coinex/ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- coinex/ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- coinex/ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- coinex/ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- coinex/ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- coinex/ccxt/static_dependencies/starknet/common.py +15 -0
- coinex/ccxt/static_dependencies/starknet/constants.py +39 -0
- coinex/ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/hash/address.py +79 -0
- coinex/ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- coinex/ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- coinex/ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- coinex/ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- coinex/ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- coinex/ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- coinex/ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- coinex/ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- coinex/ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- coinex/ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- coinex/ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- coinex/ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- coinex/ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- coinex/ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- coinex/ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- coinex/ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- coinex/ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- coinex/ccxt/static_dependencies/starkware/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- coinex/ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- coinex/ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- coinex/ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- coinex/ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- coinex/ccxt/static_dependencies/sympy/__init__.py +0 -0
- coinex/ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- coinex/ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- coinex/ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- coinex/ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- coinex/ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- coinex/ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- coinex/ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- coinex/ccxt/static_dependencies/toolz/__init__.py +26 -0
- coinex/ccxt/static_dependencies/toolz/_signatures.py +784 -0
- coinex/ccxt/static_dependencies/toolz/_version.py +520 -0
- coinex/ccxt/static_dependencies/toolz/compatibility.py +30 -0
- coinex/ccxt/static_dependencies/toolz/curried/__init__.py +101 -0
- coinex/ccxt/static_dependencies/toolz/curried/exceptions.py +22 -0
- coinex/ccxt/static_dependencies/toolz/curried/operator.py +22 -0
- coinex/ccxt/static_dependencies/toolz/dicttoolz.py +339 -0
- coinex/ccxt/static_dependencies/toolz/functoolz.py +1049 -0
- coinex/ccxt/static_dependencies/toolz/itertoolz.py +1057 -0
- coinex/ccxt/static_dependencies/toolz/recipes.py +46 -0
- coinex/ccxt/static_dependencies/toolz/utils.py +9 -0
- coinex/ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- coinex/ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- {coinex_api-0.0.13.dist-info → coinex_api-0.0.14.dist-info}/METADATA +1 -1
- coinex_api-0.0.14.dist-info/RECORD +288 -0
- coinex_api-0.0.13.dist-info/RECORD +0 -3
- {coinex_api-0.0.13.dist-info → coinex_api-0.0.14.dist-info}/WHEEL +0 -0
@@ -0,0 +1,2100 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
# -----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
__version__ = '4.4.69'
|
6
|
+
|
7
|
+
# -----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
import asyncio
|
10
|
+
import concurrent.futures
|
11
|
+
import socket
|
12
|
+
import certifi
|
13
|
+
import aiohttp
|
14
|
+
import ssl
|
15
|
+
import sys
|
16
|
+
import yarl
|
17
|
+
import math
|
18
|
+
from typing import Any, List
|
19
|
+
from ccxt.base.types import Int, Str, Num, Strings
|
20
|
+
|
21
|
+
# -----------------------------------------------------------------------------
|
22
|
+
|
23
|
+
from ccxt.async_support.base.throttler import Throttler
|
24
|
+
|
25
|
+
# -----------------------------------------------------------------------------
|
26
|
+
|
27
|
+
from ccxt.base.errors import BaseError, BadSymbol, BadRequest, BadResponse, ExchangeError, ExchangeNotAvailable, RequestTimeout, NotSupported, NullResponse, InvalidAddress, RateLimitExceeded, OperationFailed
|
28
|
+
from ccxt.base.types import OrderType, OrderSide, OrderRequest, CancellationRequest
|
29
|
+
|
30
|
+
# -----------------------------------------------------------------------------
|
31
|
+
|
32
|
+
from ccxt.base.exchange import Exchange as BaseExchange, ArgumentsRequired
|
33
|
+
|
34
|
+
# -----------------------------------------------------------------------------
|
35
|
+
|
36
|
+
from ccxt.async_support.base.ws.functions import inflate, inflate64, gunzip
|
37
|
+
from ccxt.async_support.base.ws.fast_client import FastClient
|
38
|
+
from ccxt.async_support.base.ws.future import Future
|
39
|
+
from ccxt.async_support.base.ws.order_book import OrderBook, IndexedOrderBook, CountedOrderBook
|
40
|
+
|
41
|
+
|
42
|
+
# -----------------------------------------------------------------------------
|
43
|
+
|
44
|
+
try:
|
45
|
+
from aiohttp_socks import ProxyConnector
|
46
|
+
except ImportError:
|
47
|
+
ProxyConnector = None
|
48
|
+
|
49
|
+
# -----------------------------------------------------------------------------
|
50
|
+
|
51
|
+
__all__ = [
|
52
|
+
'BaseExchange',
|
53
|
+
'Exchange',
|
54
|
+
]
|
55
|
+
|
56
|
+
# -----------------------------------------------------------------------------
|
57
|
+
|
58
|
+
|
59
|
+
class Exchange(BaseExchange):
|
60
|
+
synchronous = False
|
61
|
+
streaming = {
|
62
|
+
'maxPingPongMisses': 2,
|
63
|
+
'keepAlive': 30000
|
64
|
+
}
|
65
|
+
ping = None
|
66
|
+
newUpdates = True
|
67
|
+
clients = {}
|
68
|
+
timeout_on_exit = 250 # needed for: https://github.com/ccxt/ccxt/pull/23470
|
69
|
+
|
70
|
+
def __init__(self, config={}):
|
71
|
+
if 'asyncio_loop' in config:
|
72
|
+
self.asyncio_loop = config['asyncio_loop']
|
73
|
+
self.aiohttp_trust_env = config.get('aiohttp_trust_env', self.aiohttp_trust_env)
|
74
|
+
self.verify = config.get('verify', self.verify)
|
75
|
+
self.own_session = 'session' not in config
|
76
|
+
self.cafile = config.get('cafile', certifi.where())
|
77
|
+
self.throttler = None
|
78
|
+
super(Exchange, self).__init__(config)
|
79
|
+
self.markets_loading = None
|
80
|
+
self.reloading_markets = False
|
81
|
+
|
82
|
+
def get_event_loop(self):
|
83
|
+
return self.asyncio_loop
|
84
|
+
|
85
|
+
def init_throttler(self, cost=None):
|
86
|
+
self.throttler = Throttler(self.tokenBucket, self.asyncio_loop)
|
87
|
+
|
88
|
+
async def throttle(self, cost=None):
|
89
|
+
return await self.throttler(cost)
|
90
|
+
|
91
|
+
def get_session(self):
|
92
|
+
return self.session
|
93
|
+
|
94
|
+
def __del__(self):
|
95
|
+
if self.session is not None or self.socks_proxy_sessions is not None:
|
96
|
+
self.logger.warning(self.id + " requires to release all resources with an explicit call to the .close() coroutine. If you are using the exchange instance with async coroutines, add `await exchange.close()` to your code into a place when you're done with the exchange and don't need the exchange instance anymore (at the end of your async coroutine).")
|
97
|
+
|
98
|
+
if sys.version_info >= (3, 5):
|
99
|
+
async def __aenter__(self):
|
100
|
+
self.open()
|
101
|
+
return self
|
102
|
+
|
103
|
+
async def __aexit__(self, exc_type, exc, tb):
|
104
|
+
await self.close()
|
105
|
+
|
106
|
+
def open(self):
|
107
|
+
if self.asyncio_loop is None:
|
108
|
+
if sys.version_info >= (3, 7):
|
109
|
+
self.asyncio_loop = asyncio.get_running_loop()
|
110
|
+
else:
|
111
|
+
self.asyncio_loop = asyncio.get_event_loop()
|
112
|
+
self.throttler.loop = self.asyncio_loop
|
113
|
+
|
114
|
+
if self.ssl_context is None:
|
115
|
+
# Create our SSL context object with our CA cert file
|
116
|
+
self.ssl_context = ssl.create_default_context(cafile=self.cafile) if self.verify else self.verify
|
117
|
+
|
118
|
+
if self.own_session and self.session is None:
|
119
|
+
# Pass this SSL context to aiohttp and create a TCPConnector
|
120
|
+
self.tcp_connector = aiohttp.TCPConnector(ssl=self.ssl_context, loop=self.asyncio_loop, enable_cleanup_closed=True)
|
121
|
+
self.session = aiohttp.ClientSession(loop=self.asyncio_loop, connector=self.tcp_connector, trust_env=self.aiohttp_trust_env)
|
122
|
+
|
123
|
+
async def close(self):
|
124
|
+
await self.ws_close()
|
125
|
+
if self.session is not None:
|
126
|
+
if self.own_session:
|
127
|
+
await self.session.close()
|
128
|
+
self.session = None
|
129
|
+
await self.close_connector()
|
130
|
+
await self.close_proxy_sessions()
|
131
|
+
await self.sleep(self.timeout_on_exit)
|
132
|
+
|
133
|
+
async def close_connector(self):
|
134
|
+
if self.tcp_connector is not None:
|
135
|
+
await self.tcp_connector.close()
|
136
|
+
self.tcp_connector = None
|
137
|
+
if self.aiohttp_socks_connector is not None:
|
138
|
+
await self.aiohttp_socks_connector.close()
|
139
|
+
self.aiohttp_socks_connector = None
|
140
|
+
|
141
|
+
async def close_proxy_sessions(self):
|
142
|
+
if self.socks_proxy_sessions is not None:
|
143
|
+
for url in self.socks_proxy_sessions:
|
144
|
+
await self.socks_proxy_sessions[url].close()
|
145
|
+
self.socks_proxy_sessions = None
|
146
|
+
|
147
|
+
async def fetch(self, url, method='GET', headers=None, body=None):
|
148
|
+
"""Perform a HTTP request and return decoded JSON data"""
|
149
|
+
|
150
|
+
# ##### PROXY & HEADERS #####
|
151
|
+
request_headers = self.prepare_request_headers(headers)
|
152
|
+
self.last_request_headers = request_headers
|
153
|
+
# proxy-url
|
154
|
+
proxyUrl = self.check_proxy_url_settings(url, method, headers, body)
|
155
|
+
if proxyUrl is not None:
|
156
|
+
request_headers.update({'Origin': self.origin})
|
157
|
+
url = proxyUrl + url
|
158
|
+
# proxy agents
|
159
|
+
final_proxy = None # set default
|
160
|
+
proxy_session = None
|
161
|
+
httpProxy, httpsProxy, socksProxy = self.check_proxy_settings(url, method, headers, body)
|
162
|
+
if httpProxy:
|
163
|
+
final_proxy = httpProxy
|
164
|
+
elif httpsProxy:
|
165
|
+
final_proxy = httpsProxy
|
166
|
+
elif socksProxy:
|
167
|
+
if ProxyConnector is None:
|
168
|
+
raise NotSupported(self.id + ' - to use SOCKS proxy with ccxt, you need "aiohttp_socks" module that can be installed by "pip install aiohttp_socks"')
|
169
|
+
# override session
|
170
|
+
if (self.socks_proxy_sessions is None):
|
171
|
+
self.socks_proxy_sessions = {}
|
172
|
+
if (socksProxy not in self.socks_proxy_sessions):
|
173
|
+
# Create our SSL context object with our CA cert file
|
174
|
+
self.open() # ensure `asyncio_loop` is set
|
175
|
+
self.aiohttp_socks_connector = ProxyConnector.from_url(
|
176
|
+
socksProxy,
|
177
|
+
# extra args copied from self.open()
|
178
|
+
ssl=self.ssl_context,
|
179
|
+
loop=self.asyncio_loop,
|
180
|
+
enable_cleanup_closed=True
|
181
|
+
)
|
182
|
+
self.socks_proxy_sessions[socksProxy] = aiohttp.ClientSession(loop=self.asyncio_loop, connector=self.aiohttp_socks_connector, trust_env=self.aiohttp_trust_env)
|
183
|
+
proxy_session = self.socks_proxy_sessions[socksProxy]
|
184
|
+
# add aiohttp_proxy for python as exclusion
|
185
|
+
elif self.aiohttp_proxy:
|
186
|
+
final_proxy = self.aiohttp_proxy
|
187
|
+
|
188
|
+
proxyAgentSet = final_proxy is not None or socksProxy is not None
|
189
|
+
self.checkConflictingProxies(proxyAgentSet, proxyUrl)
|
190
|
+
|
191
|
+
# avoid old proxies mixing
|
192
|
+
if (self.aiohttp_proxy is not None) and (proxyUrl is not None or httpProxy is not None or httpsProxy is not None or socksProxy is not None):
|
193
|
+
raise NotSupported(self.id + ' you have set multiple proxies, please use one or another')
|
194
|
+
|
195
|
+
# log
|
196
|
+
if self.verbose:
|
197
|
+
self.log("\nfetch Request:", self.id, method, url, "RequestHeaders:", request_headers, "RequestBody:", body)
|
198
|
+
self.logger.debug("%s %s, Request: %s %s", method, url, headers, body)
|
199
|
+
# end of proxies & headers
|
200
|
+
|
201
|
+
request_body = body
|
202
|
+
encoded_body = body.encode() if body else None
|
203
|
+
self.open()
|
204
|
+
final_session = proxy_session if proxy_session is not None else self.session
|
205
|
+
session_method = getattr(final_session, method.lower())
|
206
|
+
|
207
|
+
http_response = None
|
208
|
+
http_status_code = None
|
209
|
+
http_status_text = None
|
210
|
+
json_response = None
|
211
|
+
try:
|
212
|
+
async with session_method(yarl.URL(url, encoded=True),
|
213
|
+
data=encoded_body,
|
214
|
+
headers=request_headers,
|
215
|
+
timeout=(self.timeout / 1000),
|
216
|
+
proxy=final_proxy) as response:
|
217
|
+
http_response = await response.text(errors='replace')
|
218
|
+
# CIMultiDictProxy
|
219
|
+
raw_headers = response.headers
|
220
|
+
headers = {}
|
221
|
+
for header in raw_headers:
|
222
|
+
if header in headers:
|
223
|
+
headers[header] = headers[header] + ', ' + raw_headers[header]
|
224
|
+
else:
|
225
|
+
headers[header] = raw_headers[header]
|
226
|
+
http_status_code = response.status
|
227
|
+
http_status_text = response.reason
|
228
|
+
http_response = self.on_rest_response(http_status_code, http_status_text, url, method, headers, http_response, request_headers, request_body)
|
229
|
+
json_response = self.parse_json(http_response)
|
230
|
+
if self.enableLastHttpResponse:
|
231
|
+
self.last_http_response = http_response
|
232
|
+
if self.enableLastResponseHeaders:
|
233
|
+
self.last_response_headers = headers
|
234
|
+
if self.enableLastJsonResponse:
|
235
|
+
self.last_json_response = json_response
|
236
|
+
if self.verbose:
|
237
|
+
self.log("\nfetch Response:", self.id, method, url, http_status_code, "ResponseHeaders:", headers, "ResponseBody:", http_response)
|
238
|
+
self.logger.debug("%s %s, Response: %s %s %s", method, url, http_status_code, headers, http_response)
|
239
|
+
|
240
|
+
except socket.gaierror as e:
|
241
|
+
details = ' '.join([self.id, method, url])
|
242
|
+
raise ExchangeNotAvailable(details) from e
|
243
|
+
|
244
|
+
except (concurrent.futures.TimeoutError, asyncio.TimeoutError) as e:
|
245
|
+
details = ' '.join([self.id, method, url])
|
246
|
+
raise RequestTimeout(details) from e
|
247
|
+
|
248
|
+
except aiohttp.ClientConnectionError as e:
|
249
|
+
details = ' '.join([self.id, method, url])
|
250
|
+
raise ExchangeNotAvailable(details) from e
|
251
|
+
|
252
|
+
except aiohttp.ClientError as e: # base exception class
|
253
|
+
details = ' '.join([self.id, method, url])
|
254
|
+
raise ExchangeError(details) from e
|
255
|
+
|
256
|
+
self.handle_errors(http_status_code, http_status_text, url, method, headers, http_response, json_response, request_headers, request_body)
|
257
|
+
self.handle_http_status_code(http_status_code, http_status_text, url, method, http_response)
|
258
|
+
if json_response is not None:
|
259
|
+
return json_response
|
260
|
+
if self.is_text_response(headers):
|
261
|
+
return http_response
|
262
|
+
if http_response == '' or http_response is None:
|
263
|
+
return http_response
|
264
|
+
return response.content
|
265
|
+
|
266
|
+
async def load_markets_helper(self, reload=False, params={}):
|
267
|
+
if not reload:
|
268
|
+
if self.markets:
|
269
|
+
if not self.markets_by_id:
|
270
|
+
return self.set_markets(self.markets)
|
271
|
+
return self.markets
|
272
|
+
currencies = None
|
273
|
+
if self.has['fetchCurrencies'] is True:
|
274
|
+
currencies = await self.fetch_currencies()
|
275
|
+
markets = await self.fetch_markets(params)
|
276
|
+
return self.set_markets(markets, currencies)
|
277
|
+
|
278
|
+
async def load_markets(self, reload=False, params={}):
|
279
|
+
if (reload and not self.reloading_markets) or not self.markets_loading:
|
280
|
+
self.reloading_markets = True
|
281
|
+
coroutine = self.load_markets_helper(reload, params)
|
282
|
+
# coroutines can only be awaited once so we wrap it in a task
|
283
|
+
self.markets_loading = asyncio.ensure_future(coroutine)
|
284
|
+
try:
|
285
|
+
result = await self.markets_loading
|
286
|
+
except asyncio.CancelledError as e: # CancelledError is a base exception so we need to catch it explicitly
|
287
|
+
self.reloading_markets = False
|
288
|
+
self.markets_loading = None
|
289
|
+
raise e
|
290
|
+
except Exception as e:
|
291
|
+
self.reloading_markets = False
|
292
|
+
self.markets_loading = None
|
293
|
+
raise e
|
294
|
+
self.reloading_markets = False
|
295
|
+
return result
|
296
|
+
|
297
|
+
async def load_fees(self, reload=False):
|
298
|
+
if not reload:
|
299
|
+
if self.loaded_fees != Exchange.loaded_fees:
|
300
|
+
return self.loaded_fees
|
301
|
+
self.loaded_fees = self.deep_extend(self.loaded_fees, await self.fetch_fees())
|
302
|
+
return self.loaded_fees
|
303
|
+
|
304
|
+
async def fetch_markets(self, params={}):
|
305
|
+
# markets are returned as a list
|
306
|
+
# currencies are returned as a dict
|
307
|
+
# this is for historical reasons
|
308
|
+
# and may be changed for consistency later
|
309
|
+
return self.to_array(self.markets)
|
310
|
+
|
311
|
+
async def fetch_currencies(self, params={}):
|
312
|
+
# markets are returned as a list
|
313
|
+
# currencies are returned as a dict
|
314
|
+
# this is for historical reasons
|
315
|
+
# and may be changed for consistency later
|
316
|
+
return self.currencies
|
317
|
+
|
318
|
+
async def fetchOHLCVC(self, symbol, timeframe='1m', since=None, limit=None, params={}):
|
319
|
+
return await self.fetch_ohlcvc(symbol, timeframe, since, limit, params)
|
320
|
+
|
321
|
+
async def fetch_full_tickers(self, symbols=None, params={}):
|
322
|
+
return await self.fetch_tickers(symbols, params)
|
323
|
+
|
324
|
+
async def sleep(self, milliseconds):
|
325
|
+
return await asyncio.sleep(milliseconds / 1000)
|
326
|
+
|
327
|
+
async def spawn_async(self, method, *args):
|
328
|
+
try:
|
329
|
+
await method(*args)
|
330
|
+
except Exception:
|
331
|
+
# todo: handle spawned errors
|
332
|
+
pass
|
333
|
+
|
334
|
+
def spawn(self, method, *args):
|
335
|
+
def callback(asyncio_future):
|
336
|
+
exception = asyncio_future.exception()
|
337
|
+
if exception is None:
|
338
|
+
future.resolve(asyncio_future.result())
|
339
|
+
else:
|
340
|
+
future.reject(exception)
|
341
|
+
future = Future()
|
342
|
+
task = self.asyncio_loop.create_task(method(*args))
|
343
|
+
task.add_done_callback(callback)
|
344
|
+
return future
|
345
|
+
|
346
|
+
# -----------------------------------------------------------------------
|
347
|
+
# WS/PRO code
|
348
|
+
|
349
|
+
@staticmethod
|
350
|
+
def inflate(data):
|
351
|
+
return inflate(data)
|
352
|
+
|
353
|
+
@staticmethod
|
354
|
+
def inflate64(data):
|
355
|
+
return inflate64(data)
|
356
|
+
|
357
|
+
@staticmethod
|
358
|
+
def gunzip(data):
|
359
|
+
return gunzip(data)
|
360
|
+
|
361
|
+
def order_book(self, snapshot={}, depth=None):
|
362
|
+
return OrderBook(snapshot, depth)
|
363
|
+
|
364
|
+
def indexed_order_book(self, snapshot={}, depth=None):
|
365
|
+
return IndexedOrderBook(snapshot, depth)
|
366
|
+
|
367
|
+
def counted_order_book(self, snapshot={}, depth=None):
|
368
|
+
return CountedOrderBook(snapshot, depth)
|
369
|
+
|
370
|
+
def client(self, url):
|
371
|
+
self.clients = self.clients or {}
|
372
|
+
if url not in self.clients:
|
373
|
+
on_message = self.handle_message
|
374
|
+
on_error = self.on_error
|
375
|
+
on_close = self.on_close
|
376
|
+
on_connected = self.on_connected
|
377
|
+
# decide client type here: aiohttp ws / websockets / signalr / socketio
|
378
|
+
ws_options = self.safe_value(self.options, 'ws', {})
|
379
|
+
options = self.extend(self.streaming, {
|
380
|
+
'log': getattr(self, 'log'),
|
381
|
+
'ping': getattr(self, 'ping', None),
|
382
|
+
'verbose': self.verbose,
|
383
|
+
'throttle': Throttler(self.tokenBucket, self.asyncio_loop),
|
384
|
+
'asyncio_loop': self.asyncio_loop,
|
385
|
+
}, ws_options)
|
386
|
+
self.clients[url] = FastClient(url, on_message, on_error, on_close, on_connected, options)
|
387
|
+
self.clients[url].proxy = self.get_ws_proxy()
|
388
|
+
return self.clients[url]
|
389
|
+
|
390
|
+
def get_ws_proxy(self):
|
391
|
+
httpProxy, httpsProxy, socksProxy = self.check_ws_proxy_settings()
|
392
|
+
if httpProxy:
|
393
|
+
return httpProxy
|
394
|
+
elif httpsProxy:
|
395
|
+
return httpsProxy
|
396
|
+
elif socksProxy:
|
397
|
+
return socksProxy
|
398
|
+
return None
|
399
|
+
|
400
|
+
def delay(self, timeout, method, *args):
|
401
|
+
return self.asyncio_loop.call_later(timeout / 1000, self.spawn, method, *args)
|
402
|
+
|
403
|
+
def handle_message(self, client, message):
|
404
|
+
always = True
|
405
|
+
if always:
|
406
|
+
raise NotSupported(self.id + '.handle_message() not implemented yet')
|
407
|
+
return {}
|
408
|
+
|
409
|
+
def watch_multiple(self, url, message_hashes, message=None, subscribe_hashes=None, subscription=None):
|
410
|
+
# base exchange self.open starts the aiohttp Session in an async context
|
411
|
+
self.open()
|
412
|
+
backoff_delay = 0
|
413
|
+
client = self.client(url)
|
414
|
+
|
415
|
+
future = Future.race([client.future(message_hash) for message_hash in message_hashes])
|
416
|
+
|
417
|
+
missing_subscriptions = []
|
418
|
+
if subscribe_hashes is not None:
|
419
|
+
for subscribe_hash in subscribe_hashes:
|
420
|
+
if subscribe_hash not in client.subscriptions:
|
421
|
+
missing_subscriptions.append(subscribe_hash)
|
422
|
+
client.subscriptions[subscribe_hash] = subscription or True
|
423
|
+
|
424
|
+
connected = client.connected if client.connected.done() \
|
425
|
+
else asyncio.ensure_future(client.connect(self.session, backoff_delay))
|
426
|
+
|
427
|
+
def after(fut):
|
428
|
+
# todo: decouple signing from subscriptions
|
429
|
+
options = self.safe_value(self.options, 'ws')
|
430
|
+
cost = self.safe_value(options, 'cost', 1)
|
431
|
+
if message:
|
432
|
+
async def send_message():
|
433
|
+
if self.enableRateLimit:
|
434
|
+
await client.throttle(cost)
|
435
|
+
try:
|
436
|
+
await client.send(message)
|
437
|
+
except ConnectionError as e:
|
438
|
+
client.on_error(e)
|
439
|
+
except Exception as e:
|
440
|
+
client.on_error(e)
|
441
|
+
asyncio.ensure_future(send_message())
|
442
|
+
|
443
|
+
if missing_subscriptions:
|
444
|
+
connected.add_done_callback(after)
|
445
|
+
|
446
|
+
return future
|
447
|
+
|
448
|
+
def watch(self, url, message_hash, message=None, subscribe_hash=None, subscription=None):
|
449
|
+
# base exchange self.open starts the aiohttp Session in an async context
|
450
|
+
self.open()
|
451
|
+
backoff_delay = 0
|
452
|
+
client = self.client(url)
|
453
|
+
if subscribe_hash is None and message_hash in client.futures:
|
454
|
+
return client.futures[message_hash]
|
455
|
+
future = client.future(message_hash)
|
456
|
+
|
457
|
+
subscribed = client.subscriptions.get(subscribe_hash)
|
458
|
+
|
459
|
+
if not subscribed:
|
460
|
+
client.subscriptions[subscribe_hash] = subscription or True
|
461
|
+
|
462
|
+
connected = client.connected if client.connected.done() \
|
463
|
+
else asyncio.ensure_future(client.connect(self.session, backoff_delay))
|
464
|
+
|
465
|
+
def after(fut):
|
466
|
+
# todo: decouple signing from subscriptions
|
467
|
+
options = self.safe_value(self.options, 'ws')
|
468
|
+
cost = self.safe_value(options, 'cost', 1)
|
469
|
+
if message:
|
470
|
+
async def send_message():
|
471
|
+
if self.enableRateLimit:
|
472
|
+
await client.throttle(cost)
|
473
|
+
try:
|
474
|
+
await client.send(message)
|
475
|
+
except ConnectionError as e:
|
476
|
+
client.on_error(e)
|
477
|
+
except Exception as e:
|
478
|
+
client.on_error(e)
|
479
|
+
asyncio.ensure_future(send_message())
|
480
|
+
|
481
|
+
if not subscribed:
|
482
|
+
connected.add_done_callback(after)
|
483
|
+
|
484
|
+
return future
|
485
|
+
|
486
|
+
def on_connected(self, client, message=None):
|
487
|
+
# for user hooks
|
488
|
+
# print('Connected to', client.url)
|
489
|
+
pass
|
490
|
+
|
491
|
+
def on_error(self, client, error):
|
492
|
+
if client.url in self.clients and self.clients[client.url].error:
|
493
|
+
del self.clients[client.url]
|
494
|
+
|
495
|
+
def on_close(self, client, error):
|
496
|
+
if client.error:
|
497
|
+
# connection closed by the user or due to an error
|
498
|
+
pass
|
499
|
+
else:
|
500
|
+
# server disconnected a working connection
|
501
|
+
if client.url in self.clients:
|
502
|
+
del self.clients[client.url]
|
503
|
+
|
504
|
+
async def ws_close(self):
|
505
|
+
if self.clients:
|
506
|
+
await asyncio.wait([asyncio.create_task(client.close()) for client in self.clients.values()], return_when=asyncio.ALL_COMPLETED)
|
507
|
+
for url in self.clients.copy():
|
508
|
+
del self.clients[url]
|
509
|
+
|
510
|
+
async def load_order_book(self, client, messageHash, symbol, limit=None, params={}):
|
511
|
+
if symbol not in self.orderbooks:
|
512
|
+
client.reject(ExchangeError(self.id + ' loadOrderBook() orderbook is not initiated'), messageHash)
|
513
|
+
return
|
514
|
+
try:
|
515
|
+
maxRetries = self.handle_option('watchOrderBook', 'maxRetries', 3)
|
516
|
+
tries = 0
|
517
|
+
stored = self.orderbooks[symbol]
|
518
|
+
while tries < maxRetries:
|
519
|
+
cache = stored.cache
|
520
|
+
order_book = await self.fetch_order_book(symbol, limit, params)
|
521
|
+
index = self.get_cache_index(order_book, cache)
|
522
|
+
if index >= 0:
|
523
|
+
stored.reset(order_book)
|
524
|
+
self.handle_deltas(stored, cache[index:])
|
525
|
+
cache.clear()
|
526
|
+
client.resolve(stored, messageHash)
|
527
|
+
return
|
528
|
+
tries += 1
|
529
|
+
client.reject(ExchangeError(self.id + ' nonce is behind cache after ' + str(maxRetries) + ' tries.'), messageHash)
|
530
|
+
del self.clients[client.url]
|
531
|
+
except BaseError as e:
|
532
|
+
client.reject(e, messageHash)
|
533
|
+
await self.load_order_book(client, messageHash, symbol, limit, params)
|
534
|
+
|
535
|
+
def format_scientific_notation_ftx(self, n):
|
536
|
+
if n == 0:
|
537
|
+
return '0e-00'
|
538
|
+
return format(n, 'g')
|
539
|
+
|
540
|
+
# ########################################################################
|
541
|
+
# ########################################################################
|
542
|
+
# ########################################################################
|
543
|
+
# ########################################################################
|
544
|
+
# ######## ######## ########
|
545
|
+
# ######## ######## ########
|
546
|
+
# ######## ######## ########
|
547
|
+
# ######## ######## ########
|
548
|
+
# ######## ######################## ########################
|
549
|
+
# ######## ######################## ########################
|
550
|
+
# ######## ######################## ########################
|
551
|
+
# ######## ######################## ########################
|
552
|
+
# ######## ######## ########
|
553
|
+
# ######## ######## ########
|
554
|
+
# ######## ######## ########
|
555
|
+
# ######## ######## ########
|
556
|
+
# ########################################################################
|
557
|
+
# ########################################################################
|
558
|
+
# ########################################################################
|
559
|
+
# ########################################################################
|
560
|
+
# ######## ######## ######## ########
|
561
|
+
# ######## ######## ######## ########
|
562
|
+
# ######## ######## ######## ########
|
563
|
+
# ######## ######## ######## ########
|
564
|
+
# ################ ######################## ################
|
565
|
+
# ################ ######################## ################
|
566
|
+
# ################ ######################## ################
|
567
|
+
# ################ ######################## ################
|
568
|
+
# ######## ######## ################ ################
|
569
|
+
# ######## ######## ################ ################
|
570
|
+
# ######## ######## ################ ################
|
571
|
+
# ######## ######## ################ ################
|
572
|
+
# ########################################################################
|
573
|
+
# ########################################################################
|
574
|
+
# ########################################################################
|
575
|
+
# ########################################################################
|
576
|
+
|
577
|
+
# METHODS BELOW THIS LINE ARE TRANSPILED FROM JAVASCRIPT TO PYTHON AND PHP
|
578
|
+
|
579
|
+
async def fetch_accounts(self, params={}):
|
580
|
+
raise NotSupported(self.id + ' fetchAccounts() is not supported yet')
|
581
|
+
|
582
|
+
async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
583
|
+
raise NotSupported(self.id + ' fetchTrades() is not supported yet')
|
584
|
+
|
585
|
+
async def fetch_trades_ws(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
586
|
+
raise NotSupported(self.id + ' fetchTradesWs() is not supported yet')
|
587
|
+
|
588
|
+
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
589
|
+
if self.has['watchLiquidationsForSymbols']:
|
590
|
+
return await self.watch_liquidations_for_symbols([symbol], since, limit, params)
|
591
|
+
raise NotSupported(self.id + ' watchLiquidations() is not supported yet')
|
592
|
+
|
593
|
+
async def watch_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
|
594
|
+
raise NotSupported(self.id + ' watchLiquidationsForSymbols() is not supported yet')
|
595
|
+
|
596
|
+
async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
597
|
+
if self.has['watchMyLiquidationsForSymbols']:
|
598
|
+
return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
|
599
|
+
raise NotSupported(self.id + ' watchMyLiquidations() is not supported yet')
|
600
|
+
|
601
|
+
async def watch_my_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
|
602
|
+
raise NotSupported(self.id + ' watchMyLiquidationsForSymbols() is not supported yet')
|
603
|
+
|
604
|
+
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
605
|
+
raise NotSupported(self.id + ' watchTrades() is not supported yet')
|
606
|
+
|
607
|
+
async def un_watch_trades(self, symbol: str, params={}):
|
608
|
+
raise NotSupported(self.id + ' unWatchTrades() is not supported yet')
|
609
|
+
|
610
|
+
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
|
611
|
+
raise NotSupported(self.id + ' watchTradesForSymbols() is not supported yet')
|
612
|
+
|
613
|
+
async def un_watch_trades_for_symbols(self, symbols: List[str], params={}):
|
614
|
+
raise NotSupported(self.id + ' unWatchTradesForSymbols() is not supported yet')
|
615
|
+
|
616
|
+
async def watch_my_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
|
617
|
+
raise NotSupported(self.id + ' watchMyTradesForSymbols() is not supported yet')
|
618
|
+
|
619
|
+
async def watch_orders_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
|
620
|
+
raise NotSupported(self.id + ' watchOrdersForSymbols() is not supported yet')
|
621
|
+
|
622
|
+
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
|
623
|
+
raise NotSupported(self.id + ' watchOHLCVForSymbols() is not supported yet')
|
624
|
+
|
625
|
+
async def un_watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], params={}):
|
626
|
+
raise NotSupported(self.id + ' unWatchOHLCVForSymbols() is not supported yet')
|
627
|
+
|
628
|
+
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}):
|
629
|
+
raise NotSupported(self.id + ' watchOrderBookForSymbols() is not supported yet')
|
630
|
+
|
631
|
+
async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}):
|
632
|
+
raise NotSupported(self.id + ' unWatchOrderBookForSymbols() is not supported yet')
|
633
|
+
|
634
|
+
async def fetch_deposit_addresses(self, codes: Strings = None, params={}):
|
635
|
+
raise NotSupported(self.id + ' fetchDepositAddresses() is not supported yet')
|
636
|
+
|
637
|
+
async def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
|
638
|
+
raise NotSupported(self.id + ' fetchOrderBook() is not supported yet')
|
639
|
+
|
640
|
+
async def fetch_order_book_ws(self, symbol: str, limit: Int = None, params={}):
|
641
|
+
raise NotSupported(self.id + ' fetchOrderBookWs() is not supported yet')
|
642
|
+
|
643
|
+
async def fetch_margin_mode(self, symbol: str, params={}):
|
644
|
+
if self.has['fetchMarginModes']:
|
645
|
+
marginModes = await self.fetch_margin_modes([symbol], params)
|
646
|
+
return self.safe_dict(marginModes, symbol)
|
647
|
+
else:
|
648
|
+
raise NotSupported(self.id + ' fetchMarginMode() is not supported yet')
|
649
|
+
|
650
|
+
async def fetch_margin_modes(self, symbols: Strings = None, params={}):
|
651
|
+
raise NotSupported(self.id + ' fetchMarginModes() is not supported yet')
|
652
|
+
|
653
|
+
async def fetch_rest_order_book_safe(self, symbol, limit=None, params={}):
|
654
|
+
fetchSnapshotMaxRetries = self.handle_option('watchOrderBook', 'maxRetries', 3)
|
655
|
+
for i in range(0, fetchSnapshotMaxRetries):
|
656
|
+
try:
|
657
|
+
orderBook = await self.fetch_order_book(symbol, limit, params)
|
658
|
+
return orderBook
|
659
|
+
except Exception as e:
|
660
|
+
if (i + 1) == fetchSnapshotMaxRetries:
|
661
|
+
raise e
|
662
|
+
return None
|
663
|
+
|
664
|
+
async def watch_order_book(self, symbol: str, limit: Int = None, params={}):
|
665
|
+
raise NotSupported(self.id + ' watchOrderBook() is not supported yet')
|
666
|
+
|
667
|
+
async def un_watch_order_book(self, symbol: str, params={}):
|
668
|
+
raise NotSupported(self.id + ' unWatchOrderBook() is not supported yet')
|
669
|
+
|
670
|
+
async def fetch_time(self, params={}):
|
671
|
+
raise NotSupported(self.id + ' fetchTime() is not supported yet')
|
672
|
+
|
673
|
+
async def fetch_trading_limits(self, symbols: Strings = None, params={}):
|
674
|
+
raise NotSupported(self.id + ' fetchTradingLimits() is not supported yet')
|
675
|
+
|
676
|
+
async def fetch_cross_borrow_rates(self, params={}):
|
677
|
+
raise NotSupported(self.id + ' fetchCrossBorrowRates() is not supported yet')
|
678
|
+
|
679
|
+
async def fetch_isolated_borrow_rates(self, params={}):
|
680
|
+
raise NotSupported(self.id + ' fetchIsolatedBorrowRates() is not supported yet')
|
681
|
+
|
682
|
+
async def fetch_leverage_tiers(self, symbols: Strings = None, params={}):
|
683
|
+
raise NotSupported(self.id + ' fetchLeverageTiers() is not supported yet')
|
684
|
+
|
685
|
+
async def fetch_funding_rates(self, symbols: Strings = None, params={}):
|
686
|
+
raise NotSupported(self.id + ' fetchFundingRates() is not supported yet')
|
687
|
+
|
688
|
+
async def fetch_funding_intervals(self, symbols: Strings = None, params={}):
|
689
|
+
raise NotSupported(self.id + ' fetchFundingIntervals() is not supported yet')
|
690
|
+
|
691
|
+
async def watch_funding_rate(self, symbol: str, params={}):
|
692
|
+
raise NotSupported(self.id + ' watchFundingRate() is not supported yet')
|
693
|
+
|
694
|
+
async def watch_funding_rates(self, symbols: List[str], params={}):
|
695
|
+
raise NotSupported(self.id + ' watchFundingRates() is not supported yet')
|
696
|
+
|
697
|
+
async def watch_funding_rates_for_symbols(self, symbols: List[str], params={}):
|
698
|
+
return await self.watch_funding_rates(symbols, params)
|
699
|
+
|
700
|
+
async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}):
|
701
|
+
raise NotSupported(self.id + ' transfer() is not supported yet')
|
702
|
+
|
703
|
+
async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
704
|
+
raise NotSupported(self.id + ' withdraw() is not supported yet')
|
705
|
+
|
706
|
+
async def create_deposit_address(self, code: str, params={}):
|
707
|
+
raise NotSupported(self.id + ' createDepositAddress() is not supported yet')
|
708
|
+
|
709
|
+
async def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
|
710
|
+
raise NotSupported(self.id + ' setLeverage() is not supported yet')
|
711
|
+
|
712
|
+
async def fetch_leverage(self, symbol: str, params={}):
|
713
|
+
if self.has['fetchLeverages']:
|
714
|
+
leverages = await self.fetch_leverages([symbol], params)
|
715
|
+
return self.safe_dict(leverages, symbol)
|
716
|
+
else:
|
717
|
+
raise NotSupported(self.id + ' fetchLeverage() is not supported yet')
|
718
|
+
|
719
|
+
async def fetch_leverages(self, symbols: Strings = None, params={}):
|
720
|
+
raise NotSupported(self.id + ' fetchLeverages() is not supported yet')
|
721
|
+
|
722
|
+
async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
|
723
|
+
raise NotSupported(self.id + ' setPositionMode() is not supported yet')
|
724
|
+
|
725
|
+
async def add_margin(self, symbol: str, amount: float, params={}):
|
726
|
+
raise NotSupported(self.id + ' addMargin() is not supported yet')
|
727
|
+
|
728
|
+
async def reduce_margin(self, symbol: str, amount: float, params={}):
|
729
|
+
raise NotSupported(self.id + ' reduceMargin() is not supported yet')
|
730
|
+
|
731
|
+
async def set_margin(self, symbol: str, amount: float, params={}):
|
732
|
+
raise NotSupported(self.id + ' setMargin() is not supported yet')
|
733
|
+
|
734
|
+
async def fetch_long_short_ratio(self, symbol: str, timeframe: Str = None, params={}):
|
735
|
+
raise NotSupported(self.id + ' fetchLongShortRatio() is not supported yet')
|
736
|
+
|
737
|
+
async def fetch_long_short_ratio_history(self, symbol: Str = None, timeframe: Str = None, since: Int = None, limit: Int = None, params={}):
|
738
|
+
raise NotSupported(self.id + ' fetchLongShortRatioHistory() is not supported yet')
|
739
|
+
|
740
|
+
async def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}):
|
741
|
+
"""
|
742
|
+
fetches the history of margin added or reduced from contract isolated positions
|
743
|
+
:param str [symbol]: unified market symbol
|
744
|
+
:param str [type]: "add" or "reduce"
|
745
|
+
:param int [since]: timestamp in ms of the earliest change to fetch
|
746
|
+
:param int [limit]: the maximum amount of changes to fetch
|
747
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
748
|
+
:returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
749
|
+
"""
|
750
|
+
raise NotSupported(self.id + ' fetchMarginAdjustmentHistory() is not supported yet')
|
751
|
+
|
752
|
+
async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
753
|
+
raise NotSupported(self.id + ' setMarginMode() is not supported yet')
|
754
|
+
|
755
|
+
async def fetch_deposit_addresses_by_network(self, code: str, params={}):
|
756
|
+
raise NotSupported(self.id + ' fetchDepositAddressesByNetwork() is not supported yet')
|
757
|
+
|
758
|
+
async def fetch_open_interest_history(self, symbol: str, timeframe='1h', since: Int = None, limit: Int = None, params={}):
|
759
|
+
raise NotSupported(self.id + ' fetchOpenInterestHistory() is not supported yet')
|
760
|
+
|
761
|
+
async def fetch_open_interest(self, symbol: str, params={}):
|
762
|
+
raise NotSupported(self.id + ' fetchOpenInterest() is not supported yet')
|
763
|
+
|
764
|
+
async def fetch_open_interests(self, symbols: Strings = None, params={}):
|
765
|
+
raise NotSupported(self.id + ' fetchOpenInterests() is not supported yet')
|
766
|
+
|
767
|
+
async def sign_in(self, params={}):
|
768
|
+
raise NotSupported(self.id + ' signIn() is not supported yet')
|
769
|
+
|
770
|
+
async def fetch_payment_methods(self, params={}):
|
771
|
+
raise NotSupported(self.id + ' fetchPaymentMethods() is not supported yet')
|
772
|
+
|
773
|
+
async def fetch_borrow_rate(self, code: str, amount: float, params={}):
|
774
|
+
raise NotSupported(self.id + ' fetchBorrowRate is deprecated, please use fetchCrossBorrowRate or fetchIsolatedBorrowRate instead')
|
775
|
+
|
776
|
+
async def repay_cross_margin(self, code: str, amount: float, params={}):
|
777
|
+
raise NotSupported(self.id + ' repayCrossMargin is not support yet')
|
778
|
+
|
779
|
+
async def repay_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
|
780
|
+
raise NotSupported(self.id + ' repayIsolatedMargin is not support yet')
|
781
|
+
|
782
|
+
async def borrow_cross_margin(self, code: str, amount: float, params={}):
|
783
|
+
raise NotSupported(self.id + ' borrowCrossMargin is not support yet')
|
784
|
+
|
785
|
+
async def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
|
786
|
+
raise NotSupported(self.id + ' borrowIsolatedMargin is not support yet')
|
787
|
+
|
788
|
+
async def borrow_margin(self, code: str, amount: float, symbol: Str = None, params={}):
|
789
|
+
raise NotSupported(self.id + ' borrowMargin is deprecated, please use borrowCrossMargin or borrowIsolatedMargin instead')
|
790
|
+
|
791
|
+
async def repay_margin(self, code: str, amount: float, symbol: Str = None, params={}):
|
792
|
+
raise NotSupported(self.id + ' repayMargin is deprecated, please use repayCrossMargin or repayIsolatedMargin instead')
|
793
|
+
|
794
|
+
async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
795
|
+
message = ''
|
796
|
+
if self.has['fetchTrades']:
|
797
|
+
message = '. If you want to build OHLCV candles from trade executions data, visit https://github.com/ccxt/ccxt/tree/master/examples/ and see "build-ohlcv-bars" file'
|
798
|
+
raise NotSupported(self.id + ' fetchOHLCV() is not supported yet' + message)
|
799
|
+
|
800
|
+
async def fetch_ohlcv_ws(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
801
|
+
message = ''
|
802
|
+
if self.has['fetchTradesWs']:
|
803
|
+
message = '. If you want to build OHLCV candles from trade executions data, visit https://github.com/ccxt/ccxt/tree/master/examples/ and see "build-ohlcv-bars" file'
|
804
|
+
raise NotSupported(self.id + ' fetchOHLCVWs() is not supported yet. Try using fetchOHLCV instead.' + message)
|
805
|
+
|
806
|
+
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
807
|
+
raise NotSupported(self.id + ' watchOHLCV() is not supported yet')
|
808
|
+
|
809
|
+
async def fetch_web_endpoint(self, method, endpointMethod, returnAsJson, startRegex=None, endRegex=None):
|
810
|
+
errorMessage = ''
|
811
|
+
options = self.safe_value(self.options, method, {})
|
812
|
+
muteOnFailure = self.safe_bool(options, 'webApiMuteFailure', True)
|
813
|
+
try:
|
814
|
+
# if it was not explicitly disabled, then don't fetch
|
815
|
+
if self.safe_bool(options, 'webApiEnable', True) is not True:
|
816
|
+
return None
|
817
|
+
maxRetries = self.safe_value(options, 'webApiRetries', 10)
|
818
|
+
response = None
|
819
|
+
retry = 0
|
820
|
+
shouldBreak = False
|
821
|
+
while(retry < maxRetries):
|
822
|
+
try:
|
823
|
+
response = await getattr(self, endpointMethod)({})
|
824
|
+
shouldBreak = True
|
825
|
+
break
|
826
|
+
except Exception as e:
|
827
|
+
retry = retry + 1
|
828
|
+
if retry == maxRetries:
|
829
|
+
raise e
|
830
|
+
if shouldBreak:
|
831
|
+
break # self is needed because of GO
|
832
|
+
content = response
|
833
|
+
if startRegex is not None:
|
834
|
+
splitted_by_start = content.split(startRegex)
|
835
|
+
content = splitted_by_start[1] # we need second part after start
|
836
|
+
if endRegex is not None:
|
837
|
+
splitted_by_end = content.split(endRegex)
|
838
|
+
content = splitted_by_end[0] # we need first part after start
|
839
|
+
if returnAsJson and (isinstance(content, str)):
|
840
|
+
jsoned = self.parse_json(content.strip()) # content should be trimmed before json parsing
|
841
|
+
if jsoned:
|
842
|
+
return jsoned # if parsing was not successfull, exception should be thrown
|
843
|
+
else:
|
844
|
+
raise BadResponse('could not parse the response into json')
|
845
|
+
else:
|
846
|
+
return content
|
847
|
+
except Exception as e:
|
848
|
+
errorMessage = self.id + ' ' + method + '() failed to fetch correct data from website. Probably webpage markup has been changed, breaking the page custom parser.'
|
849
|
+
if muteOnFailure:
|
850
|
+
return None
|
851
|
+
else:
|
852
|
+
raise BadResponse(errorMessage)
|
853
|
+
|
854
|
+
async def fetch_l2_order_book(self, symbol: str, limit: Int = None, params={}):
|
855
|
+
orderbook = await self.fetch_order_book(symbol, limit, params)
|
856
|
+
return self.extend(orderbook, {
|
857
|
+
'asks': self.sort_by(self.aggregate(orderbook['asks']), 0),
|
858
|
+
'bids': self.sort_by(self.aggregate(orderbook['bids']), 0, True),
|
859
|
+
})
|
860
|
+
|
861
|
+
async def load_trading_limits(self, symbols: Strings = None, reload=False, params={}):
|
862
|
+
if self.has['fetchTradingLimits']:
|
863
|
+
if reload or not ('limitsLoaded' in self.options):
|
864
|
+
response = await self.fetch_trading_limits(symbols)
|
865
|
+
for i in range(0, len(symbols)):
|
866
|
+
symbol = symbols[i]
|
867
|
+
self.markets[symbol] = self.deep_extend(self.markets[symbol], response[symbol])
|
868
|
+
self.options['limitsLoaded'] = self.milliseconds()
|
869
|
+
return self.markets
|
870
|
+
|
871
|
+
async def fetch2(self, path, api: Any = 'public', method='GET', params={}, headers: Any = None, body: Any = None, config={}):
|
872
|
+
if self.enableRateLimit:
|
873
|
+
cost = self.calculate_rate_limiter_cost(api, method, path, params, config)
|
874
|
+
await self.throttle(cost)
|
875
|
+
self.lastRestRequestTimestamp = self.milliseconds()
|
876
|
+
request = self.sign(path, api, method, params, headers, body)
|
877
|
+
self.last_request_headers = request['headers']
|
878
|
+
self.last_request_body = request['body']
|
879
|
+
self.last_request_url = request['url']
|
880
|
+
retries = None
|
881
|
+
retries, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailure', 0)
|
882
|
+
retryDelay = None
|
883
|
+
retryDelay, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailureDelay', 0)
|
884
|
+
for i in range(0, retries + 1):
|
885
|
+
try:
|
886
|
+
return await self.fetch(request['url'], request['method'], request['headers'], request['body'])
|
887
|
+
except Exception as e:
|
888
|
+
if isinstance(e, OperationFailed):
|
889
|
+
if i < retries:
|
890
|
+
if self.verbose:
|
891
|
+
self.log('Request failed with the error: ' + str(e) + ', retrying ' + (i + str(1)) + ' of ' + str(retries) + '...')
|
892
|
+
if (retryDelay is not None) and (retryDelay != 0):
|
893
|
+
await self.sleep(retryDelay)
|
894
|
+
else:
|
895
|
+
raise e
|
896
|
+
else:
|
897
|
+
raise e
|
898
|
+
return None # self line is never reached, but exists for c# value return requirement
|
899
|
+
|
900
|
+
async def request(self, path, api: Any = 'public', method='GET', params={}, headers: Any = None, body: Any = None, config={}):
|
901
|
+
return await self.fetch2(path, api, method, params, headers, body, config)
|
902
|
+
|
903
|
+
async def load_accounts(self, reload=False, params={}):
|
904
|
+
if reload:
|
905
|
+
self.accounts = await self.fetch_accounts(params)
|
906
|
+
else:
|
907
|
+
if self.accounts:
|
908
|
+
return self.accounts
|
909
|
+
else:
|
910
|
+
self.accounts = await self.fetch_accounts(params)
|
911
|
+
self.accountsById = self.index_by(self.accounts, 'id')
|
912
|
+
return self.accounts
|
913
|
+
|
914
|
+
async def edit_limit_buy_order(self, id: str, symbol: str, amount: float, price: Num = None, params={}):
|
915
|
+
return await self.edit_limit_order(id, symbol, 'buy', amount, price, params)
|
916
|
+
|
917
|
+
async def edit_limit_sell_order(self, id: str, symbol: str, amount: float, price: Num = None, params={}):
|
918
|
+
return await self.edit_limit_order(id, symbol, 'sell', amount, price, params)
|
919
|
+
|
920
|
+
async def edit_limit_order(self, id: str, symbol: str, side: OrderSide, amount: float, price: Num = None, params={}):
|
921
|
+
return await self.edit_order(id, symbol, 'limit', side, amount, price, params)
|
922
|
+
|
923
|
+
async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
|
924
|
+
await self.cancel_order(id, symbol)
|
925
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
926
|
+
|
927
|
+
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
|
928
|
+
await self.cancel_order_ws(id, symbol)
|
929
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
930
|
+
|
931
|
+
async def fetch_position(self, symbol: str, params={}):
|
932
|
+
raise NotSupported(self.id + ' fetchPosition() is not supported yet')
|
933
|
+
|
934
|
+
async def fetch_position_ws(self, symbol: str, params={}):
|
935
|
+
raise NotSupported(self.id + ' fetchPositionWs() is not supported yet')
|
936
|
+
|
937
|
+
async def watch_position(self, symbol: Str = None, params={}):
|
938
|
+
raise NotSupported(self.id + ' watchPosition() is not supported yet')
|
939
|
+
|
940
|
+
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
|
941
|
+
raise NotSupported(self.id + ' watchPositions() is not supported yet')
|
942
|
+
|
943
|
+
async def watch_position_for_symbols(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
|
944
|
+
return await self.watch_positions(symbols, since, limit, params)
|
945
|
+
|
946
|
+
async def fetch_positions_for_symbol(self, symbol: str, params={}):
|
947
|
+
"""
|
948
|
+
fetches all open positions for specific symbol, unlike fetchPositions(which is designed to work with multiple symbols) so self method might be preffered for one-market position, because of less rate-limit consumption and speed
|
949
|
+
:param str symbol: unified market symbol
|
950
|
+
:param dict params: extra parameters specific to the endpoint
|
951
|
+
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>` with maximum 3 items - possible one position for "one-way" mode, and possible two positions(long & short) for "two-way"(a.k.a. hedge) mode
|
952
|
+
"""
|
953
|
+
raise NotSupported(self.id + ' fetchPositionsForSymbol() is not supported yet')
|
954
|
+
|
955
|
+
async def fetch_positions_for_symbol_ws(self, symbol: str, params={}):
|
956
|
+
"""
|
957
|
+
fetches all open positions for specific symbol, unlike fetchPositions(which is designed to work with multiple symbols) so self method might be preffered for one-market position, because of less rate-limit consumption and speed
|
958
|
+
:param str symbol: unified market symbol
|
959
|
+
:param dict params: extra parameters specific to the endpoint
|
960
|
+
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>` with maximum 3 items - possible one position for "one-way" mode, and possible two positions(long & short) for "two-way"(a.k.a. hedge) mode
|
961
|
+
"""
|
962
|
+
raise NotSupported(self.id + ' fetchPositionsForSymbol() is not supported yet')
|
963
|
+
|
964
|
+
async def fetch_positions(self, symbols: Strings = None, params={}):
|
965
|
+
raise NotSupported(self.id + ' fetchPositions() is not supported yet')
|
966
|
+
|
967
|
+
async def fetch_positions_ws(self, symbols: Strings = None, params={}):
|
968
|
+
raise NotSupported(self.id + ' fetchPositions() is not supported yet')
|
969
|
+
|
970
|
+
async def fetch_positions_risk(self, symbols: Strings = None, params={}):
|
971
|
+
raise NotSupported(self.id + ' fetchPositionsRisk() is not supported yet')
|
972
|
+
|
973
|
+
async def fetch_bids_asks(self, symbols: Strings = None, params={}):
|
974
|
+
raise NotSupported(self.id + ' fetchBidsAsks() is not supported yet')
|
975
|
+
|
976
|
+
async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
977
|
+
raise NotSupported(self.id + ' fetchBorrowInterest() is not supported yet')
|
978
|
+
|
979
|
+
async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
980
|
+
raise NotSupported(self.id + ' fetchLedger() is not supported yet')
|
981
|
+
|
982
|
+
async def fetch_ledger_entry(self, id: str, code: Str = None, params={}):
|
983
|
+
raise NotSupported(self.id + ' fetchLedgerEntry() is not supported yet')
|
984
|
+
|
985
|
+
async def fetch_balance(self, params={}):
|
986
|
+
raise NotSupported(self.id + ' fetchBalance() is not supported yet')
|
987
|
+
|
988
|
+
async def fetch_balance_ws(self, params={}):
|
989
|
+
raise NotSupported(self.id + ' fetchBalanceWs() is not supported yet')
|
990
|
+
|
991
|
+
async def watch_balance(self, params={}):
|
992
|
+
raise NotSupported(self.id + ' watchBalance() is not supported yet')
|
993
|
+
|
994
|
+
async def fetch_partial_balance(self, part, params={}):
|
995
|
+
balance = await self.fetch_balance(params)
|
996
|
+
return balance[part]
|
997
|
+
|
998
|
+
async def fetch_free_balance(self, params={}):
|
999
|
+
return await self.fetch_partial_balance('free', params)
|
1000
|
+
|
1001
|
+
async def fetch_used_balance(self, params={}):
|
1002
|
+
return await self.fetch_partial_balance('used', params)
|
1003
|
+
|
1004
|
+
async def fetch_total_balance(self, params={}):
|
1005
|
+
return await self.fetch_partial_balance('total', params)
|
1006
|
+
|
1007
|
+
async def fetch_status(self, params={}):
|
1008
|
+
raise NotSupported(self.id + ' fetchStatus() is not supported yet')
|
1009
|
+
|
1010
|
+
async def fetch_transaction_fee(self, code: str, params={}):
|
1011
|
+
if not self.has['fetchTransactionFees']:
|
1012
|
+
raise NotSupported(self.id + ' fetchTransactionFee() is not supported yet')
|
1013
|
+
return await self.fetch_transaction_fees([code], params)
|
1014
|
+
|
1015
|
+
async def fetch_transaction_fees(self, codes: Strings = None, params={}):
|
1016
|
+
raise NotSupported(self.id + ' fetchTransactionFees() is not supported yet')
|
1017
|
+
|
1018
|
+
async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
|
1019
|
+
raise NotSupported(self.id + ' fetchDepositWithdrawFees() is not supported yet')
|
1020
|
+
|
1021
|
+
async def fetch_deposit_withdraw_fee(self, code: str, params={}):
|
1022
|
+
if not self.has['fetchDepositWithdrawFees']:
|
1023
|
+
raise NotSupported(self.id + ' fetchDepositWithdrawFee() is not supported yet')
|
1024
|
+
fees = await self.fetch_deposit_withdraw_fees([code], params)
|
1025
|
+
return self.safe_value(fees, code)
|
1026
|
+
|
1027
|
+
async def fetch_cross_borrow_rate(self, code: str, params={}):
|
1028
|
+
await self.load_markets()
|
1029
|
+
if not self.has['fetchBorrowRates']:
|
1030
|
+
raise NotSupported(self.id + ' fetchCrossBorrowRate() is not supported yet')
|
1031
|
+
borrowRates = await self.fetch_cross_borrow_rates(params)
|
1032
|
+
rate = self.safe_value(borrowRates, code)
|
1033
|
+
if rate is None:
|
1034
|
+
raise ExchangeError(self.id + ' fetchCrossBorrowRate() could not find the borrow rate for currency code ' + code)
|
1035
|
+
return rate
|
1036
|
+
|
1037
|
+
async def fetch_isolated_borrow_rate(self, symbol: str, params={}):
|
1038
|
+
await self.load_markets()
|
1039
|
+
if not self.has['fetchBorrowRates']:
|
1040
|
+
raise NotSupported(self.id + ' fetchIsolatedBorrowRate() is not supported yet')
|
1041
|
+
borrowRates = await self.fetch_isolated_borrow_rates(params)
|
1042
|
+
rate = self.safe_dict(borrowRates, symbol)
|
1043
|
+
if rate is None:
|
1044
|
+
raise ExchangeError(self.id + ' fetchIsolatedBorrowRate() could not find the borrow rate for market symbol ' + symbol)
|
1045
|
+
return rate
|
1046
|
+
|
1047
|
+
async def fetch_ticker(self, symbol: str, params={}):
|
1048
|
+
if self.has['fetchTickers']:
|
1049
|
+
await self.load_markets()
|
1050
|
+
market = self.market(symbol)
|
1051
|
+
symbol = market['symbol']
|
1052
|
+
tickers = await self.fetch_tickers([symbol], params)
|
1053
|
+
ticker = self.safe_dict(tickers, symbol)
|
1054
|
+
if ticker is None:
|
1055
|
+
raise NullResponse(self.id + ' fetchTickers() could not find a ticker for ' + symbol)
|
1056
|
+
else:
|
1057
|
+
return ticker
|
1058
|
+
else:
|
1059
|
+
raise NotSupported(self.id + ' fetchTicker() is not supported yet')
|
1060
|
+
|
1061
|
+
async def fetch_mark_price(self, symbol: str, params={}):
|
1062
|
+
if self.has['fetchMarkPrices']:
|
1063
|
+
await self.load_markets()
|
1064
|
+
market = self.market(symbol)
|
1065
|
+
symbol = market['symbol']
|
1066
|
+
tickers = await self.fetch_mark_prices([symbol], params)
|
1067
|
+
ticker = self.safe_dict(tickers, symbol)
|
1068
|
+
if ticker is None:
|
1069
|
+
raise NullResponse(self.id + ' fetchMarkPrices() could not find a ticker for ' + symbol)
|
1070
|
+
else:
|
1071
|
+
return ticker
|
1072
|
+
else:
|
1073
|
+
raise NotSupported(self.id + ' fetchMarkPrices() is not supported yet')
|
1074
|
+
|
1075
|
+
async def fetch_ticker_ws(self, symbol: str, params={}):
|
1076
|
+
if self.has['fetchTickersWs']:
|
1077
|
+
await self.load_markets()
|
1078
|
+
market = self.market(symbol)
|
1079
|
+
symbol = market['symbol']
|
1080
|
+
tickers = await self.fetch_tickers_ws([symbol], params)
|
1081
|
+
ticker = self.safe_dict(tickers, symbol)
|
1082
|
+
if ticker is None:
|
1083
|
+
raise NullResponse(self.id + ' fetchTickerWs() could not find a ticker for ' + symbol)
|
1084
|
+
else:
|
1085
|
+
return ticker
|
1086
|
+
else:
|
1087
|
+
raise NotSupported(self.id + ' fetchTickerWs() is not supported yet')
|
1088
|
+
|
1089
|
+
async def watch_ticker(self, symbol: str, params={}):
|
1090
|
+
raise NotSupported(self.id + ' watchTicker() is not supported yet')
|
1091
|
+
|
1092
|
+
async def fetch_tickers(self, symbols: Strings = None, params={}):
|
1093
|
+
raise NotSupported(self.id + ' fetchTickers() is not supported yet')
|
1094
|
+
|
1095
|
+
async def fetch_mark_prices(self, symbols: Strings = None, params={}):
|
1096
|
+
raise NotSupported(self.id + ' fetchMarkPrices() is not supported yet')
|
1097
|
+
|
1098
|
+
async def fetch_tickers_ws(self, symbols: Strings = None, params={}):
|
1099
|
+
raise NotSupported(self.id + ' fetchTickers() is not supported yet')
|
1100
|
+
|
1101
|
+
async def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}):
|
1102
|
+
raise NotSupported(self.id + ' fetchOrderBooks() is not supported yet')
|
1103
|
+
|
1104
|
+
async def watch_bids_asks(self, symbols: Strings = None, params={}):
|
1105
|
+
raise NotSupported(self.id + ' watchBidsAsks() is not supported yet')
|
1106
|
+
|
1107
|
+
async def watch_tickers(self, symbols: Strings = None, params={}):
|
1108
|
+
raise NotSupported(self.id + ' watchTickers() is not supported yet')
|
1109
|
+
|
1110
|
+
async def un_watch_tickers(self, symbols: Strings = None, params={}):
|
1111
|
+
raise NotSupported(self.id + ' unWatchTickers() is not supported yet')
|
1112
|
+
|
1113
|
+
async def fetch_order(self, id: str, symbol: Str = None, params={}):
|
1114
|
+
raise NotSupported(self.id + ' fetchOrder() is not supported yet')
|
1115
|
+
|
1116
|
+
async def fetch_order_ws(self, id: str, symbol: Str = None, params={}):
|
1117
|
+
raise NotSupported(self.id + ' fetchOrderWs() is not supported yet')
|
1118
|
+
|
1119
|
+
async def fetch_order_status(self, id: str, symbol: Str = None, params={}):
|
1120
|
+
# TODO: TypeScript: change method signature by replacing
|
1121
|
+
# Promise<string> with Promise<Order['status']>.
|
1122
|
+
order = await self.fetch_order(id, symbol, params)
|
1123
|
+
return order['status']
|
1124
|
+
|
1125
|
+
async def fetch_unified_order(self, order, params={}):
|
1126
|
+
return await self.fetch_order(self.safe_string(order, 'id'), self.safe_string(order, 'symbol'), params)
|
1127
|
+
|
1128
|
+
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1129
|
+
raise NotSupported(self.id + ' createOrder() is not supported yet')
|
1130
|
+
|
1131
|
+
async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}):
|
1132
|
+
raise NotSupported(self.id + ' createConvertTrade() is not supported yet')
|
1133
|
+
|
1134
|
+
async def fetch_convert_trade(self, id: str, code: Str = None, params={}):
|
1135
|
+
raise NotSupported(self.id + ' fetchConvertTrade() is not supported yet')
|
1136
|
+
|
1137
|
+
async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
1138
|
+
raise NotSupported(self.id + ' fetchConvertTradeHistory() is not supported yet')
|
1139
|
+
|
1140
|
+
async def fetch_position_mode(self, symbol: Str = None, params={}):
|
1141
|
+
raise NotSupported(self.id + ' fetchPositionMode() is not supported yet')
|
1142
|
+
|
1143
|
+
async def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount=None, trailingTriggerPrice=None, params={}):
|
1144
|
+
"""
|
1145
|
+
create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
|
1146
|
+
:param str symbol: unified symbol of the market to create an order in
|
1147
|
+
:param str type: 'market' or 'limit'
|
1148
|
+
:param str side: 'buy' or 'sell'
|
1149
|
+
:param float amount: how much you want to trade in units of the base currency, or number of contracts
|
1150
|
+
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
|
1151
|
+
:param float trailingAmount: the quote amount to trail away from the current market price
|
1152
|
+
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
|
1153
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1154
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1155
|
+
"""
|
1156
|
+
if trailingAmount is None:
|
1157
|
+
raise ArgumentsRequired(self.id + ' createTrailingAmountOrder() requires a trailingAmount argument')
|
1158
|
+
params['trailingAmount'] = trailingAmount
|
1159
|
+
if trailingTriggerPrice is not None:
|
1160
|
+
params['trailingTriggerPrice'] = trailingTriggerPrice
|
1161
|
+
if self.has['createTrailingAmountOrder']:
|
1162
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
1163
|
+
raise NotSupported(self.id + ' createTrailingAmountOrder() is not supported yet')
|
1164
|
+
|
1165
|
+
async def create_trailing_amount_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount=None, trailingTriggerPrice=None, params={}):
|
1166
|
+
"""
|
1167
|
+
create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
|
1168
|
+
:param str symbol: unified symbol of the market to create an order in
|
1169
|
+
:param str type: 'market' or 'limit'
|
1170
|
+
:param str side: 'buy' or 'sell'
|
1171
|
+
:param float amount: how much you want to trade in units of the base currency, or number of contracts
|
1172
|
+
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
|
1173
|
+
:param float trailingAmount: the quote amount to trail away from the current market price
|
1174
|
+
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
|
1175
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1176
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1177
|
+
"""
|
1178
|
+
if trailingAmount is None:
|
1179
|
+
raise ArgumentsRequired(self.id + ' createTrailingAmountOrderWs() requires a trailingAmount argument')
|
1180
|
+
params['trailingAmount'] = trailingAmount
|
1181
|
+
if trailingTriggerPrice is not None:
|
1182
|
+
params['trailingTriggerPrice'] = trailingTriggerPrice
|
1183
|
+
if self.has['createTrailingAmountOrderWs']:
|
1184
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
1185
|
+
raise NotSupported(self.id + ' createTrailingAmountOrderWs() is not supported yet')
|
1186
|
+
|
1187
|
+
async def create_trailing_percent_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent=None, trailingTriggerPrice=None, params={}):
|
1188
|
+
"""
|
1189
|
+
create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
|
1190
|
+
:param str symbol: unified symbol of the market to create an order in
|
1191
|
+
:param str type: 'market' or 'limit'
|
1192
|
+
:param str side: 'buy' or 'sell'
|
1193
|
+
:param float amount: how much you want to trade in units of the base currency, or number of contracts
|
1194
|
+
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
|
1195
|
+
:param float trailingPercent: the percent to trail away from the current market price
|
1196
|
+
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
|
1197
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1198
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1199
|
+
"""
|
1200
|
+
if trailingPercent is None:
|
1201
|
+
raise ArgumentsRequired(self.id + ' createTrailingPercentOrder() requires a trailingPercent argument')
|
1202
|
+
params['trailingPercent'] = trailingPercent
|
1203
|
+
if trailingTriggerPrice is not None:
|
1204
|
+
params['trailingTriggerPrice'] = trailingTriggerPrice
|
1205
|
+
if self.has['createTrailingPercentOrder']:
|
1206
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
1207
|
+
raise NotSupported(self.id + ' createTrailingPercentOrder() is not supported yet')
|
1208
|
+
|
1209
|
+
async def create_trailing_percent_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent=None, trailingTriggerPrice=None, params={}):
|
1210
|
+
"""
|
1211
|
+
create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
|
1212
|
+
:param str symbol: unified symbol of the market to create an order in
|
1213
|
+
:param str type: 'market' or 'limit'
|
1214
|
+
:param str side: 'buy' or 'sell'
|
1215
|
+
:param float amount: how much you want to trade in units of the base currency, or number of contracts
|
1216
|
+
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
|
1217
|
+
:param float trailingPercent: the percent to trail away from the current market price
|
1218
|
+
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
|
1219
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1220
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1221
|
+
"""
|
1222
|
+
if trailingPercent is None:
|
1223
|
+
raise ArgumentsRequired(self.id + ' createTrailingPercentOrderWs() requires a trailingPercent argument')
|
1224
|
+
params['trailingPercent'] = trailingPercent
|
1225
|
+
if trailingTriggerPrice is not None:
|
1226
|
+
params['trailingTriggerPrice'] = trailingTriggerPrice
|
1227
|
+
if self.has['createTrailingPercentOrderWs']:
|
1228
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
1229
|
+
raise NotSupported(self.id + ' createTrailingPercentOrderWs() is not supported yet')
|
1230
|
+
|
1231
|
+
async def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
|
1232
|
+
"""
|
1233
|
+
create a market order by providing the symbol, side and cost
|
1234
|
+
:param str symbol: unified symbol of the market to create an order in
|
1235
|
+
:param str side: 'buy' or 'sell'
|
1236
|
+
:param float cost: how much you want to trade in units of the quote currency
|
1237
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1238
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1239
|
+
"""
|
1240
|
+
if self.has['createMarketOrderWithCost'] or (self.has['createMarketBuyOrderWithCost'] and self.has['createMarketSellOrderWithCost']):
|
1241
|
+
return await self.create_order(symbol, 'market', side, cost, 1, params)
|
1242
|
+
raise NotSupported(self.id + ' createMarketOrderWithCost() is not supported yet')
|
1243
|
+
|
1244
|
+
async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
|
1245
|
+
"""
|
1246
|
+
create a market buy order by providing the symbol and cost
|
1247
|
+
:param str symbol: unified symbol of the market to create an order in
|
1248
|
+
:param float cost: how much you want to trade in units of the quote currency
|
1249
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1250
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1251
|
+
"""
|
1252
|
+
if self.options['createMarketBuyOrderRequiresPrice'] or self.has['createMarketBuyOrderWithCost']:
|
1253
|
+
return await self.create_order(symbol, 'market', 'buy', cost, 1, params)
|
1254
|
+
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() is not supported yet')
|
1255
|
+
|
1256
|
+
async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
|
1257
|
+
"""
|
1258
|
+
create a market sell order by providing the symbol and cost
|
1259
|
+
:param str symbol: unified symbol of the market to create an order in
|
1260
|
+
:param float cost: how much you want to trade in units of the quote currency
|
1261
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1262
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1263
|
+
"""
|
1264
|
+
if self.options['createMarketSellOrderRequiresPrice'] or self.has['createMarketSellOrderWithCost']:
|
1265
|
+
return await self.create_order(symbol, 'market', 'sell', cost, 1, params)
|
1266
|
+
raise NotSupported(self.id + ' createMarketSellOrderWithCost() is not supported yet')
|
1267
|
+
|
1268
|
+
async def create_market_order_with_cost_ws(self, symbol: str, side: OrderSide, cost: float, params={}):
|
1269
|
+
"""
|
1270
|
+
create a market order by providing the symbol, side and cost
|
1271
|
+
:param str symbol: unified symbol of the market to create an order in
|
1272
|
+
:param str side: 'buy' or 'sell'
|
1273
|
+
:param float cost: how much you want to trade in units of the quote currency
|
1274
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1275
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1276
|
+
"""
|
1277
|
+
if self.has['createMarketOrderWithCostWs'] or (self.has['createMarketBuyOrderWithCostWs'] and self.has['createMarketSellOrderWithCostWs']):
|
1278
|
+
return await self.create_order_ws(symbol, 'market', side, cost, 1, params)
|
1279
|
+
raise NotSupported(self.id + ' createMarketOrderWithCostWs() is not supported yet')
|
1280
|
+
|
1281
|
+
async def create_trigger_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
|
1282
|
+
"""
|
1283
|
+
create a trigger stop order(type 1)
|
1284
|
+
:param str symbol: unified symbol of the market to create an order in
|
1285
|
+
:param str type: 'market' or 'limit'
|
1286
|
+
:param str side: 'buy' or 'sell'
|
1287
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1288
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1289
|
+
:param float triggerPrice: the price to trigger the stop order, in units of the quote currency
|
1290
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1291
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1292
|
+
"""
|
1293
|
+
if triggerPrice is None:
|
1294
|
+
raise ArgumentsRequired(self.id + ' createTriggerOrder() requires a triggerPrice argument')
|
1295
|
+
params['triggerPrice'] = triggerPrice
|
1296
|
+
if self.has['createTriggerOrder']:
|
1297
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
1298
|
+
raise NotSupported(self.id + ' createTriggerOrder() is not supported yet')
|
1299
|
+
|
1300
|
+
async def create_trigger_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
|
1301
|
+
"""
|
1302
|
+
create a trigger stop order(type 1)
|
1303
|
+
:param str symbol: unified symbol of the market to create an order in
|
1304
|
+
:param str type: 'market' or 'limit'
|
1305
|
+
:param str side: 'buy' or 'sell'
|
1306
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1307
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1308
|
+
:param float triggerPrice: the price to trigger the stop order, in units of the quote currency
|
1309
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1310
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1311
|
+
"""
|
1312
|
+
if triggerPrice is None:
|
1313
|
+
raise ArgumentsRequired(self.id + ' createTriggerOrderWs() requires a triggerPrice argument')
|
1314
|
+
params['triggerPrice'] = triggerPrice
|
1315
|
+
if self.has['createTriggerOrderWs']:
|
1316
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
1317
|
+
raise NotSupported(self.id + ' createTriggerOrderWs() is not supported yet')
|
1318
|
+
|
1319
|
+
async def create_stop_loss_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, stopLossPrice: Num = None, params={}):
|
1320
|
+
"""
|
1321
|
+
create a trigger stop loss order(type 2)
|
1322
|
+
:param str symbol: unified symbol of the market to create an order in
|
1323
|
+
:param str type: 'market' or 'limit'
|
1324
|
+
:param str side: 'buy' or 'sell'
|
1325
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1326
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1327
|
+
:param float stopLossPrice: the price to trigger the stop loss order, in units of the quote currency
|
1328
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1329
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1330
|
+
"""
|
1331
|
+
if stopLossPrice is None:
|
1332
|
+
raise ArgumentsRequired(self.id + ' createStopLossOrder() requires a stopLossPrice argument')
|
1333
|
+
params['stopLossPrice'] = stopLossPrice
|
1334
|
+
if self.has['createStopLossOrder']:
|
1335
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
1336
|
+
raise NotSupported(self.id + ' createStopLossOrder() is not supported yet')
|
1337
|
+
|
1338
|
+
async def create_stop_loss_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, stopLossPrice: Num = None, params={}):
|
1339
|
+
"""
|
1340
|
+
create a trigger stop loss order(type 2)
|
1341
|
+
:param str symbol: unified symbol of the market to create an order in
|
1342
|
+
:param str type: 'market' or 'limit'
|
1343
|
+
:param str side: 'buy' or 'sell'
|
1344
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1345
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1346
|
+
:param float stopLossPrice: the price to trigger the stop loss order, in units of the quote currency
|
1347
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1348
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1349
|
+
"""
|
1350
|
+
if stopLossPrice is None:
|
1351
|
+
raise ArgumentsRequired(self.id + ' createStopLossOrderWs() requires a stopLossPrice argument')
|
1352
|
+
params['stopLossPrice'] = stopLossPrice
|
1353
|
+
if self.has['createStopLossOrderWs']:
|
1354
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
1355
|
+
raise NotSupported(self.id + ' createStopLossOrderWs() is not supported yet')
|
1356
|
+
|
1357
|
+
async def create_take_profit_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, takeProfitPrice: Num = None, params={}):
|
1358
|
+
"""
|
1359
|
+
create a trigger take profit order(type 2)
|
1360
|
+
:param str symbol: unified symbol of the market to create an order in
|
1361
|
+
:param str type: 'market' or 'limit'
|
1362
|
+
:param str side: 'buy' or 'sell'
|
1363
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1364
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1365
|
+
:param float takeProfitPrice: the price to trigger the take profit order, in units of the quote currency
|
1366
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1367
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1368
|
+
"""
|
1369
|
+
if takeProfitPrice is None:
|
1370
|
+
raise ArgumentsRequired(self.id + ' createTakeProfitOrder() requires a takeProfitPrice argument')
|
1371
|
+
params['takeProfitPrice'] = takeProfitPrice
|
1372
|
+
if self.has['createTakeProfitOrder']:
|
1373
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
1374
|
+
raise NotSupported(self.id + ' createTakeProfitOrder() is not supported yet')
|
1375
|
+
|
1376
|
+
async def create_take_profit_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, takeProfitPrice: Num = None, params={}):
|
1377
|
+
"""
|
1378
|
+
create a trigger take profit order(type 2)
|
1379
|
+
:param str symbol: unified symbol of the market to create an order in
|
1380
|
+
:param str type: 'market' or 'limit'
|
1381
|
+
:param str side: 'buy' or 'sell'
|
1382
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1383
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1384
|
+
:param float takeProfitPrice: the price to trigger the take profit order, in units of the quote currency
|
1385
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1386
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1387
|
+
"""
|
1388
|
+
if takeProfitPrice is None:
|
1389
|
+
raise ArgumentsRequired(self.id + ' createTakeProfitOrderWs() requires a takeProfitPrice argument')
|
1390
|
+
params['takeProfitPrice'] = takeProfitPrice
|
1391
|
+
if self.has['createTakeProfitOrderWs']:
|
1392
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
1393
|
+
raise NotSupported(self.id + ' createTakeProfitOrderWs() is not supported yet')
|
1394
|
+
|
1395
|
+
async def create_order_with_take_profit_and_stop_loss(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, takeProfit: Num = None, stopLoss: Num = None, params={}):
|
1396
|
+
"""
|
1397
|
+
create an order with a stop loss or take profit attached(type 3)
|
1398
|
+
:param str symbol: unified symbol of the market to create an order in
|
1399
|
+
:param str type: 'market' or 'limit'
|
1400
|
+
:param str side: 'buy' or 'sell'
|
1401
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1402
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1403
|
+
:param float [takeProfit]: the take profit price, in units of the quote currency
|
1404
|
+
:param float [stopLoss]: the stop loss price, in units of the quote currency
|
1405
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1406
|
+
:param str [params.takeProfitType]: *not available on all exchanges* 'limit' or 'market'
|
1407
|
+
:param str [params.stopLossType]: *not available on all exchanges* 'limit' or 'market'
|
1408
|
+
:param str [params.takeProfitPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
|
1409
|
+
:param str [params.stopLossPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
|
1410
|
+
:param float [params.takeProfitLimitPrice]: *not available on all exchanges* limit price for a limit take profit order
|
1411
|
+
:param float [params.stopLossLimitPrice]: *not available on all exchanges* stop loss for a limit stop loss order
|
1412
|
+
:param float [params.takeProfitAmount]: *not available on all exchanges* the amount for a take profit
|
1413
|
+
:param float [params.stopLossAmount]: *not available on all exchanges* the amount for a stop loss
|
1414
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1415
|
+
"""
|
1416
|
+
params = self.set_take_profit_and_stop_loss_params(symbol, type, side, amount, price, takeProfit, stopLoss, params)
|
1417
|
+
if self.has['createOrderWithTakeProfitAndStopLoss']:
|
1418
|
+
return await self.create_order(symbol, type, side, amount, price, params)
|
1419
|
+
raise NotSupported(self.id + ' createOrderWithTakeProfitAndStopLoss() is not supported yet')
|
1420
|
+
|
1421
|
+
async def create_order_with_take_profit_and_stop_loss_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, takeProfit: Num = None, stopLoss: Num = None, params={}):
|
1422
|
+
"""
|
1423
|
+
create an order with a stop loss or take profit attached(type 3)
|
1424
|
+
:param str symbol: unified symbol of the market to create an order in
|
1425
|
+
:param str type: 'market' or 'limit'
|
1426
|
+
:param str side: 'buy' or 'sell'
|
1427
|
+
:param float amount: how much you want to trade in units of the base currency or the number of contracts
|
1428
|
+
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
|
1429
|
+
:param float [takeProfit]: the take profit price, in units of the quote currency
|
1430
|
+
:param float [stopLoss]: the stop loss price, in units of the quote currency
|
1431
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1432
|
+
:param str [params.takeProfitType]: *not available on all exchanges* 'limit' or 'market'
|
1433
|
+
:param str [params.stopLossType]: *not available on all exchanges* 'limit' or 'market'
|
1434
|
+
:param str [params.takeProfitPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
|
1435
|
+
:param str [params.stopLossPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
|
1436
|
+
:param float [params.takeProfitLimitPrice]: *not available on all exchanges* limit price for a limit take profit order
|
1437
|
+
:param float [params.stopLossLimitPrice]: *not available on all exchanges* stop loss for a limit stop loss order
|
1438
|
+
:param float [params.takeProfitAmount]: *not available on all exchanges* the amount for a take profit
|
1439
|
+
:param float [params.stopLossAmount]: *not available on all exchanges* the amount for a stop loss
|
1440
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1441
|
+
"""
|
1442
|
+
params = self.set_take_profit_and_stop_loss_params(symbol, type, side, amount, price, takeProfit, stopLoss, params)
|
1443
|
+
if self.has['createOrderWithTakeProfitAndStopLossWs']:
|
1444
|
+
return await self.create_order_ws(symbol, type, side, amount, price, params)
|
1445
|
+
raise NotSupported(self.id + ' createOrderWithTakeProfitAndStopLossWs() is not supported yet')
|
1446
|
+
|
1447
|
+
async def create_orders(self, orders: List[OrderRequest], params={}):
|
1448
|
+
raise NotSupported(self.id + ' createOrders() is not supported yet')
|
1449
|
+
|
1450
|
+
async def edit_orders(self, orders: List[OrderRequest], params={}):
|
1451
|
+
raise NotSupported(self.id + ' editOrders() is not supported yet')
|
1452
|
+
|
1453
|
+
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1454
|
+
raise NotSupported(self.id + ' createOrderWs() is not supported yet')
|
1455
|
+
|
1456
|
+
async def cancel_order(self, id: str, symbol: Str = None, params={}):
|
1457
|
+
raise NotSupported(self.id + ' cancelOrder() is not supported yet')
|
1458
|
+
|
1459
|
+
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}):
|
1460
|
+
raise NotSupported(self.id + ' cancelOrderWs() is not supported yet')
|
1461
|
+
|
1462
|
+
async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
|
1463
|
+
raise NotSupported(self.id + ' cancelOrdersWs() is not supported yet')
|
1464
|
+
|
1465
|
+
async def cancel_all_orders(self, symbol: Str = None, params={}):
|
1466
|
+
raise NotSupported(self.id + ' cancelAllOrders() is not supported yet')
|
1467
|
+
|
1468
|
+
async def cancel_all_orders_after(self, timeout: Int, params={}):
|
1469
|
+
raise NotSupported(self.id + ' cancelAllOrdersAfter() is not supported yet')
|
1470
|
+
|
1471
|
+
async def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
|
1472
|
+
raise NotSupported(self.id + ' cancelOrdersForSymbols() is not supported yet')
|
1473
|
+
|
1474
|
+
async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
|
1475
|
+
raise NotSupported(self.id + ' cancelAllOrdersWs() is not supported yet')
|
1476
|
+
|
1477
|
+
async def cancel_unified_order(self, order, params={}):
|
1478
|
+
return self.cancel_order(self.safe_string(order, 'id'), self.safe_string(order, 'symbol'), params)
|
1479
|
+
|
1480
|
+
async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1481
|
+
if self.has['fetchOpenOrders'] and self.has['fetchClosedOrders']:
|
1482
|
+
raise NotSupported(self.id + ' fetchOrders() is not supported yet, consider using fetchOpenOrders() and fetchClosedOrders() instead')
|
1483
|
+
raise NotSupported(self.id + ' fetchOrders() is not supported yet')
|
1484
|
+
|
1485
|
+
async def fetch_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1486
|
+
raise NotSupported(self.id + ' fetchOrdersWs() is not supported yet')
|
1487
|
+
|
1488
|
+
async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1489
|
+
raise NotSupported(self.id + ' fetchOrderTrades() is not supported yet')
|
1490
|
+
|
1491
|
+
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1492
|
+
raise NotSupported(self.id + ' watchOrders() is not supported yet')
|
1493
|
+
|
1494
|
+
async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1495
|
+
if self.has['fetchOrders']:
|
1496
|
+
orders = await self.fetch_orders(symbol, since, limit, params)
|
1497
|
+
return self.filter_by(orders, 'status', 'open')
|
1498
|
+
raise NotSupported(self.id + ' fetchOpenOrders() is not supported yet')
|
1499
|
+
|
1500
|
+
async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1501
|
+
if self.has['fetchOrdersWs']:
|
1502
|
+
orders = await self.fetch_orders_ws(symbol, since, limit, params)
|
1503
|
+
return self.filter_by(orders, 'status', 'open')
|
1504
|
+
raise NotSupported(self.id + ' fetchOpenOrdersWs() is not supported yet')
|
1505
|
+
|
1506
|
+
async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1507
|
+
if self.has['fetchOrders']:
|
1508
|
+
orders = await self.fetch_orders(symbol, since, limit, params)
|
1509
|
+
return self.filter_by(orders, 'status', 'closed')
|
1510
|
+
raise NotSupported(self.id + ' fetchClosedOrders() is not supported yet')
|
1511
|
+
|
1512
|
+
async def fetch_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1513
|
+
raise NotSupported(self.id + ' fetchCanceledAndClosedOrders() is not supported yet')
|
1514
|
+
|
1515
|
+
async def fetch_closed_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1516
|
+
if self.has['fetchOrdersWs']:
|
1517
|
+
orders = await self.fetch_orders_ws(symbol, since, limit, params)
|
1518
|
+
return self.filter_by(orders, 'status', 'closed')
|
1519
|
+
raise NotSupported(self.id + ' fetchClosedOrdersWs() is not supported yet')
|
1520
|
+
|
1521
|
+
async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1522
|
+
raise NotSupported(self.id + ' fetchMyTrades() is not supported yet')
|
1523
|
+
|
1524
|
+
async def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1525
|
+
raise NotSupported(self.id + ' fetchMyLiquidations() is not supported yet')
|
1526
|
+
|
1527
|
+
async def fetch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
1528
|
+
raise NotSupported(self.id + ' fetchLiquidations() is not supported yet')
|
1529
|
+
|
1530
|
+
async def fetch_my_trades_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1531
|
+
raise NotSupported(self.id + ' fetchMyTradesWs() is not supported yet')
|
1532
|
+
|
1533
|
+
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1534
|
+
raise NotSupported(self.id + ' watchMyTrades() is not supported yet')
|
1535
|
+
|
1536
|
+
async def fetch_greeks(self, symbol: str, params={}):
|
1537
|
+
raise NotSupported(self.id + ' fetchGreeks() is not supported yet')
|
1538
|
+
|
1539
|
+
async def fetch_option_chain(self, code: str, params={}):
|
1540
|
+
raise NotSupported(self.id + ' fetchOptionChain() is not supported yet')
|
1541
|
+
|
1542
|
+
async def fetch_option(self, symbol: str, params={}):
|
1543
|
+
raise NotSupported(self.id + ' fetchOption() is not supported yet')
|
1544
|
+
|
1545
|
+
async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}):
|
1546
|
+
raise NotSupported(self.id + ' fetchConvertQuote() is not supported yet')
|
1547
|
+
|
1548
|
+
async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
1549
|
+
"""
|
1550
|
+
fetch history of deposits and withdrawals
|
1551
|
+
:param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
|
1552
|
+
:param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
|
1553
|
+
:param int [limit]: max number of deposit/withdrawals to return, default is None
|
1554
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1555
|
+
:returns dict: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1556
|
+
"""
|
1557
|
+
raise NotSupported(self.id + ' fetchDepositsWithdrawals() is not supported yet')
|
1558
|
+
|
1559
|
+
async def fetch_deposits(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1560
|
+
raise NotSupported(self.id + ' fetchDeposits() is not supported yet')
|
1561
|
+
|
1562
|
+
async def fetch_withdrawals(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1563
|
+
raise NotSupported(self.id + ' fetchWithdrawals() is not supported yet')
|
1564
|
+
|
1565
|
+
async def fetch_deposits_ws(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
1566
|
+
raise NotSupported(self.id + ' fetchDepositsWs() is not supported yet')
|
1567
|
+
|
1568
|
+
async def fetch_withdrawals_ws(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
1569
|
+
raise NotSupported(self.id + ' fetchWithdrawalsWs() is not supported yet')
|
1570
|
+
|
1571
|
+
async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1572
|
+
raise NotSupported(self.id + ' fetchFundingRateHistory() is not supported yet')
|
1573
|
+
|
1574
|
+
async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1575
|
+
raise NotSupported(self.id + ' fetchFundingHistory() is not supported yet')
|
1576
|
+
|
1577
|
+
async def close_position(self, symbol: str, side: OrderSide = None, params={}):
|
1578
|
+
raise NotSupported(self.id + ' closePosition() is not supported yet')
|
1579
|
+
|
1580
|
+
async def close_all_positions(self, params={}):
|
1581
|
+
raise NotSupported(self.id + ' closeAllPositions() is not supported yet')
|
1582
|
+
|
1583
|
+
async def fetch_l3_order_book(self, symbol: str, limit: Int = None, params={}):
|
1584
|
+
raise BadRequest(self.id + ' fetchL3OrderBook() is not supported yet')
|
1585
|
+
|
1586
|
+
async def fetch_deposit_address(self, code: str, params={}):
|
1587
|
+
if self.has['fetchDepositAddresses']:
|
1588
|
+
depositAddresses = await self.fetch_deposit_addresses([code], params)
|
1589
|
+
depositAddress = self.safe_value(depositAddresses, code)
|
1590
|
+
if depositAddress is None:
|
1591
|
+
raise InvalidAddress(self.id + ' fetchDepositAddress() could not find a deposit address for ' + code + ', make sure you have created a corresponding deposit address in your wallet on the exchange website')
|
1592
|
+
else:
|
1593
|
+
return depositAddress
|
1594
|
+
elif self.has['fetchDepositAddressesByNetwork']:
|
1595
|
+
network = self.safe_string(params, 'network')
|
1596
|
+
params = self.omit(params, 'network')
|
1597
|
+
addressStructures = await self.fetch_deposit_addresses_by_network(code, params)
|
1598
|
+
if network is not None:
|
1599
|
+
return self.safe_dict(addressStructures, network)
|
1600
|
+
else:
|
1601
|
+
keys = list(addressStructures.keys())
|
1602
|
+
key = self.safe_string(keys, 0)
|
1603
|
+
return self.safe_dict(addressStructures, key)
|
1604
|
+
else:
|
1605
|
+
raise NotSupported(self.id + ' fetchDepositAddress() is not supported yet')
|
1606
|
+
|
1607
|
+
async def create_limit_order(self, symbol: str, side: OrderSide, amount: float, price: float, params={}):
|
1608
|
+
return await self.create_order(symbol, 'limit', side, amount, price, params)
|
1609
|
+
|
1610
|
+
async def create_limit_order_ws(self, symbol: str, side: OrderSide, amount: float, price: float, params={}):
|
1611
|
+
return await self.create_order_ws(symbol, 'limit', side, amount, price, params)
|
1612
|
+
|
1613
|
+
async def create_market_order(self, symbol: str, side: OrderSide, amount: float, price: Num = None, params={}):
|
1614
|
+
return await self.create_order(symbol, 'market', side, amount, price, params)
|
1615
|
+
|
1616
|
+
async def create_market_order_ws(self, symbol: str, side: OrderSide, amount: float, price: Num = None, params={}):
|
1617
|
+
return await self.create_order_ws(symbol, 'market', side, amount, price, params)
|
1618
|
+
|
1619
|
+
async def create_limit_buy_order(self, symbol: str, amount: float, price: float, params={}):
|
1620
|
+
return await self.create_order(symbol, 'limit', 'buy', amount, price, params)
|
1621
|
+
|
1622
|
+
async def create_limit_buy_order_ws(self, symbol: str, amount: float, price: float, params={}):
|
1623
|
+
return await self.create_order_ws(symbol, 'limit', 'buy', amount, price, params)
|
1624
|
+
|
1625
|
+
async def create_limit_sell_order(self, symbol: str, amount: float, price: float, params={}):
|
1626
|
+
return await self.create_order(symbol, 'limit', 'sell', amount, price, params)
|
1627
|
+
|
1628
|
+
async def create_limit_sell_order_ws(self, symbol: str, amount: float, price: float, params={}):
|
1629
|
+
return await self.create_order_ws(symbol, 'limit', 'sell', amount, price, params)
|
1630
|
+
|
1631
|
+
async def create_market_buy_order(self, symbol: str, amount: float, params={}):
|
1632
|
+
return await self.create_order(symbol, 'market', 'buy', amount, None, params)
|
1633
|
+
|
1634
|
+
async def create_market_buy_order_ws(self, symbol: str, amount: float, params={}):
|
1635
|
+
return await self.create_order_ws(symbol, 'market', 'buy', amount, None, params)
|
1636
|
+
|
1637
|
+
async def create_market_sell_order(self, symbol: str, amount: float, params={}):
|
1638
|
+
return await self.create_order(symbol, 'market', 'sell', amount, None, params)
|
1639
|
+
|
1640
|
+
async def create_market_sell_order_ws(self, symbol: str, amount: float, params={}):
|
1641
|
+
return await self.create_order_ws(symbol, 'market', 'sell', amount, None, params)
|
1642
|
+
|
1643
|
+
async def load_time_difference(self, params={}):
|
1644
|
+
serverTime = await self.fetch_time(params)
|
1645
|
+
after = self.milliseconds()
|
1646
|
+
self.options['timeDifference'] = after - serverTime
|
1647
|
+
return self.options['timeDifference']
|
1648
|
+
|
1649
|
+
async def fetch_market_leverage_tiers(self, symbol: str, params={}):
|
1650
|
+
if self.has['fetchLeverageTiers']:
|
1651
|
+
market = self.market(symbol)
|
1652
|
+
if not market['contract']:
|
1653
|
+
raise BadSymbol(self.id + ' fetchMarketLeverageTiers() supports contract markets only')
|
1654
|
+
tiers = await self.fetch_leverage_tiers([symbol])
|
1655
|
+
return self.safe_value(tiers, symbol)
|
1656
|
+
else:
|
1657
|
+
raise NotSupported(self.id + ' fetchMarketLeverageTiers() is not supported yet')
|
1658
|
+
|
1659
|
+
async def create_post_only_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1660
|
+
if not self.has['createPostOnlyOrder']:
|
1661
|
+
raise NotSupported(self.id + ' createPostOnlyOrder() is not supported yet')
|
1662
|
+
query = self.extend(params, {'postOnly': True})
|
1663
|
+
return await self.create_order(symbol, type, side, amount, price, query)
|
1664
|
+
|
1665
|
+
async def create_post_only_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1666
|
+
if not self.has['createPostOnlyOrderWs']:
|
1667
|
+
raise NotSupported(self.id + ' createPostOnlyOrderWs() is not supported yet')
|
1668
|
+
query = self.extend(params, {'postOnly': True})
|
1669
|
+
return await self.create_order_ws(symbol, type, side, amount, price, query)
|
1670
|
+
|
1671
|
+
async def create_reduce_only_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1672
|
+
if not self.has['createReduceOnlyOrder']:
|
1673
|
+
raise NotSupported(self.id + ' createReduceOnlyOrder() is not supported yet')
|
1674
|
+
query = self.extend(params, {'reduceOnly': True})
|
1675
|
+
return await self.create_order(symbol, type, side, amount, price, query)
|
1676
|
+
|
1677
|
+
async def create_reduce_only_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1678
|
+
if not self.has['createReduceOnlyOrderWs']:
|
1679
|
+
raise NotSupported(self.id + ' createReduceOnlyOrderWs() is not supported yet')
|
1680
|
+
query = self.extend(params, {'reduceOnly': True})
|
1681
|
+
return await self.create_order_ws(symbol, type, side, amount, price, query)
|
1682
|
+
|
1683
|
+
async def create_stop_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
|
1684
|
+
if not self.has['createStopOrder']:
|
1685
|
+
raise NotSupported(self.id + ' createStopOrder() is not supported yet')
|
1686
|
+
if triggerPrice is None:
|
1687
|
+
raise ArgumentsRequired(self.id + ' create_stop_order() requires a stopPrice argument')
|
1688
|
+
query = self.extend(params, {'stopPrice': triggerPrice})
|
1689
|
+
return await self.create_order(symbol, type, side, amount, price, query)
|
1690
|
+
|
1691
|
+
async def create_stop_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
|
1692
|
+
if not self.has['createStopOrderWs']:
|
1693
|
+
raise NotSupported(self.id + ' createStopOrderWs() is not supported yet')
|
1694
|
+
if triggerPrice is None:
|
1695
|
+
raise ArgumentsRequired(self.id + ' createStopOrderWs() requires a stopPrice argument')
|
1696
|
+
query = self.extend(params, {'stopPrice': triggerPrice})
|
1697
|
+
return await self.create_order_ws(symbol, type, side, amount, price, query)
|
1698
|
+
|
1699
|
+
async def create_stop_limit_order(self, symbol: str, side: OrderSide, amount: float, price: float, triggerPrice: float, params={}):
|
1700
|
+
if not self.has['createStopLimitOrder']:
|
1701
|
+
raise NotSupported(self.id + ' createStopLimitOrder() is not supported yet')
|
1702
|
+
query = self.extend(params, {'stopPrice': triggerPrice})
|
1703
|
+
return await self.create_order(symbol, 'limit', side, amount, price, query)
|
1704
|
+
|
1705
|
+
async def create_stop_limit_order_ws(self, symbol: str, side: OrderSide, amount: float, price: float, triggerPrice: float, params={}):
|
1706
|
+
if not self.has['createStopLimitOrderWs']:
|
1707
|
+
raise NotSupported(self.id + ' createStopLimitOrderWs() is not supported yet')
|
1708
|
+
query = self.extend(params, {'stopPrice': triggerPrice})
|
1709
|
+
return await self.create_order_ws(symbol, 'limit', side, amount, price, query)
|
1710
|
+
|
1711
|
+
async def create_stop_market_order(self, symbol: str, side: OrderSide, amount: float, triggerPrice: float, params={}):
|
1712
|
+
if not self.has['createStopMarketOrder']:
|
1713
|
+
raise NotSupported(self.id + ' createStopMarketOrder() is not supported yet')
|
1714
|
+
query = self.extend(params, {'stopPrice': triggerPrice})
|
1715
|
+
return await self.create_order(symbol, 'market', side, amount, None, query)
|
1716
|
+
|
1717
|
+
async def create_stop_market_order_ws(self, symbol: str, side: OrderSide, amount: float, triggerPrice: float, params={}):
|
1718
|
+
if not self.has['createStopMarketOrderWs']:
|
1719
|
+
raise NotSupported(self.id + ' createStopMarketOrderWs() is not supported yet')
|
1720
|
+
query = self.extend(params, {'stopPrice': triggerPrice})
|
1721
|
+
return await self.create_order_ws(symbol, 'market', side, amount, None, query)
|
1722
|
+
|
1723
|
+
async def fetch_last_prices(self, symbols: Strings = None, params={}):
|
1724
|
+
raise NotSupported(self.id + ' fetchLastPrices() is not supported yet')
|
1725
|
+
|
1726
|
+
async def fetch_trading_fees(self, params={}):
|
1727
|
+
raise NotSupported(self.id + ' fetchTradingFees() is not supported yet')
|
1728
|
+
|
1729
|
+
async def fetch_trading_fees_ws(self, params={}):
|
1730
|
+
raise NotSupported(self.id + ' fetchTradingFeesWs() is not supported yet')
|
1731
|
+
|
1732
|
+
async def fetch_trading_fee(self, symbol: str, params={}):
|
1733
|
+
if not self.has['fetchTradingFees']:
|
1734
|
+
raise NotSupported(self.id + ' fetchTradingFee() is not supported yet')
|
1735
|
+
fees = await self.fetch_trading_fees(params)
|
1736
|
+
return self.safe_dict(fees, symbol)
|
1737
|
+
|
1738
|
+
async def fetch_convert_currencies(self, params={}):
|
1739
|
+
raise NotSupported(self.id + ' fetchConvertCurrencies() is not supported yet')
|
1740
|
+
|
1741
|
+
async def fetch_funding_rate(self, symbol: str, params={}):
|
1742
|
+
if self.has['fetchFundingRates']:
|
1743
|
+
await self.load_markets()
|
1744
|
+
market = self.market(symbol)
|
1745
|
+
symbol = market['symbol']
|
1746
|
+
if not market['contract']:
|
1747
|
+
raise BadSymbol(self.id + ' fetchFundingRate() supports contract markets only')
|
1748
|
+
rates = await self.fetch_funding_rates([symbol], params)
|
1749
|
+
rate = self.safe_value(rates, symbol)
|
1750
|
+
if rate is None:
|
1751
|
+
raise NullResponse(self.id + ' fetchFundingRate() returned no data for ' + symbol)
|
1752
|
+
else:
|
1753
|
+
return rate
|
1754
|
+
else:
|
1755
|
+
raise NotSupported(self.id + ' fetchFundingRate() is not supported yet')
|
1756
|
+
|
1757
|
+
async def fetch_funding_interval(self, symbol: str, params={}):
|
1758
|
+
if self.has['fetchFundingIntervals']:
|
1759
|
+
await self.load_markets()
|
1760
|
+
market = self.market(symbol)
|
1761
|
+
symbol = market['symbol']
|
1762
|
+
if not market['contract']:
|
1763
|
+
raise BadSymbol(self.id + ' fetchFundingInterval() supports contract markets only')
|
1764
|
+
rates = await self.fetch_funding_intervals([symbol], params)
|
1765
|
+
rate = self.safe_value(rates, symbol)
|
1766
|
+
if rate is None:
|
1767
|
+
raise NullResponse(self.id + ' fetchFundingInterval() returned no data for ' + symbol)
|
1768
|
+
else:
|
1769
|
+
return rate
|
1770
|
+
else:
|
1771
|
+
raise NotSupported(self.id + ' fetchFundingInterval() is not supported yet')
|
1772
|
+
|
1773
|
+
async def fetch_mark_ohlcv(self, symbol, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
1774
|
+
"""
|
1775
|
+
fetches historical mark price candlestick data containing the open, high, low, and close price of a market
|
1776
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
1777
|
+
:param str timeframe: the length of time each candle represents
|
1778
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1779
|
+
:param int [limit]: the maximum amount of candles to fetch
|
1780
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1781
|
+
:returns float[][]: A list of candles ordered, open, high, low, close, None
|
1782
|
+
"""
|
1783
|
+
if self.has['fetchMarkOHLCV']:
|
1784
|
+
request: dict = {
|
1785
|
+
'price': 'mark',
|
1786
|
+
}
|
1787
|
+
return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
|
1788
|
+
else:
|
1789
|
+
raise NotSupported(self.id + ' fetchMarkOHLCV() is not supported yet')
|
1790
|
+
|
1791
|
+
async def fetch_index_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
1792
|
+
"""
|
1793
|
+
fetches historical index price candlestick data containing the open, high, low, and close price of a market
|
1794
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
1795
|
+
:param str timeframe: the length of time each candle represents
|
1796
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1797
|
+
:param int [limit]: the maximum amount of candles to fetch
|
1798
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1799
|
+
@returns {} A list of candles ordered, open, high, low, close, None
|
1800
|
+
"""
|
1801
|
+
if self.has['fetchIndexOHLCV']:
|
1802
|
+
request: dict = {
|
1803
|
+
'price': 'index',
|
1804
|
+
}
|
1805
|
+
return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
|
1806
|
+
else:
|
1807
|
+
raise NotSupported(self.id + ' fetchIndexOHLCV() is not supported yet')
|
1808
|
+
|
1809
|
+
async def fetch_premium_index_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
1810
|
+
"""
|
1811
|
+
fetches historical premium index price candlestick data containing the open, high, low, and close price of a market
|
1812
|
+
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
1813
|
+
:param str timeframe: the length of time each candle represents
|
1814
|
+
:param int [since]: timestamp in ms of the earliest candle to fetch
|
1815
|
+
:param int [limit]: the maximum amount of candles to fetch
|
1816
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1817
|
+
:returns float[][]: A list of candles ordered, open, high, low, close, None
|
1818
|
+
"""
|
1819
|
+
if self.has['fetchPremiumIndexOHLCV']:
|
1820
|
+
request: dict = {
|
1821
|
+
'price': 'premiumIndex',
|
1822
|
+
}
|
1823
|
+
return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
|
1824
|
+
else:
|
1825
|
+
raise NotSupported(self.id + ' fetchPremiumIndexOHLCV() is not supported yet')
|
1826
|
+
|
1827
|
+
async def fetch_transactions(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
1828
|
+
"""
|
1829
|
+
@deprecated
|
1830
|
+
*DEPRECATED* use fetchDepositsWithdrawals instead
|
1831
|
+
:param str code: unified currency code for the currency of the deposit/withdrawals, default is None
|
1832
|
+
:param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
|
1833
|
+
:param int [limit]: max number of deposit/withdrawals to return, default is None
|
1834
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1835
|
+
:returns dict: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1836
|
+
"""
|
1837
|
+
if self.has['fetchDepositsWithdrawals']:
|
1838
|
+
return await self.fetch_deposits_withdrawals(code, since, limit, params)
|
1839
|
+
else:
|
1840
|
+
raise NotSupported(self.id + ' fetchTransactions() is not supported yet')
|
1841
|
+
|
1842
|
+
async def fetch_paginated_call_dynamic(self, method: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}, maxEntriesPerRequest: Int = None, removeRepeated=True):
|
1843
|
+
maxCalls = None
|
1844
|
+
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
|
1845
|
+
maxRetries = None
|
1846
|
+
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
|
1847
|
+
paginationDirection = None
|
1848
|
+
paginationDirection, params = self.handle_option_and_params(params, method, 'paginationDirection', 'backward')
|
1849
|
+
paginationTimestamp = None
|
1850
|
+
removeRepeatedOption = removeRepeated
|
1851
|
+
removeRepeatedOption, params = self.handle_option_and_params(params, method, 'removeRepeated', removeRepeated)
|
1852
|
+
calls = 0
|
1853
|
+
result = []
|
1854
|
+
errors = 0
|
1855
|
+
until = self.safe_integer_2(params, 'untill', 'till') # do not omit it from params here
|
1856
|
+
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
|
1857
|
+
if (paginationDirection == 'forward'):
|
1858
|
+
if since is None:
|
1859
|
+
raise ArgumentsRequired(self.id + ' pagination requires a since argument when paginationDirection set to forward')
|
1860
|
+
paginationTimestamp = since
|
1861
|
+
while((calls < maxCalls)):
|
1862
|
+
calls += 1
|
1863
|
+
try:
|
1864
|
+
if paginationDirection == 'backward':
|
1865
|
+
# do it backwards, starting from the last
|
1866
|
+
# UNTIL filtering is required in order to work
|
1867
|
+
if paginationTimestamp is not None:
|
1868
|
+
params['until'] = paginationTimestamp - 1
|
1869
|
+
response = await getattr(self, method)(symbol, None, maxEntriesPerRequest, params)
|
1870
|
+
responseLength = len(response)
|
1871
|
+
if self.verbose:
|
1872
|
+
backwardMessage = 'Dynamic pagination call ' + self.number_to_string(calls) + ' method ' + method + ' response length ' + self.number_to_string(responseLength)
|
1873
|
+
if paginationTimestamp is not None:
|
1874
|
+
backwardMessage += ' timestamp ' + self.number_to_string(paginationTimestamp)
|
1875
|
+
self.log(backwardMessage)
|
1876
|
+
if responseLength == 0:
|
1877
|
+
break
|
1878
|
+
errors = 0
|
1879
|
+
result = self.array_concat(result, response)
|
1880
|
+
firstElement = self.safe_value(response, 0)
|
1881
|
+
paginationTimestamp = self.safe_integer_2(firstElement, 'timestamp', 0)
|
1882
|
+
if (since is not None) and (paginationTimestamp <= since):
|
1883
|
+
break
|
1884
|
+
else:
|
1885
|
+
# do it forwards, starting from the since
|
1886
|
+
response = await getattr(self, method)(symbol, paginationTimestamp, maxEntriesPerRequest, params)
|
1887
|
+
responseLength = len(response)
|
1888
|
+
if self.verbose:
|
1889
|
+
forwardMessage = 'Dynamic pagination call ' + self.number_to_string(calls) + ' method ' + method + ' response length ' + self.number_to_string(responseLength)
|
1890
|
+
if paginationTimestamp is not None:
|
1891
|
+
forwardMessage += ' timestamp ' + self.number_to_string(paginationTimestamp)
|
1892
|
+
self.log(forwardMessage)
|
1893
|
+
if responseLength == 0:
|
1894
|
+
break
|
1895
|
+
errors = 0
|
1896
|
+
result = self.array_concat(result, response)
|
1897
|
+
last = self.safe_value(response, responseLength - 1)
|
1898
|
+
paginationTimestamp = self.safe_integer(last, 'timestamp') + 1
|
1899
|
+
if (until is not None) and (paginationTimestamp >= until):
|
1900
|
+
break
|
1901
|
+
except Exception as e:
|
1902
|
+
errors += 1
|
1903
|
+
if errors > maxRetries:
|
1904
|
+
raise e
|
1905
|
+
uniqueResults = result
|
1906
|
+
if removeRepeatedOption:
|
1907
|
+
uniqueResults = self.remove_repeated_elements_from_array(result)
|
1908
|
+
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
|
1909
|
+
return self.filter_by_since_limit(uniqueResults, since, limit, key)
|
1910
|
+
|
1911
|
+
async def safe_deterministic_call(self, method: str, symbol: Str = None, since: Int = None, limit: Int = None, timeframe: Str = None, params={}):
|
1912
|
+
maxRetries = None
|
1913
|
+
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
|
1914
|
+
errors = 0
|
1915
|
+
while(errors <= maxRetries):
|
1916
|
+
try:
|
1917
|
+
if timeframe and method != 'fetchFundingRateHistory':
|
1918
|
+
return await getattr(self, method)(symbol, timeframe, since, limit, params)
|
1919
|
+
else:
|
1920
|
+
return await getattr(self, method)(symbol, since, limit, params)
|
1921
|
+
except Exception as e:
|
1922
|
+
if isinstance(e, RateLimitExceeded):
|
1923
|
+
raise e # if we are rate limited, we should not retry and fail fast
|
1924
|
+
errors += 1
|
1925
|
+
if errors > maxRetries:
|
1926
|
+
raise e
|
1927
|
+
return []
|
1928
|
+
|
1929
|
+
async def fetch_paginated_call_deterministic(self, method: str, symbol: Str = None, since: Int = None, limit: Int = None, timeframe: Str = None, params={}, maxEntriesPerRequest=None):
|
1930
|
+
maxCalls = None
|
1931
|
+
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
|
1932
|
+
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
|
1933
|
+
current = self.milliseconds()
|
1934
|
+
tasks = []
|
1935
|
+
time = self.parse_timeframe(timeframe) * 1000
|
1936
|
+
step = time * maxEntriesPerRequest
|
1937
|
+
currentSince = current - (maxCalls * step) - 1
|
1938
|
+
if since is not None:
|
1939
|
+
currentSince = max(currentSince, since)
|
1940
|
+
else:
|
1941
|
+
currentSince = max(currentSince, 1241440531000) # avoid timestamps older than 2009
|
1942
|
+
until = self.safe_integer_2(params, 'until', 'till') # do not omit it here
|
1943
|
+
if until is not None:
|
1944
|
+
requiredCalls = int(math.ceil((until - since)) / step)
|
1945
|
+
if requiredCalls > maxCalls:
|
1946
|
+
raise BadRequest(self.id + ' the number of required calls is greater than the max number of calls allowed, either increase the paginationCalls or decrease the since-until gap. Current paginationCalls limit is ' + str(maxCalls) + ' required calls is ' + str(requiredCalls))
|
1947
|
+
for i in range(0, maxCalls):
|
1948
|
+
if (until is not None) and (currentSince >= until):
|
1949
|
+
break
|
1950
|
+
if currentSince >= current:
|
1951
|
+
break
|
1952
|
+
tasks.append(self.safe_deterministic_call(method, symbol, currentSince, maxEntriesPerRequest, timeframe, params))
|
1953
|
+
currentSince = self.sum(currentSince, step) - 1
|
1954
|
+
results = await asyncio.gather(*tasks)
|
1955
|
+
result = []
|
1956
|
+
for i in range(0, len(results)):
|
1957
|
+
result = self.array_concat(result, results[i])
|
1958
|
+
uniqueResults = self.remove_repeated_elements_from_array(result)
|
1959
|
+
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
|
1960
|
+
return self.filter_by_since_limit(uniqueResults, since, limit, key)
|
1961
|
+
|
1962
|
+
async def fetch_paginated_call_cursor(self, method: str, symbol: Str = None, since=None, limit=None, params={}, cursorReceived=None, cursorSent=None, cursorIncrement=None, maxEntriesPerRequest=None):
|
1963
|
+
maxCalls = None
|
1964
|
+
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
|
1965
|
+
maxRetries = None
|
1966
|
+
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
|
1967
|
+
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
|
1968
|
+
cursorValue = None
|
1969
|
+
i = 0
|
1970
|
+
errors = 0
|
1971
|
+
result = []
|
1972
|
+
timeframe = self.safe_string(params, 'timeframe')
|
1973
|
+
params = self.omit(params, 'timeframe') # reading the timeframe from the method arguments to avoid changing the signature
|
1974
|
+
while(i < maxCalls):
|
1975
|
+
try:
|
1976
|
+
if cursorValue is not None:
|
1977
|
+
if cursorIncrement is not None:
|
1978
|
+
cursorValue = self.parse_to_int(cursorValue) + cursorIncrement
|
1979
|
+
params[cursorSent] = cursorValue
|
1980
|
+
response = None
|
1981
|
+
if method == 'fetchAccounts':
|
1982
|
+
response = await getattr(self, method)(params)
|
1983
|
+
elif method == 'getLeverageTiersPaginated' or method == 'fetchPositions':
|
1984
|
+
response = await getattr(self, method)(symbol, params)
|
1985
|
+
elif method == 'fetchOpenInterestHistory':
|
1986
|
+
response = await getattr(self, method)(symbol, timeframe, since, maxEntriesPerRequest, params)
|
1987
|
+
else:
|
1988
|
+
response = await getattr(self, method)(symbol, since, maxEntriesPerRequest, params)
|
1989
|
+
errors = 0
|
1990
|
+
responseLength = len(response)
|
1991
|
+
if self.verbose:
|
1992
|
+
cursorString = '' if (cursorValue is None) else cursorValue
|
1993
|
+
iteration = (i + 1)
|
1994
|
+
cursorMessage = 'Cursor pagination call ' + str(iteration) + ' method ' + method + ' response length ' + str(responseLength) + ' cursor ' + cursorString
|
1995
|
+
self.log(cursorMessage)
|
1996
|
+
if responseLength == 0:
|
1997
|
+
break
|
1998
|
+
result = self.array_concat(result, response)
|
1999
|
+
last = self.safe_dict(response, responseLength - 1)
|
2000
|
+
# cursorValue = self.safe_value(last['info'], cursorReceived)
|
2001
|
+
cursorValue = None # search for the cursor
|
2002
|
+
for j in range(0, responseLength):
|
2003
|
+
index = responseLength - j - 1
|
2004
|
+
entry = self.safe_dict(response, index)
|
2005
|
+
info = self.safe_dict(entry, 'info')
|
2006
|
+
cursor = self.safe_value(info, cursorReceived)
|
2007
|
+
if cursor is not None:
|
2008
|
+
cursorValue = cursor
|
2009
|
+
break
|
2010
|
+
if cursorValue is None:
|
2011
|
+
break
|
2012
|
+
lastTimestamp = self.safe_integer(last, 'timestamp')
|
2013
|
+
if lastTimestamp is not None and lastTimestamp < since:
|
2014
|
+
break
|
2015
|
+
except Exception as e:
|
2016
|
+
errors += 1
|
2017
|
+
if errors > maxRetries:
|
2018
|
+
raise e
|
2019
|
+
i += 1
|
2020
|
+
sorted = self.sort_cursor_paginated_result(result)
|
2021
|
+
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
|
2022
|
+
return self.filter_by_since_limit(sorted, since, limit, key)
|
2023
|
+
|
2024
|
+
async def fetch_paginated_call_incremental(self, method: str, symbol: Str = None, since=None, limit=None, params={}, pageKey=None, maxEntriesPerRequest=None):
|
2025
|
+
maxCalls = None
|
2026
|
+
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
|
2027
|
+
maxRetries = None
|
2028
|
+
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
|
2029
|
+
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
|
2030
|
+
i = 0
|
2031
|
+
errors = 0
|
2032
|
+
result = []
|
2033
|
+
while(i < maxCalls):
|
2034
|
+
try:
|
2035
|
+
params[pageKey] = i + 1
|
2036
|
+
response = await getattr(self, method)(symbol, since, maxEntriesPerRequest, params)
|
2037
|
+
errors = 0
|
2038
|
+
responseLength = len(response)
|
2039
|
+
if self.verbose:
|
2040
|
+
iteration = (i + str(1))
|
2041
|
+
incrementalMessage = 'Incremental pagination call ' + iteration + ' method ' + method + ' response length ' + str(responseLength)
|
2042
|
+
self.log(incrementalMessage)
|
2043
|
+
if responseLength == 0:
|
2044
|
+
break
|
2045
|
+
result = self.array_concat(result, response)
|
2046
|
+
except Exception as e:
|
2047
|
+
errors += 1
|
2048
|
+
if errors > maxRetries:
|
2049
|
+
raise e
|
2050
|
+
i += 1
|
2051
|
+
sorted = self.sort_cursor_paginated_result(result)
|
2052
|
+
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
|
2053
|
+
return self.filter_by_since_limit(sorted, since, limit, key)
|
2054
|
+
|
2055
|
+
async def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}):
|
2056
|
+
"""
|
2057
|
+
fetches the history of margin added or reduced from contract isolated positions
|
2058
|
+
:param str [symbol]: unified market symbol
|
2059
|
+
:param int [since]: timestamp in ms of the position
|
2060
|
+
:param int [limit]: the maximum amount of candles to fetch, default=1000
|
2061
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
2062
|
+
:returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
|
2063
|
+
"""
|
2064
|
+
if self.has['fetchPositionsHistory']:
|
2065
|
+
positions = await self.fetch_positions_history([symbol], since, limit, params)
|
2066
|
+
return positions
|
2067
|
+
else:
|
2068
|
+
raise NotSupported(self.id + ' fetchPositionHistory() is not supported yet')
|
2069
|
+
|
2070
|
+
async def fetch_positions_history(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
|
2071
|
+
"""
|
2072
|
+
fetches the history of margin added or reduced from contract isolated positions
|
2073
|
+
:param str [symbol]: unified market symbol
|
2074
|
+
:param int [since]: timestamp in ms of the position
|
2075
|
+
:param int [limit]: the maximum amount of candles to fetch, default=1000
|
2076
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
2077
|
+
:returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
|
2078
|
+
"""
|
2079
|
+
raise NotSupported(self.id + ' fetchPositionsHistory() is not supported yet')
|
2080
|
+
|
2081
|
+
async def fetch_transfer(self, id: str, code: Str = None, params={}):
|
2082
|
+
"""
|
2083
|
+
fetches a transfer
|
2084
|
+
:param str id: transfer id
|
2085
|
+
:param [str] code: unified currency code
|
2086
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
2087
|
+
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
|
2088
|
+
"""
|
2089
|
+
raise NotSupported(self.id + ' fetchTransfer() is not supported yet')
|
2090
|
+
|
2091
|
+
async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
2092
|
+
"""
|
2093
|
+
fetches a transfer
|
2094
|
+
:param str id: transfer id
|
2095
|
+
:param int [since]: timestamp in ms of the earliest transfer to fetch
|
2096
|
+
:param int [limit]: the maximum amount of transfers to fetch
|
2097
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
2098
|
+
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
|
2099
|
+
"""
|
2100
|
+
raise NotSupported(self.id + ' fetchTransfers() is not supported yet')
|