Files
ccxt_with_mt5/ccxt/async_support/base/exchange.py
lz_db 0fab423a18 add
2025-11-16 12:31:03 +08:00

2309 lines
126 KiB
Python

# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
__version__ = '4.5.18'
# -----------------------------------------------------------------------------
import asyncio
import concurrent.futures
import socket
import certifi
import aiohttp
import ssl
import sys
import yarl
import math
from typing import Any, List
from ccxt.base.types import Int, Str, Num, Strings
# -----------------------------------------------------------------------------
from ccxt.async_support.base.throttler import Throttler
# -----------------------------------------------------------------------------
from ccxt.base.errors import BaseError, BadSymbol, BadRequest, BadResponse, ExchangeError, ExchangeNotAvailable, RequestTimeout, NotSupported, NullResponse, InvalidAddress, RateLimitExceeded, OperationFailed
from ccxt.base.types import ConstructorArgs, OrderType, OrderSide, OrderRequest, CancellationRequest, Order
# -----------------------------------------------------------------------------
from ccxt.base.exchange import Exchange as BaseExchange, ArgumentsRequired
# -----------------------------------------------------------------------------
from ccxt.async_support.base.ws.functions import inflate, inflate64, gunzip
from ccxt.async_support.base.ws.client import Client
from ccxt.async_support.base.ws.future import Future
from ccxt.async_support.base.ws.order_book import OrderBook, IndexedOrderBook, CountedOrderBook
# -----------------------------------------------------------------------------
try:
from aiohttp_socks import ProxyConnector as SocksProxyConnector
except ImportError:
SocksProxyConnector = None
# -----------------------------------------------------------------------------
__all__ = [
'BaseExchange',
'Exchange',
]
# -----------------------------------------------------------------------------
# --- PROTO BUF IMPORTS
try:
from ccxt.protobuf.mexc import PushDataV3ApiWrapper_pb2
from google.protobuf.json_format import MessageToDict
except ImportError:
PushDataV3ApiWrapper_pb2 = None
MessageToDict = None
# -----------------------------------------------------------------------------
class Exchange(BaseExchange):
synchronous = False
streaming = {
'maxPingPongMisses': 2,
'keepAlive': 30000
}
ping = None
newUpdates = True
clients = {}
timeout_on_exit = 250 # needed for: https://github.com/ccxt/ccxt/pull/23470
def __init__(self, config: ConstructorArgs = {}):
if 'asyncio_loop' in config:
self.asyncio_loop = config['asyncio_loop']
self.aiohttp_trust_env = config.get('aiohttp_trust_env', self.aiohttp_trust_env)
self.verify = config.get('verify', self.verify)
self.own_session = 'session' not in config
self.cafile = config.get('cafile', certifi.where())
self.throttler = None
super(Exchange, self).__init__(config)
self.markets_loading = None
self.reloading_markets = False
def get_event_loop(self):
return self.asyncio_loop
def init_throttler(self, cost=None):
self.throttler = Throttler(self.tokenBucket, self.asyncio_loop)
async def throttle(self, cost=None):
return await self.throttler(cost)
def get_session(self):
return self.session
def __del__(self):
if self.session is not None or self.socks_proxy_sessions is not None:
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).")
if sys.version_info >= (3, 5):
async def __aenter__(self):
self.open()
return self
async def __aexit__(self, exc_type, exc, tb):
await self.close()
def open(self):
if self.asyncio_loop is None:
if sys.version_info >= (3, 7):
self.asyncio_loop = asyncio.get_running_loop()
else:
self.asyncio_loop = asyncio.get_event_loop()
self.throttler.loop = self.asyncio_loop
if self.ssl_context is None:
# Create our SSL context object with our CA cert file
self.ssl_context = ssl.create_default_context(cafile=self.cafile) if self.verify else self.verify
if (self.ssl_context and self.safe_bool(self.options, 'include_OS_certificates', False)):
os_default_paths = ssl.get_default_verify_paths()
if os_default_paths.cafile and os_default_paths.cafile != self.cafile:
self.ssl_context.load_verify_locations(cafile=os_default_paths.cafile)
if self.own_session and self.session is None:
# Pass this SSL context to aiohttp and create a TCPConnector
self.tcp_connector = aiohttp.TCPConnector(ssl=self.ssl_context, loop=self.asyncio_loop, enable_cleanup_closed=True)
self.session = aiohttp.ClientSession(loop=self.asyncio_loop, connector=self.tcp_connector, trust_env=self.aiohttp_trust_env)
async def close(self):
await self.ws_close()
if self.session is not None:
if self.own_session:
await self.session.close()
self.session = None
await self.close_connector()
await self.close_proxy_sessions()
await self.sleep(self.timeout_on_exit)
async def close_connector(self):
if self.tcp_connector is not None:
await self.tcp_connector.close()
self.tcp_connector = None
if self.aiohttp_socks_connector is not None:
await self.aiohttp_socks_connector.close()
self.aiohttp_socks_connector = None
async def close_proxy_sessions(self):
if self.socks_proxy_sessions is not None:
for url in self.socks_proxy_sessions:
await self.socks_proxy_sessions[url].close()
self.socks_proxy_sessions = None
async def fetch(self, url, method='GET', headers=None, body=None):
"""Perform a HTTP request and return decoded JSON data"""
# ##### PROXY & HEADERS #####
request_headers = self.prepare_request_headers(headers)
self.last_request_headers = request_headers
# proxy-url
proxyUrl = self.check_proxy_url_settings(url, method, headers, body)
if proxyUrl is not None:
request_headers.update({'Origin': self.origin})
url = proxyUrl + self.url_encoder_for_proxy_url(url)
# proxy agents
final_proxy = None # set default
proxy_session = None
httpProxy, httpsProxy, socksProxy = self.check_proxy_settings(url, method, headers, body)
if httpProxy:
final_proxy = httpProxy
elif httpsProxy:
final_proxy = httpsProxy
elif socksProxy:
if SocksProxyConnector is None:
raise NotSupported(self.id + ' - to use SOCKS proxy with ccxt, you need "aiohttp_socks" module that can be installed by "pip install aiohttp_socks"')
# override session
if (self.socks_proxy_sessions is None):
self.socks_proxy_sessions = {}
if (socksProxy not in self.socks_proxy_sessions):
# Create our SSL context object with our CA cert file
self.open() # ensure `asyncio_loop` is set
proxy_session = self.get_socks_proxy_session(socksProxy)
# add aiohttp_proxy for python as exclusion
elif self.aiohttp_proxy:
final_proxy = self.aiohttp_proxy
proxyAgentSet = final_proxy is not None or socksProxy is not None
self.checkConflictingProxies(proxyAgentSet, proxyUrl)
# avoid old proxies mixing
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):
raise NotSupported(self.id + ' you have set multiple proxies, please use one or another')
# log
if self.verbose:
self.log("\nfetch Request:", self.id, method, url, "RequestHeaders:", request_headers, "RequestBody:", body)
self.logger.debug("%s %s, Request: %s %s", method, url, headers, body)
# end of proxies & headers
request_body = body
encoded_body = body.encode() if body else None
self.open()
final_session = proxy_session if proxy_session is not None else self.session
session_method = getattr(final_session, method.lower())
http_response = None
http_status_code = None
http_status_text = None
json_response = None
try:
async with session_method(yarl.URL(url, encoded=True),
data=encoded_body,
headers=request_headers,
timeout=(self.timeout / 1000),
proxy=final_proxy) as response:
http_response = await response.text(errors='replace')
# CIMultiDictProxy
raw_headers = response.headers
headers = {}
for header in raw_headers:
if header in headers:
headers[header] = headers[header] + ', ' + raw_headers[header]
else:
headers[header] = raw_headers[header]
http_status_code = response.status
http_status_text = response.reason
http_response = self.on_rest_response(http_status_code, http_status_text, url, method, headers, http_response, request_headers, request_body)
json_response = self.parse_json(http_response)
if self.enableLastHttpResponse:
self.last_http_response = http_response
if self.enableLastResponseHeaders:
self.last_response_headers = headers
if self.enableLastJsonResponse:
self.last_json_response = json_response
if self.verbose:
self.log("\nfetch Response:", self.id, method, url, http_status_code, "ResponseHeaders:", headers, "ResponseBody:", http_response)
if json_response and not isinstance(json_response, list) and self.returnResponseHeaders:
json_response['responseHeaders'] = headers
self.logger.debug("%s %s, Response: %s %s %s", method, url, http_status_code, headers, http_response)
except socket.gaierror as e:
details = ' '.join([self.id, method, url])
raise ExchangeNotAvailable(details) from e
except (concurrent.futures.TimeoutError, asyncio.TimeoutError) as e:
details = ' '.join([self.id, method, url])
raise RequestTimeout(details) from e
except aiohttp.ClientConnectionError as e:
details = ' '.join([self.id, method, url])
raise ExchangeNotAvailable(details) from e
except aiohttp.ClientError as e: # base exception class
details = ' '.join([self.id, method, url])
raise ExchangeError(details) from e
self.handle_errors(http_status_code, http_status_text, url, method, headers, http_response, json_response, request_headers, request_body)
self.handle_http_status_code(http_status_code, http_status_text, url, method, http_response)
if json_response is not None:
return json_response
if self.is_text_response(headers):
return http_response
if http_response == '' or http_response is None:
return http_response
return response.content
def get_socks_proxy_session(self, socksProxy):
if (self.socks_proxy_sessions is None):
self.socks_proxy_sessions = {}
if (socksProxy not in self.socks_proxy_sessions):
reverse_dns = socksProxy.startswith('socks5h://')
socks_proxy_selected = socksProxy if not reverse_dns else socksProxy.replace('socks5h://', 'socks5://')
self.aiohttp_socks_connector = SocksProxyConnector.from_url(
socks_proxy_selected,
# extra args copied from self.open()
ssl=self.ssl_context,
loop=self.asyncio_loop,
enable_cleanup_closed=True,
rdns=reverse_dns if reverse_dns else None
)
self.socks_proxy_sessions[socksProxy] = aiohttp.ClientSession(loop=self.asyncio_loop, connector=self.aiohttp_socks_connector, trust_env=self.aiohttp_trust_env)
return self.socks_proxy_sessions[socksProxy]
async def load_markets_helper(self, reload=False, params={}):
if not reload:
if self.markets:
if not self.markets_by_id:
return self.set_markets(self.markets)
return self.markets
currencies = None
if self.has['fetchCurrencies'] is True:
currencies = await self.fetch_currencies()
self.options['cachedCurrencies'] = currencies
markets = await self.fetch_markets(params)
if 'cachedCurrencies' in self.options:
del self.options['cachedCurrencies']
return self.set_markets(markets, currencies)
async def load_markets(self, reload=False, params={}):
"""
Loads and prepares the markets for trading.
Args:
reload (bool): If True, the markets will be reloaded from the exchange.
params (dict): Additional exchange-specific parameters for the request.
Returns:
dict: A dictionary of markets.
Raises:
Exception: If the markets cannot be loaded or prepared.
Notes:
This method is asynchronous.
It ensures that the markets are only loaded once, even if called multiple times.
If the markets are already loaded and `reload` is False or not provided, it returns the existing markets.
If a reload is in progress, it waits for completion before returning.
If an error occurs during loading or preparation, an exception is raised.
"""
if (reload and not self.reloading_markets) or not self.markets_loading:
self.reloading_markets = True
coroutine = self.load_markets_helper(reload, params)
# coroutines can only be awaited once so we wrap it in a task
self.markets_loading = asyncio.ensure_future(coroutine)
try:
result = await self.markets_loading
except asyncio.CancelledError as e: # CancelledError is a base exception so we need to catch it explicitly
self.reloading_markets = False
self.markets_loading = None
raise e
except Exception as e:
self.reloading_markets = False
self.markets_loading = None
raise e
self.reloading_markets = False
return result
async def load_fees(self, reload=False):
if not reload:
if self.loaded_fees != Exchange.loaded_fees:
return self.loaded_fees
self.loaded_fees = self.deep_extend(self.loaded_fees, await self.fetch_fees())
return self.loaded_fees
async def fetch_markets(self, params={}):
# markets are returned as a list
# currencies are returned as a dict
# this is for historical reasons
# and may be changed for consistency later
return self.to_array(self.markets)
async def fetch_currencies(self, params={}):
# markets are returned as a list
# currencies are returned as a dict
# this is for historical reasons
# and may be changed for consistency later
return self.currencies
async def fetchOHLCVC(self, symbol, timeframe='1m', since=None, limit=None, params={}):
return await self.fetch_ohlcvc(symbol, timeframe, since, limit, params)
async def fetch_full_tickers(self, symbols=None, params={}):
return await self.fetch_tickers(symbols, params)
async def sleep(self, milliseconds):
return await asyncio.sleep(milliseconds / 1000)
async def spawn_async(self, method, *args):
try:
await method(*args)
except Exception:
# todo: handle spawned errors
pass
def spawn(self, method, *args):
def callback(asyncio_future):
exception = asyncio_future.exception()
if exception is None:
future.resolve(asyncio_future.result())
else:
future.reject(exception)
future = Future()
task = self.asyncio_loop.create_task(method(*args))
task.add_done_callback(callback)
return future
# -----------------------------------------------------------------------
# WS/PRO code
@staticmethod
def inflate(data):
return inflate(data)
@staticmethod
def inflate64(data):
return inflate64(data)
@staticmethod
def gunzip(data):
return gunzip(data)
def order_book(self, snapshot={}, depth=None):
return OrderBook(snapshot, depth)
def indexed_order_book(self, snapshot={}, depth=None):
return IndexedOrderBook(snapshot, depth)
def counted_order_book(self, snapshot={}, depth=None):
return CountedOrderBook(snapshot, depth)
def client(self, url):
self.clients = self.clients or {}
if url not in self.clients:
on_message = self.handle_message
on_error = self.on_error
on_close = self.on_close
on_connected = self.on_connected
# decide client type here: aiohttp ws / websockets / signalr / socketio
ws_options = self.safe_value(self.options, 'ws', {})
options = self.extend(self.streaming, {
'log': getattr(self, 'log'),
'ping': getattr(self, 'ping', None),
'verbose': self.verbose,
'throttle': Throttler(self.tokenBucket, self.asyncio_loop),
'asyncio_loop': self.asyncio_loop,
'decompressBinary': self.safe_bool(self.options, 'decompressBinary', True),
}, ws_options)
# we use aiohttp instead of fastClient now because of this
# https://github.com/ccxt/ccxt/pull/25995
self.clients[url] = Client(url, on_message, on_error, on_close, on_connected, options)
# set http/s proxy (socks proxy should be set in other place)
httpProxy, httpsProxy, socksProxy = self.check_ws_proxy_settings()
if (httpProxy or httpsProxy):
self.clients[url].proxy = httpProxy if httpProxy else httpsProxy
return self.clients[url]
def delay(self, timeout, method, *args):
return self.asyncio_loop.call_later(timeout / 1000, self.spawn, method, *args)
def handle_message(self, client, message):
always = True
if always:
raise NotSupported(self.id + '.handle_message() not implemented yet')
return {}
def watch_multiple(self, url, message_hashes, message=None, subscribe_hashes=None, subscription=None):
# base exchange self.open starts the aiohttp Session in an async context
self.open()
backoff_delay = 0
client = self.client(url)
future = Future.race([client.future(message_hash) for message_hash in message_hashes])
missing_subscriptions = []
if subscribe_hashes is not None:
for subscribe_hash in subscribe_hashes:
if subscribe_hash not in client.subscriptions:
missing_subscriptions.append(subscribe_hash)
client.subscriptions[subscribe_hash] = subscription or True
connected = client.connected if client.connected.done() \
else asyncio.ensure_future(client.connect(self.session, backoff_delay))
def after(fut):
# todo: decouple signing from subscriptions
options = self.safe_value(self.options, 'ws')
cost = self.safe_value(options, 'cost', 1)
if message:
async def send_message():
if self.enableRateLimit:
await client.throttle(cost)
try:
await client.send(message)
except ConnectionError as e:
client.on_error(e)
except Exception as e:
client.on_error(e)
asyncio.ensure_future(send_message())
if missing_subscriptions:
connected.add_done_callback(after)
return future
def watch(self, url, message_hash, message=None, subscribe_hash=None, subscription=None):
# base exchange self.open starts the aiohttp Session in an async context
self.open()
backoff_delay = 0
client = self.client(url)
if subscribe_hash is None and message_hash in client.futures:
return client.futures[message_hash]
future = client.future(message_hash)
subscribed = client.subscriptions.get(subscribe_hash)
if not subscribed:
client.subscriptions[subscribe_hash] = subscription or True
selected_session = self.session
# http/s proxy is being set in other places
httpProxy, httpsProxy, socksProxy = self.check_ws_proxy_settings()
if (socksProxy):
selected_session = self.get_socks_proxy_session(socksProxy)
connected = client.connected if client.connected.done() \
else asyncio.ensure_future(client.connect(selected_session, backoff_delay))
def after(fut):
# todo: decouple signing from subscriptions
options = self.safe_value(self.options, 'ws')
cost = self.safe_value(options, 'cost', 1)
if message:
async def send_message():
if self.enableRateLimit:
await client.throttle(cost)
try:
await client.send(message)
except ConnectionError as e:
client.on_error(e)
except Exception as e:
client.on_error(e)
asyncio.ensure_future(send_message())
if not subscribed:
connected.add_done_callback(after)
return future
def on_connected(self, client, message=None):
# for user hooks
# print('Connected to', client.url)
pass
def on_error(self, client, error):
if client.url in self.clients and self.clients[client.url].error:
del self.clients[client.url]
def on_close(self, client, error):
if client.error:
# connection closed by the user or due to an error
pass
else:
# server disconnected a working connection
if client.url in self.clients:
del self.clients[client.url]
async def ws_close(self):
if self.clients:
await asyncio.wait([asyncio.create_task(client.close()) for client in self.clients.values()], return_when=asyncio.ALL_COMPLETED)
for url in self.clients.copy():
del self.clients[url]
async def load_order_book(self, client, messageHash, symbol, limit=None, params={}):
if symbol not in self.orderbooks:
client.reject(ExchangeError(self.id + ' loadOrderBook() orderbook is not initiated'), messageHash)
return
try:
maxRetries = self.handle_option('watchOrderBook', 'maxRetries', 3)
tries = 0
stored = self.orderbooks[symbol]
while tries < maxRetries:
cache = stored.cache
order_book = await self.fetch_order_book(symbol, limit, params)
index = self.get_cache_index(order_book, cache)
if index >= 0:
stored.reset(order_book)
self.handle_deltas(stored, cache[index:])
cache.clear()
client.resolve(stored, messageHash)
return
tries += 1
client.reject(ExchangeError(self.id + ' nonce is behind cache after ' + str(maxRetries) + ' tries.'), messageHash)
del self.clients[client.url]
except BaseError as e:
client.reject(e, messageHash)
await self.load_order_book(client, messageHash, symbol, limit, params)
def format_scientific_notation_ftx(self, n):
if n == 0:
return '0e-00'
return format(n, 'g')
def decode_proto_msg(self, data):
if not MessageToDict:
raise NotSupported(self.id + ' requires protobuf to decode messages, please install it with `pip install "protobuf==5.29.5"`')
message = PushDataV3ApiWrapper_pb2.PushDataV3ApiWrapper()
message.ParseFromString(data)
dict_msg = MessageToDict(message)
# {
# "channel":"spot@public.kline.v3.api.pb@BTCUSDT@Min1",
# "symbol":"BTCUSDT",
# "symbolId":"2fb942154ef44a4ab2ef98c8afb6a4a7",
# "createTime":"1754735110559",
# "publicSpotKline":{
# "interval":"Min1",
# "windowStart":"1754735100",
# "openingPrice":"117792.45",
# "closingPrice":"117805.32",
# "highestPrice":"117814.63",
# "lowestPrice":"117792.45",
# "volume":"0.13425465",
# "amount":"15815.77",
# "windowEnd":"1754735160"
# }
# }
return dict_msg
# ########################################################################
# ########################################################################
# ########################################################################
# ########################################################################
# ######## ######## ########
# ######## ######## ########
# ######## ######## ########
# ######## ######## ########
# ######## ######################## ########################
# ######## ######################## ########################
# ######## ######################## ########################
# ######## ######################## ########################
# ######## ######## ########
# ######## ######## ########
# ######## ######## ########
# ######## ######## ########
# ########################################################################
# ########################################################################
# ########################################################################
# ########################################################################
# ######## ######## ######## ########
# ######## ######## ######## ########
# ######## ######## ######## ########
# ######## ######## ######## ########
# ################ ######################## ################
# ################ ######################## ################
# ################ ######################## ################
# ################ ######################## ################
# ######## ######## ################ ################
# ######## ######## ################ ################
# ######## ######## ################ ################
# ######## ######## ################ ################
# ########################################################################
# ########################################################################
# ########################################################################
# ########################################################################
# METHODS BELOW THIS LINE ARE TRANSPILED FROM TYPESCRIPT
async def fetch_accounts(self, params={}):
raise NotSupported(self.id + ' fetchAccounts() is not supported yet')
async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchTrades() is not supported yet')
async def fetch_trades_ws(self, symbol: str, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchTradesWs() is not supported yet')
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
if self.has['watchLiquidationsForSymbols']:
return await self.watch_liquidations_for_symbols([symbol], since, limit, params)
raise NotSupported(self.id + ' watchLiquidations() is not supported yet')
async def watch_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchLiquidationsForSymbols() is not supported yet')
async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
if self.has['watchMyLiquidationsForSymbols']:
return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
raise NotSupported(self.id + ' watchMyLiquidations() is not supported yet')
async def watch_my_liquidations_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchMyLiquidationsForSymbols() is not supported yet')
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchTrades() is not supported yet')
async def un_watch_orders(self, symbol: Str = None, params={}):
raise NotSupported(self.id + ' unWatchOrders() is not supported yet')
async def un_watch_trades(self, symbol: str, params={}):
raise NotSupported(self.id + ' unWatchTrades() is not supported yet')
async def watch_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchTradesForSymbols() is not supported yet')
async def un_watch_trades_for_symbols(self, symbols: List[str], params={}):
raise NotSupported(self.id + ' unWatchTradesForSymbols() is not supported yet')
async def watch_my_trades_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchMyTradesForSymbols() is not supported yet')
async def watch_orders_for_symbols(self, symbols: List[str], since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchOrdersForSymbols() is not supported yet')
async def watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchOHLCVForSymbols() is not supported yet')
async def un_watch_ohlcv_for_symbols(self, symbolsAndTimeframes: List[List[str]], params={}):
raise NotSupported(self.id + ' unWatchOHLCVForSymbols() is not supported yet')
async def watch_order_book_for_symbols(self, symbols: List[str], limit: Int = None, params={}):
raise NotSupported(self.id + ' watchOrderBookForSymbols() is not supported yet')
async def un_watch_order_book_for_symbols(self, symbols: List[str], params={}):
raise NotSupported(self.id + ' unWatchOrderBookForSymbols() is not supported yet')
async def un_watch_positions(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' unWatchPositions() is not supported yet')
async def un_watch_ticker(self, symbol: str, params={}):
raise NotSupported(self.id + ' unWatchTicker() is not supported yet')
async def un_watch_mark_price(self, symbol: str, params={}):
raise NotSupported(self.id + ' unWatchMarkPrice() is not supported yet')
async def un_watch_mark_prices(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' unWatchMarkPrices() is not supported yet')
async def fetch_deposit_addresses(self, codes: Strings = None, params={}):
raise NotSupported(self.id + ' fetchDepositAddresses() is not supported yet')
async def fetch_order_book(self, symbol: str, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchOrderBook() is not supported yet')
async def fetch_order_book_ws(self, symbol: str, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchOrderBookWs() is not supported yet')
async def fetch_margin_mode(self, symbol: str, params={}):
if self.has['fetchMarginModes']:
marginModes = await self.fetch_margin_modes([symbol], params)
return self.safe_dict(marginModes, symbol)
else:
raise NotSupported(self.id + ' fetchMarginMode() is not supported yet')
async def fetch_margin_modes(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchMarginModes() is not supported yet')
async def fetch_rest_order_book_safe(self, symbol, limit=None, params={}):
fetchSnapshotMaxRetries = self.handle_option('watchOrderBook', 'maxRetries', 3)
for i in range(0, fetchSnapshotMaxRetries):
try:
orderBook = await self.fetch_order_book(symbol, limit, params)
return orderBook
except Exception as e:
if (i + 1) == fetchSnapshotMaxRetries:
raise e
return None
async def watch_order_book(self, symbol: str, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchOrderBook() is not supported yet')
async def un_watch_order_book(self, symbol: str, params={}):
raise NotSupported(self.id + ' unWatchOrderBook() is not supported yet')
async def fetch_time(self, params={}):
raise NotSupported(self.id + ' fetchTime() is not supported yet')
async def fetch_trading_limits(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchTradingLimits() is not supported yet')
async def fetch_cross_borrow_rates(self, params={}):
raise NotSupported(self.id + ' fetchCrossBorrowRates() is not supported yet')
async def fetch_isolated_borrow_rates(self, params={}):
raise NotSupported(self.id + ' fetchIsolatedBorrowRates() is not supported yet')
async def fetch_leverage_tiers(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchLeverageTiers() is not supported yet')
async def fetch_funding_rates(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchFundingRates() is not supported yet')
async def fetch_funding_intervals(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchFundingIntervals() is not supported yet')
async def watch_funding_rate(self, symbol: str, params={}):
raise NotSupported(self.id + ' watchFundingRate() is not supported yet')
async def watch_funding_rates(self, symbols: List[str], params={}):
raise NotSupported(self.id + ' watchFundingRates() is not supported yet')
async def watch_funding_rates_for_symbols(self, symbols: List[str], params={}):
return await self.watch_funding_rates(symbols, params)
async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}):
raise NotSupported(self.id + ' transfer() is not supported yet')
async def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}):
raise NotSupported(self.id + ' withdraw() is not supported yet')
async def create_deposit_address(self, code: str, params={}):
raise NotSupported(self.id + ' createDepositAddress() is not supported yet')
async def set_leverage(self, leverage: int, symbol: Str = None, params={}):
raise NotSupported(self.id + ' setLeverage() is not supported yet')
async def fetch_leverage(self, symbol: str, params={}):
if self.has['fetchLeverages']:
leverages = await self.fetch_leverages([symbol], params)
return self.safe_dict(leverages, symbol)
else:
raise NotSupported(self.id + ' fetchLeverage() is not supported yet')
async def fetch_leverages(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchLeverages() is not supported yet')
async def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
raise NotSupported(self.id + ' setPositionMode() is not supported yet')
async def add_margin(self, symbol: str, amount: float, params={}):
raise NotSupported(self.id + ' addMargin() is not supported yet')
async def reduce_margin(self, symbol: str, amount: float, params={}):
raise NotSupported(self.id + ' reduceMargin() is not supported yet')
async def set_margin(self, symbol: str, amount: float, params={}):
raise NotSupported(self.id + ' setMargin() is not supported yet')
async def fetch_long_short_ratio(self, symbol: str, timeframe: Str = None, params={}):
raise NotSupported(self.id + ' fetchLongShortRatio() is not supported yet')
async def fetch_long_short_ratio_history(self, symbol: Str = None, timeframe: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchLongShortRatioHistory() is not supported yet')
async def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}):
"""
fetches the history of margin added or reduced from contract isolated positions
:param str [symbol]: unified market symbol
:param str [type]: "add" or "reduce"
:param int [since]: timestamp in ms of the earliest change to fetch
:param int [limit]: the maximum amount of changes to fetch
:param dict params: extra parameters specific to the exchange api endpoint
:returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
"""
raise NotSupported(self.id + ' fetchMarginAdjustmentHistory() is not supported yet')
async def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
raise NotSupported(self.id + ' setMarginMode() is not supported yet')
async def fetch_deposit_addresses_by_network(self, code: str, params={}):
raise NotSupported(self.id + ' fetchDepositAddressesByNetwork() is not supported yet')
async def fetch_open_interest_history(self, symbol: str, timeframe: str = '1h', since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchOpenInterestHistory() is not supported yet')
async def fetch_open_interest(self, symbol: str, params={}):
raise NotSupported(self.id + ' fetchOpenInterest() is not supported yet')
async def fetch_open_interests(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchOpenInterests() is not supported yet')
async def sign_in(self, params={}):
raise NotSupported(self.id + ' signIn() is not supported yet')
async def fetch_payment_methods(self, params={}):
raise NotSupported(self.id + ' fetchPaymentMethods() is not supported yet')
async def fetch_borrow_rate(self, code: str, amount: float, params={}):
raise NotSupported(self.id + ' fetchBorrowRate is deprecated, please use fetchCrossBorrowRate or fetchIsolatedBorrowRate instead')
async def repay_cross_margin(self, code: str, amount: float, params={}):
raise NotSupported(self.id + ' repayCrossMargin is not support yet')
async def repay_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
raise NotSupported(self.id + ' repayIsolatedMargin is not support yet')
async def borrow_cross_margin(self, code: str, amount: float, params={}):
raise NotSupported(self.id + ' borrowCrossMargin is not support yet')
async def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
raise NotSupported(self.id + ' borrowIsolatedMargin is not support yet')
async def borrow_margin(self, code: str, amount: float, symbol: Str = None, params={}):
raise NotSupported(self.id + ' borrowMargin is deprecated, please use borrowCrossMargin or borrowIsolatedMargin instead')
async def repay_margin(self, code: str, amount: float, symbol: Str = None, params={}):
raise NotSupported(self.id + ' repayMargin is deprecated, please use repayCrossMargin or repayIsolatedMargin instead')
async def fetch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
message = ''
if self.has['fetchTrades']:
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'
raise NotSupported(self.id + ' fetchOHLCV() is not supported yet' + message)
async def fetch_ohlcv_ws(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
message = ''
if self.has['fetchTradesWs']:
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'
raise NotSupported(self.id + ' fetchOHLCVWs() is not supported yet. Try using fetchOHLCV instead.' + message)
async def watch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchOHLCV() is not supported yet')
async def fetch_web_endpoint(self, method, endpointMethod, returnAsJson, startRegex=None, endRegex=None):
errorMessage = ''
options = self.safe_value(self.options, method, {})
muteOnFailure = self.safe_bool(options, 'webApiMuteFailure', True)
try:
# if it was not explicitly disabled, then don't fetch
if self.safe_bool(options, 'webApiEnable', True) is not True:
return None
maxRetries = self.safe_value(options, 'webApiRetries', 10)
response = None
retry = 0
shouldBreak = False
while(retry < maxRetries):
try:
response = await getattr(self, endpointMethod)({})
shouldBreak = True
break
except Exception as e:
retry = retry + 1
if retry == maxRetries:
raise e
if shouldBreak:
break # self is needed because of GO
content = response
if startRegex is not None:
splitted_by_start = content.split(startRegex)
content = splitted_by_start[1] # we need second part after start
if endRegex is not None:
splitted_by_end = content.split(endRegex)
content = splitted_by_end[0] # we need first part after start
if returnAsJson and (isinstance(content, str)):
jsoned = self.parse_json(content.strip()) # content should be trimmed before json parsing
if jsoned:
return jsoned # if parsing was not successfull, exception should be thrown
else:
raise BadResponse('could not parse the response into json')
else:
return content
except Exception as e:
errorMessage = self.id + ' ' + method + '() failed to fetch correct data from website. Probably webpage markup has been changed, breaking the page custom parser.'
if muteOnFailure:
return None
else:
raise BadResponse(errorMessage)
async def fetch_l2_order_book(self, symbol: str, limit: Int = None, params={}):
orderbook = await self.fetch_order_book(symbol, limit, params)
return self.extend(orderbook, {
'asks': self.sort_by(self.aggregate(orderbook['asks']), 0),
'bids': self.sort_by(self.aggregate(orderbook['bids']), 0, True),
})
async def load_trading_limits(self, symbols: Strings = None, reload=False, params={}):
if self.has['fetchTradingLimits']:
if reload or not ('limitsLoaded' in self.options):
response = await self.fetch_trading_limits(symbols)
for i in range(0, len(symbols)):
symbol = symbols[i]
self.markets[symbol] = self.deep_extend(self.markets[symbol], response[symbol])
self.options['limitsLoaded'] = self.milliseconds()
return self.markets
async def fetch2(self, path, api: Any = 'public', method='GET', params={}, headers: Any = None, body: Any = None, config={}):
if self.enableRateLimit:
cost = self.calculate_rate_limiter_cost(api, method, path, params, config)
await self.throttle(cost)
retries = None
retries, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailure', 0)
retryDelay = None
retryDelay, params = self.handle_option_and_params(params, path, 'maxRetriesOnFailureDelay', 0)
self.lastRestRequestTimestamp = self.milliseconds()
request = self.sign(path, api, method, params, headers, body)
self.last_request_headers = request['headers']
self.last_request_body = request['body']
self.last_request_url = request['url']
for i in range(0, retries + 1):
try:
return await self.fetch(request['url'], request['method'], request['headers'], request['body'])
except Exception as e:
if isinstance(e, OperationFailed):
if i < retries:
if self.verbose:
self.log('Request failed with the error: ' + str(e) + ', retrying ' + (i + str(1)) + ' of ' + str(retries) + '...')
if (retryDelay is not None) and (retryDelay != 0):
await self.sleep(retryDelay)
else:
raise e
else:
raise e
return None # self line is never reached, but exists for c# value return requirement
async def request(self, path, api: Any = 'public', method='GET', params={}, headers: Any = None, body: Any = None, config={}):
return await self.fetch2(path, api, method, params, headers, body, config)
async def load_accounts(self, reload=False, params={}):
if reload:
self.accounts = await self.fetch_accounts(params)
else:
if self.accounts:
return self.accounts
else:
self.accounts = await self.fetch_accounts(params)
self.accountsById = self.index_by(self.accounts, 'id')
return self.accounts
async def edit_limit_buy_order(self, id: str, symbol: str, amount: float, price: Num = None, params={}):
return await self.edit_limit_order(id, symbol, 'buy', amount, price, params)
async def edit_limit_sell_order(self, id: str, symbol: str, amount: float, price: Num = None, params={}):
return await self.edit_limit_order(id, symbol, 'sell', amount, price, params)
async def edit_limit_order(self, id: str, symbol: str, side: OrderSide, amount: float, price: Num = None, params={}):
return await self.edit_order(id, symbol, 'limit', side, amount, price, params)
async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
await self.cancel_order(id, symbol)
return await self.create_order(symbol, type, side, amount, price, params)
async def edit_order_with_client_order_id(self, clientOrderId: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
return await self.edit_order('', symbol, type, side, amount, price, self.extend({'clientOrderId': clientOrderId}, params))
async def edit_order_ws(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
await self.cancel_order_ws(id, symbol)
return await self.create_order_ws(symbol, type, side, amount, price, params)
async def fetch_position(self, symbol: str, params={}):
raise NotSupported(self.id + ' fetchPosition() is not supported yet')
async def fetch_position_ws(self, symbol: str, params={}):
raise NotSupported(self.id + ' fetchPositionWs() is not supported yet')
async def watch_position(self, symbol: Str = None, params={}):
raise NotSupported(self.id + ' watchPosition() is not supported yet')
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchPositions() is not supported yet')
async def watch_position_for_symbols(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
return await self.watch_positions(symbols, since, limit, params)
async def fetch_positions_for_symbol(self, symbol: str, params={}):
"""
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
:param str symbol: unified market symbol
:param dict params: extra parameters specific to the endpoint
: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
"""
raise NotSupported(self.id + ' fetchPositionsForSymbol() is not supported yet')
async def fetch_positions_for_symbol_ws(self, symbol: str, params={}):
"""
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
:param str symbol: unified market symbol
:param dict params: extra parameters specific to the endpoint
: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
"""
raise NotSupported(self.id + ' fetchPositionsForSymbol() is not supported yet')
async def fetch_positions(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchPositions() is not supported yet')
async def fetch_positions_ws(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchPositions() is not supported yet')
async def fetch_positions_risk(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchPositionsRisk() is not supported yet')
async def fetch_bids_asks(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchBidsAsks() is not supported yet')
async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchBorrowInterest() is not supported yet')
async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchLedger() is not supported yet')
async def fetch_ledger_entry(self, id: str, code: Str = None, params={}):
raise NotSupported(self.id + ' fetchLedgerEntry() is not supported yet')
async def fetch_balance(self, params={}):
raise NotSupported(self.id + ' fetchBalance() is not supported yet')
async def fetch_balance_ws(self, params={}):
raise NotSupported(self.id + ' fetchBalanceWs() is not supported yet')
async def watch_balance(self, params={}):
raise NotSupported(self.id + ' watchBalance() is not supported yet')
async def fetch_partial_balance(self, part, params={}):
balance = await self.fetch_balance(params)
return balance[part]
async def fetch_free_balance(self, params={}):
return await self.fetch_partial_balance('free', params)
async def fetch_used_balance(self, params={}):
return await self.fetch_partial_balance('used', params)
async def fetch_total_balance(self, params={}):
return await self.fetch_partial_balance('total', params)
async def fetch_status(self, params={}):
raise NotSupported(self.id + ' fetchStatus() is not supported yet')
async def fetch_transaction_fee(self, code: str, params={}):
if not self.has['fetchTransactionFees']:
raise NotSupported(self.id + ' fetchTransactionFee() is not supported yet')
return await self.fetch_transaction_fees([code], params)
async def fetch_transaction_fees(self, codes: Strings = None, params={}):
raise NotSupported(self.id + ' fetchTransactionFees() is not supported yet')
async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
raise NotSupported(self.id + ' fetchDepositWithdrawFees() is not supported yet')
async def fetch_deposit_withdraw_fee(self, code: str, params={}):
if not self.has['fetchDepositWithdrawFees']:
raise NotSupported(self.id + ' fetchDepositWithdrawFee() is not supported yet')
fees = await self.fetch_deposit_withdraw_fees([code], params)
return self.safe_value(fees, code)
async def fetch_cross_borrow_rate(self, code: str, params={}):
await self.load_markets()
if not self.has['fetchBorrowRates']:
raise NotSupported(self.id + ' fetchCrossBorrowRate() is not supported yet')
borrowRates = await self.fetch_cross_borrow_rates(params)
rate = self.safe_value(borrowRates, code)
if rate is None:
raise ExchangeError(self.id + ' fetchCrossBorrowRate() could not find the borrow rate for currency code ' + code)
return rate
async def fetch_isolated_borrow_rate(self, symbol: str, params={}):
await self.load_markets()
if not self.has['fetchBorrowRates']:
raise NotSupported(self.id + ' fetchIsolatedBorrowRate() is not supported yet')
borrowRates = await self.fetch_isolated_borrow_rates(params)
rate = self.safe_dict(borrowRates, symbol)
if rate is None:
raise ExchangeError(self.id + ' fetchIsolatedBorrowRate() could not find the borrow rate for market symbol ' + symbol)
return rate
async def fetch_ticker(self, symbol: str, params={}):
if self.has['fetchTickers']:
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
tickers = await self.fetch_tickers([symbol], params)
ticker = self.safe_dict(tickers, symbol)
if ticker is None:
raise NullResponse(self.id + ' fetchTickers() could not find a ticker for ' + symbol)
else:
return ticker
else:
raise NotSupported(self.id + ' fetchTicker() is not supported yet')
async def fetch_mark_price(self, symbol: str, params={}):
if self.has['fetchMarkPrices']:
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
tickers = await self.fetch_mark_prices([symbol], params)
ticker = self.safe_dict(tickers, symbol)
if ticker is None:
raise NullResponse(self.id + ' fetchMarkPrices() could not find a ticker for ' + symbol)
else:
return ticker
else:
raise NotSupported(self.id + ' fetchMarkPrices() is not supported yet')
async def fetch_ticker_ws(self, symbol: str, params={}):
if self.has['fetchTickersWs']:
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
tickers = await self.fetch_tickers_ws([symbol], params)
ticker = self.safe_dict(tickers, symbol)
if ticker is None:
raise NullResponse(self.id + ' fetchTickerWs() could not find a ticker for ' + symbol)
else:
return ticker
else:
raise NotSupported(self.id + ' fetchTickerWs() is not supported yet')
async def watch_ticker(self, symbol: str, params={}):
raise NotSupported(self.id + ' watchTicker() is not supported yet')
async def fetch_tickers(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchTickers() is not supported yet')
async def fetch_mark_prices(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchMarkPrices() is not supported yet')
async def fetch_tickers_ws(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchTickers() is not supported yet')
async def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchOrderBooks() is not supported yet')
async def watch_bids_asks(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' watchBidsAsks() is not supported yet')
async def watch_tickers(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' watchTickers() is not supported yet')
async def un_watch_tickers(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' unWatchTickers() is not supported yet')
async def fetch_order(self, id: str, symbol: Str = None, params={}):
raise NotSupported(self.id + ' fetchOrder() is not supported yet')
async def fetch_order_with_client_order_id(self, clientOrderId: str, symbol: Str = None, params={}):
"""
create a market order by providing the symbol, side and cost
:param str clientOrderId: client order Id
:param str symbol: unified symbol of the market to create an order in
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
extendedParams = self.extend(params, {'clientOrderId': clientOrderId})
return await self.fetch_order('', symbol, extendedParams)
async def fetch_order_ws(self, id: str, symbol: Str = None, params={}):
raise NotSupported(self.id + ' fetchOrderWs() is not supported yet')
async def fetch_order_status(self, id: str, symbol: Str = None, params={}):
# TODO: TypeScript: change method signature by replacing
# Promise<string> with Promise<Order['status']>.
order = await self.fetch_order(id, symbol, params)
return order['status']
async def fetch_unified_order(self, order, params={}):
return await self.fetch_order(self.safe_string(order, 'id'), self.safe_string(order, 'symbol'), params)
async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
raise NotSupported(self.id + ' createOrder() is not supported yet')
async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}):
raise NotSupported(self.id + ' createConvertTrade() is not supported yet')
async def fetch_convert_trade(self, id: str, code: Str = None, params={}):
raise NotSupported(self.id + ' fetchConvertTrade() is not supported yet')
async def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchConvertTradeHistory() is not supported yet')
async def fetch_position_mode(self, symbol: Str = None, params={}):
raise NotSupported(self.id + ' fetchPositionMode() is not supported yet')
async def create_trailing_amount_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount: Num = None, trailingTriggerPrice: Num = None, params={}):
"""
create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency, or number of contracts
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
:param float trailingAmount: the quote amount to trail away from the current market price
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if trailingAmount is None:
raise ArgumentsRequired(self.id + ' createTrailingAmountOrder() requires a trailingAmount argument')
params['trailingAmount'] = trailingAmount
if trailingTriggerPrice is not None:
params['trailingTriggerPrice'] = trailingTriggerPrice
if self.has['createTrailingAmountOrder']:
return await self.create_order(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTrailingAmountOrder() is not supported yet')
async def create_trailing_amount_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingAmount: Num = None, trailingTriggerPrice: Num = None, params={}):
"""
create a trailing order by providing the symbol, type, side, amount, price and trailingAmount
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency, or number of contracts
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
:param float trailingAmount: the quote amount to trail away from the current market price
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if trailingAmount is None:
raise ArgumentsRequired(self.id + ' createTrailingAmountOrderWs() requires a trailingAmount argument')
params['trailingAmount'] = trailingAmount
if trailingTriggerPrice is not None:
params['trailingTriggerPrice'] = trailingTriggerPrice
if self.has['createTrailingAmountOrderWs']:
return await self.create_order_ws(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTrailingAmountOrderWs() is not supported yet')
async def create_trailing_percent_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent: Num = None, trailingTriggerPrice: Num = None, params={}):
"""
create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency, or number of contracts
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
:param float trailingPercent: the percent to trail away from the current market price
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if trailingPercent is None:
raise ArgumentsRequired(self.id + ' createTrailingPercentOrder() requires a trailingPercent argument')
params['trailingPercent'] = trailingPercent
if trailingTriggerPrice is not None:
params['trailingTriggerPrice'] = trailingTriggerPrice
if self.has['createTrailingPercentOrder']:
return await self.create_order(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTrailingPercentOrder() is not supported yet')
async def create_trailing_percent_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, trailingPercent: Num = None, trailingTriggerPrice: Num = None, params={}):
"""
create a trailing order by providing the symbol, type, side, amount, price and trailingPercent
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency, or number of contracts
:param float [price]: the price for the order to be filled at, in units of the quote currency, ignored in market orders
:param float trailingPercent: the percent to trail away from the current market price
:param float [trailingTriggerPrice]: the price to activate a trailing order, default uses the price argument
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if trailingPercent is None:
raise ArgumentsRequired(self.id + ' createTrailingPercentOrderWs() requires a trailingPercent argument')
params['trailingPercent'] = trailingPercent
if trailingTriggerPrice is not None:
params['trailingTriggerPrice'] = trailingTriggerPrice
if self.has['createTrailingPercentOrderWs']:
return await self.create_order_ws(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTrailingPercentOrderWs() is not supported yet')
async def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
"""
create a market order by providing the symbol, side and cost
:param str symbol: unified symbol of the market to create an order in
:param str side: 'buy' or 'sell'
:param float cost: how much you want to trade in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if self.has['createMarketOrderWithCost'] or (self.has['createMarketBuyOrderWithCost'] and self.has['createMarketSellOrderWithCost']):
return await self.create_order(symbol, 'market', side, cost, 1, params)
raise NotSupported(self.id + ' createMarketOrderWithCost() is not supported yet')
async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
"""
create a market buy order by providing the symbol and cost
:param str symbol: unified symbol of the market to create an order in
:param float cost: how much you want to trade in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if self.options['createMarketBuyOrderRequiresPrice'] or self.has['createMarketBuyOrderWithCost']:
return await self.create_order(symbol, 'market', 'buy', cost, 1, params)
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() is not supported yet')
async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
"""
create a market sell order by providing the symbol and cost
:param str symbol: unified symbol of the market to create an order in
:param float cost: how much you want to trade in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if self.options['createMarketSellOrderRequiresPrice'] or self.has['createMarketSellOrderWithCost']:
return await self.create_order(symbol, 'market', 'sell', cost, 1, params)
raise NotSupported(self.id + ' createMarketSellOrderWithCost() is not supported yet')
async def create_market_order_with_cost_ws(self, symbol: str, side: OrderSide, cost: float, params={}):
"""
create a market order by providing the symbol, side and cost
:param str symbol: unified symbol of the market to create an order in
:param str side: 'buy' or 'sell'
:param float cost: how much you want to trade in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if self.has['createMarketOrderWithCostWs'] or (self.has['createMarketBuyOrderWithCostWs'] and self.has['createMarketSellOrderWithCostWs']):
return await self.create_order_ws(symbol, 'market', side, cost, 1, params)
raise NotSupported(self.id + ' createMarketOrderWithCostWs() is not supported yet')
async def create_trigger_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
"""
create a trigger stop order(type 1)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float triggerPrice: the price to trigger the stop order, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if triggerPrice is None:
raise ArgumentsRequired(self.id + ' createTriggerOrder() requires a triggerPrice argument')
params['triggerPrice'] = triggerPrice
if self.has['createTriggerOrder']:
return await self.create_order(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTriggerOrder() is not supported yet')
async def create_trigger_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
"""
create a trigger stop order(type 1)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float triggerPrice: the price to trigger the stop order, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if triggerPrice is None:
raise ArgumentsRequired(self.id + ' createTriggerOrderWs() requires a triggerPrice argument')
params['triggerPrice'] = triggerPrice
if self.has['createTriggerOrderWs']:
return await self.create_order_ws(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTriggerOrderWs() is not supported yet')
async def create_stop_loss_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, stopLossPrice: Num = None, params={}):
"""
create a trigger stop loss order(type 2)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float stopLossPrice: the price to trigger the stop loss order, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if stopLossPrice is None:
raise ArgumentsRequired(self.id + ' createStopLossOrder() requires a stopLossPrice argument')
params['stopLossPrice'] = stopLossPrice
if self.has['createStopLossOrder']:
return await self.create_order(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createStopLossOrder() is not supported yet')
async def create_stop_loss_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, stopLossPrice: Num = None, params={}):
"""
create a trigger stop loss order(type 2)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float stopLossPrice: the price to trigger the stop loss order, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if stopLossPrice is None:
raise ArgumentsRequired(self.id + ' createStopLossOrderWs() requires a stopLossPrice argument')
params['stopLossPrice'] = stopLossPrice
if self.has['createStopLossOrderWs']:
return await self.create_order_ws(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createStopLossOrderWs() is not supported yet')
async def create_take_profit_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, takeProfitPrice: Num = None, params={}):
"""
create a trigger take profit order(type 2)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float takeProfitPrice: the price to trigger the take profit order, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if takeProfitPrice is None:
raise ArgumentsRequired(self.id + ' createTakeProfitOrder() requires a takeProfitPrice argument')
params['takeProfitPrice'] = takeProfitPrice
if self.has['createTakeProfitOrder']:
return await self.create_order(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTakeProfitOrder() is not supported yet')
async def create_take_profit_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, takeProfitPrice: Num = None, params={}):
"""
create a trigger take profit order(type 2)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float takeProfitPrice: the price to trigger the take profit order, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
if takeProfitPrice is None:
raise ArgumentsRequired(self.id + ' createTakeProfitOrderWs() requires a takeProfitPrice argument')
params['takeProfitPrice'] = takeProfitPrice
if self.has['createTakeProfitOrderWs']:
return await self.create_order_ws(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createTakeProfitOrderWs() is not supported yet')
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={}):
"""
create an order with a stop loss or take profit attached(type 3)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float [takeProfit]: the take profit price, in units of the quote currency
:param float [stopLoss]: the stop loss price, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:param str [params.takeProfitType]: *not available on all exchanges* 'limit' or 'market'
:param str [params.stopLossType]: *not available on all exchanges* 'limit' or 'market'
:param str [params.takeProfitPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
:param str [params.stopLossPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
:param float [params.takeProfitLimitPrice]: *not available on all exchanges* limit price for a limit take profit order
:param float [params.stopLossLimitPrice]: *not available on all exchanges* stop loss for a limit stop loss order
:param float [params.takeProfitAmount]: *not available on all exchanges* the amount for a take profit
:param float [params.stopLossAmount]: *not available on all exchanges* the amount for a stop loss
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
params = self.set_take_profit_and_stop_loss_params(symbol, type, side, amount, price, takeProfit, stopLoss, params)
if self.has['createOrderWithTakeProfitAndStopLoss']:
return await self.create_order(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createOrderWithTakeProfitAndStopLoss() is not supported yet')
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={}):
"""
create an order with a stop loss or take profit attached(type 3)
:param str symbol: unified symbol of the market to create an order in
:param str type: 'market' or 'limit'
:param str side: 'buy' or 'sell'
:param float amount: how much you want to trade in units of the base currency or the number of contracts
:param float [price]: the price to fulfill the order, in units of the quote currency, ignored in market orders
:param float [takeProfit]: the take profit price, in units of the quote currency
:param float [stopLoss]: the stop loss price, in units of the quote currency
:param dict [params]: extra parameters specific to the exchange API endpoint
:param str [params.takeProfitType]: *not available on all exchanges* 'limit' or 'market'
:param str [params.stopLossType]: *not available on all exchanges* 'limit' or 'market'
:param str [params.takeProfitPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
:param str [params.stopLossPriceType]: *not available on all exchanges* 'last', 'mark' or 'index'
:param float [params.takeProfitLimitPrice]: *not available on all exchanges* limit price for a limit take profit order
:param float [params.stopLossLimitPrice]: *not available on all exchanges* stop loss for a limit stop loss order
:param float [params.takeProfitAmount]: *not available on all exchanges* the amount for a take profit
:param float [params.stopLossAmount]: *not available on all exchanges* the amount for a stop loss
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
params = self.set_take_profit_and_stop_loss_params(symbol, type, side, amount, price, takeProfit, stopLoss, params)
if self.has['createOrderWithTakeProfitAndStopLossWs']:
return await self.create_order_ws(symbol, type, side, amount, price, params)
raise NotSupported(self.id + ' createOrderWithTakeProfitAndStopLossWs() is not supported yet')
async def create_orders(self, orders: List[OrderRequest], params={}):
raise NotSupported(self.id + ' createOrders() is not supported yet')
async def edit_orders(self, orders: List[OrderRequest], params={}):
raise NotSupported(self.id + ' editOrders() is not supported yet')
async def create_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
raise NotSupported(self.id + ' createOrderWs() is not supported yet')
async def cancel_order(self, id: str, symbol: Str = None, params={}):
raise NotSupported(self.id + ' cancelOrder() is not supported yet')
async def cancel_order_with_client_order_id(self, clientOrderId: str, symbol: Str = None, params={}):
"""
create a market order by providing the symbol, side and cost
:param str clientOrderId: client order Id
:param str symbol: unified symbol of the market to create an order in
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
extendedParams = self.extend(params, {'clientOrderId': clientOrderId})
return await self.cancel_order('', symbol, extendedParams)
async def cancel_order_ws(self, id: str, symbol: Str = None, params={}):
raise NotSupported(self.id + ' cancelOrderWs() is not supported yet')
async def cancel_orders(self, ids: List[str], symbol: Str = None, params={}):
raise NotSupported(self.id + ' cancelOrders() is not supported yet')
async def cancel_orders_with_client_order_ids(self, clientOrderIds: List[str], symbol: Str = None, params={}):
"""
create a market order by providing the symbol, side and cost
:param str[] clientOrderIds: client order Ids
:param str symbol: unified symbol of the market to create an order in
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
extendedParams = self.extend(params, {'clientOrderIds': clientOrderIds})
return await self.cancel_orders([], symbol, extendedParams)
async def cancel_orders_ws(self, ids: List[str], symbol: Str = None, params={}):
raise NotSupported(self.id + ' cancelOrdersWs() is not supported yet')
async def cancel_all_orders(self, symbol: Str = None, params={}):
raise NotSupported(self.id + ' cancelAllOrders() is not supported yet')
async def cancel_all_orders_after(self, timeout: Int, params={}):
raise NotSupported(self.id + ' cancelAllOrdersAfter() is not supported yet')
async def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
raise NotSupported(self.id + ' cancelOrdersForSymbols() is not supported yet')
async def cancel_all_orders_ws(self, symbol: Str = None, params={}):
raise NotSupported(self.id + ' cancelAllOrdersWs() is not supported yet')
async def cancel_unified_order(self, order: Order, params={}):
return self.cancel_order(self.safe_string(order, 'id'), self.safe_string(order, 'symbol'), params)
async def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
if self.has['fetchOpenOrders'] and self.has['fetchClosedOrders']:
raise NotSupported(self.id + ' fetchOrders() is not supported yet, consider using fetchOpenOrders() and fetchClosedOrders() instead')
raise NotSupported(self.id + ' fetchOrders() is not supported yet')
async def fetch_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchOrdersWs() is not supported yet')
async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchOrderTrades() is not supported yet')
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchOrders() is not supported yet')
async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
if self.has['fetchOrders']:
orders = await self.fetch_orders(symbol, since, limit, params)
return self.filter_by(orders, 'status', 'open')
raise NotSupported(self.id + ' fetchOpenOrders() is not supported yet')
async def fetch_open_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
if self.has['fetchOrdersWs']:
orders = await self.fetch_orders_ws(symbol, since, limit, params)
return self.filter_by(orders, 'status', 'open')
raise NotSupported(self.id + ' fetchOpenOrdersWs() is not supported yet')
async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
if self.has['fetchOrders']:
orders = await self.fetch_orders(symbol, since, limit, params)
return self.filter_by(orders, 'status', 'closed')
raise NotSupported(self.id + ' fetchClosedOrders() is not supported yet')
async def fetch_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchCanceledAndClosedOrders() is not supported yet')
async def fetch_closed_orders_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
if self.has['fetchOrdersWs']:
orders = await self.fetch_orders_ws(symbol, since, limit, params)
return self.filter_by(orders, 'status', 'closed')
raise NotSupported(self.id + ' fetchClosedOrdersWs() is not supported yet')
async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchMyTrades() is not supported yet')
async def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchMyLiquidations() is not supported yet')
async def fetch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchLiquidations() is not supported yet')
async def fetch_my_trades_ws(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchMyTradesWs() is not supported yet')
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' watchMyTrades() is not supported yet')
async def fetch_greeks(self, symbol: str, params={}):
raise NotSupported(self.id + ' fetchGreeks() is not supported yet')
async def fetch_all_greeks(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchAllGreeks() is not supported yet')
async def fetch_option_chain(self, code: str, params={}):
raise NotSupported(self.id + ' fetchOptionChain() is not supported yet')
async def fetch_option(self, symbol: str, params={}):
raise NotSupported(self.id + ' fetchOption() is not supported yet')
async def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}):
raise NotSupported(self.id + ' fetchConvertQuote() is not supported yet')
async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
"""
fetch history of deposits and withdrawals
:param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
:param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
:param int [limit]: max number of deposit/withdrawals to return, default is None
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
"""
raise NotSupported(self.id + ' fetchDepositsWithdrawals() is not supported yet')
async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchDeposits() is not supported yet')
async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchWithdrawals() is not supported yet')
async def fetch_deposits_ws(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchDepositsWs() is not supported yet')
async def fetch_withdrawals_ws(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchWithdrawalsWs() is not supported yet')
async def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchFundingRateHistory() is not supported yet')
async def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
raise NotSupported(self.id + ' fetchFundingHistory() is not supported yet')
async def close_position(self, symbol: str, side: OrderSide = None, params={}):
raise NotSupported(self.id + ' closePosition() is not supported yet')
async def close_all_positions(self, params={}):
raise NotSupported(self.id + ' closeAllPositions() is not supported yet')
async def fetch_l3_order_book(self, symbol: str, limit: Int = None, params={}):
raise BadRequest(self.id + ' fetchL3OrderBook() is not supported yet')
async def fetch_deposit_address(self, code: str, params={}):
if self.has['fetchDepositAddresses']:
depositAddresses = await self.fetch_deposit_addresses([code], params)
depositAddress = self.safe_value(depositAddresses, code)
if depositAddress is None:
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')
else:
return depositAddress
elif self.has['fetchDepositAddressesByNetwork']:
network = self.safe_string(params, 'network')
params = self.omit(params, 'network')
addressStructures = await self.fetch_deposit_addresses_by_network(code, params)
if network is not None:
return self.safe_dict(addressStructures, network)
else:
keys = list(addressStructures.keys())
key = self.safe_string(keys, 0)
return self.safe_dict(addressStructures, key)
else:
raise NotSupported(self.id + ' fetchDepositAddress() is not supported yet')
async def create_limit_order(self, symbol: str, side: OrderSide, amount: float, price: float, params={}):
return await self.create_order(symbol, 'limit', side, amount, price, params)
async def create_limit_order_ws(self, symbol: str, side: OrderSide, amount: float, price: float, params={}):
return await self.create_order_ws(symbol, 'limit', side, amount, price, params)
async def create_market_order(self, symbol: str, side: OrderSide, amount: float, price: Num = None, params={}):
return await self.create_order(symbol, 'market', side, amount, price, params)
async def create_market_order_ws(self, symbol: str, side: OrderSide, amount: float, price: Num = None, params={}):
return await self.create_order_ws(symbol, 'market', side, amount, price, params)
async def create_limit_buy_order(self, symbol: str, amount: float, price: float, params={}):
return await self.create_order(symbol, 'limit', 'buy', amount, price, params)
async def create_limit_buy_order_ws(self, symbol: str, amount: float, price: float, params={}):
return await self.create_order_ws(symbol, 'limit', 'buy', amount, price, params)
async def create_limit_sell_order(self, symbol: str, amount: float, price: float, params={}):
return await self.create_order(symbol, 'limit', 'sell', amount, price, params)
async def create_limit_sell_order_ws(self, symbol: str, amount: float, price: float, params={}):
return await self.create_order_ws(symbol, 'limit', 'sell', amount, price, params)
async def create_market_buy_order(self, symbol: str, amount: float, params={}):
return await self.create_order(symbol, 'market', 'buy', amount, None, params)
async def create_market_buy_order_ws(self, symbol: str, amount: float, params={}):
return await self.create_order_ws(symbol, 'market', 'buy', amount, None, params)
async def create_market_sell_order(self, symbol: str, amount: float, params={}):
return await self.create_order(symbol, 'market', 'sell', amount, None, params)
async def create_market_sell_order_ws(self, symbol: str, amount: float, params={}):
return await self.create_order_ws(symbol, 'market', 'sell', amount, None, params)
async def load_time_difference(self, params={}):
serverTime = await self.fetch_time(params)
after = self.milliseconds()
self.options['timeDifference'] = after - serverTime
return self.options['timeDifference']
async def fetch_market_leverage_tiers(self, symbol: str, params={}):
if self.has['fetchLeverageTiers']:
market = self.market(symbol)
if not market['contract']:
raise BadSymbol(self.id + ' fetchMarketLeverageTiers() supports contract markets only')
tiers = await self.fetch_leverage_tiers([symbol])
return self.safe_value(tiers, symbol)
else:
raise NotSupported(self.id + ' fetchMarketLeverageTiers() is not supported yet')
async def create_post_only_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
if not self.has['createPostOnlyOrder']:
raise NotSupported(self.id + ' createPostOnlyOrder() is not supported yet')
query = self.extend(params, {'postOnly': True})
return await self.create_order(symbol, type, side, amount, price, query)
async def create_post_only_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
if not self.has['createPostOnlyOrderWs']:
raise NotSupported(self.id + ' createPostOnlyOrderWs() is not supported yet')
query = self.extend(params, {'postOnly': True})
return await self.create_order_ws(symbol, type, side, amount, price, query)
async def create_reduce_only_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
if not self.has['createReduceOnlyOrder']:
raise NotSupported(self.id + ' createReduceOnlyOrder() is not supported yet')
query = self.extend(params, {'reduceOnly': True})
return await self.create_order(symbol, type, side, amount, price, query)
async def create_reduce_only_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
if not self.has['createReduceOnlyOrderWs']:
raise NotSupported(self.id + ' createReduceOnlyOrderWs() is not supported yet')
query = self.extend(params, {'reduceOnly': True})
return await self.create_order_ws(symbol, type, side, amount, price, query)
async def create_stop_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
if not self.has['createStopOrder']:
raise NotSupported(self.id + ' createStopOrder() is not supported yet')
if triggerPrice is None:
raise ArgumentsRequired(self.id + ' create_stop_order() requires a stopPrice argument')
query = self.extend(params, {'stopPrice': triggerPrice})
return await self.create_order(symbol, type, side, amount, price, query)
async def create_stop_order_ws(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, triggerPrice: Num = None, params={}):
if not self.has['createStopOrderWs']:
raise NotSupported(self.id + ' createStopOrderWs() is not supported yet')
if triggerPrice is None:
raise ArgumentsRequired(self.id + ' createStopOrderWs() requires a stopPrice argument')
query = self.extend(params, {'stopPrice': triggerPrice})
return await self.create_order_ws(symbol, type, side, amount, price, query)
async def create_stop_limit_order(self, symbol: str, side: OrderSide, amount: float, price: float, triggerPrice: float, params={}):
if not self.has['createStopLimitOrder']:
raise NotSupported(self.id + ' createStopLimitOrder() is not supported yet')
query = self.extend(params, {'stopPrice': triggerPrice})
return await self.create_order(symbol, 'limit', side, amount, price, query)
async def create_stop_limit_order_ws(self, symbol: str, side: OrderSide, amount: float, price: float, triggerPrice: float, params={}):
if not self.has['createStopLimitOrderWs']:
raise NotSupported(self.id + ' createStopLimitOrderWs() is not supported yet')
query = self.extend(params, {'stopPrice': triggerPrice})
return await self.create_order_ws(symbol, 'limit', side, amount, price, query)
async def create_stop_market_order(self, symbol: str, side: OrderSide, amount: float, triggerPrice: float, params={}):
if not self.has['createStopMarketOrder']:
raise NotSupported(self.id + ' createStopMarketOrder() is not supported yet')
query = self.extend(params, {'stopPrice': triggerPrice})
return await self.create_order(symbol, 'market', side, amount, None, query)
async def create_stop_market_order_ws(self, symbol: str, side: OrderSide, amount: float, triggerPrice: float, params={}):
if not self.has['createStopMarketOrderWs']:
raise NotSupported(self.id + ' createStopMarketOrderWs() is not supported yet')
query = self.extend(params, {'stopPrice': triggerPrice})
return await self.create_order_ws(symbol, 'market', side, amount, None, query)
async def fetch_last_prices(self, symbols: Strings = None, params={}):
raise NotSupported(self.id + ' fetchLastPrices() is not supported yet')
async def fetch_trading_fees(self, params={}):
raise NotSupported(self.id + ' fetchTradingFees() is not supported yet')
async def fetch_trading_fees_ws(self, params={}):
raise NotSupported(self.id + ' fetchTradingFeesWs() is not supported yet')
async def fetch_trading_fee(self, symbol: str, params={}):
if not self.has['fetchTradingFees']:
raise NotSupported(self.id + ' fetchTradingFee() is not supported yet')
fees = await self.fetch_trading_fees(params)
return self.safe_dict(fees, symbol)
async def fetch_convert_currencies(self, params={}):
raise NotSupported(self.id + ' fetchConvertCurrencies() is not supported yet')
async def fetch_funding_rate(self, symbol: str, params={}):
if self.has['fetchFundingRates']:
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
if not market['contract']:
raise BadSymbol(self.id + ' fetchFundingRate() supports contract markets only')
rates = await self.fetch_funding_rates([symbol], params)
rate = self.safe_value(rates, symbol)
if rate is None:
raise NullResponse(self.id + ' fetchFundingRate() returned no data for ' + symbol)
else:
return rate
else:
raise NotSupported(self.id + ' fetchFundingRate() is not supported yet')
async def fetch_funding_interval(self, symbol: str, params={}):
if self.has['fetchFundingIntervals']:
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
if not market['contract']:
raise BadSymbol(self.id + ' fetchFundingInterval() supports contract markets only')
rates = await self.fetch_funding_intervals([symbol], params)
rate = self.safe_value(rates, symbol)
if rate is None:
raise NullResponse(self.id + ' fetchFundingInterval() returned no data for ' + symbol)
else:
return rate
else:
raise NotSupported(self.id + ' fetchFundingInterval() is not supported yet')
async def fetch_mark_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
"""
fetches historical mark price candlestick data containing the open, high, low, and close price of a market
:param str symbol: unified symbol of the market to fetch OHLCV data for
:param str timeframe: the length of time each candle represents
:param int [since]: timestamp in ms of the earliest candle to fetch
:param int [limit]: the maximum amount of candles to fetch
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns float[][]: A list of candles ordered, open, high, low, close, None
"""
if self.has['fetchMarkOHLCV']:
request: dict = {
'price': 'mark',
}
return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
else:
raise NotSupported(self.id + ' fetchMarkOHLCV() is not supported yet')
async def fetch_index_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
"""
fetches historical index price candlestick data containing the open, high, low, and close price of a market
:param str symbol: unified symbol of the market to fetch OHLCV data for
:param str timeframe: the length of time each candle represents
:param int [since]: timestamp in ms of the earliest candle to fetch
:param int [limit]: the maximum amount of candles to fetch
:param dict [params]: extra parameters specific to the exchange API endpoint
@returns {} A list of candles ordered, open, high, low, close, None
"""
if self.has['fetchIndexOHLCV']:
request: dict = {
'price': 'index',
}
return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
else:
raise NotSupported(self.id + ' fetchIndexOHLCV() is not supported yet')
async def fetch_premium_index_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}):
"""
fetches historical premium index price candlestick data containing the open, high, low, and close price of a market
:param str symbol: unified symbol of the market to fetch OHLCV data for
:param str timeframe: the length of time each candle represents
:param int [since]: timestamp in ms of the earliest candle to fetch
:param int [limit]: the maximum amount of candles to fetch
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns float[][]: A list of candles ordered, open, high, low, close, None
"""
if self.has['fetchPremiumIndexOHLCV']:
request: dict = {
'price': 'premiumIndex',
}
return await self.fetch_ohlcv(symbol, timeframe, since, limit, self.extend(request, params))
else:
raise NotSupported(self.id + ' fetchPremiumIndexOHLCV() is not supported yet')
async def fetch_transactions(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
"""
@deprecated
*DEPRECATED* use fetchDepositsWithdrawals instead
:param str code: unified currency code for the currency of the deposit/withdrawals, default is None
:param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
:param int [limit]: max number of deposit/withdrawals to return, default is None
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
"""
if self.has['fetchDepositsWithdrawals']:
return await self.fetch_deposits_withdrawals(code, since, limit, params)
else:
raise NotSupported(self.id + ' fetchTransactions() is not supported yet')
async def fetch_paginated_call_dynamic(self, method: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}, maxEntriesPerRequest: Int = None, removeRepeated=True):
maxCalls = None
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
maxRetries = None
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
paginationDirection = None
paginationDirection, params = self.handle_option_and_params(params, method, 'paginationDirection', 'backward')
paginationTimestamp = None
removeRepeatedOption = removeRepeated
removeRepeatedOption, params = self.handle_option_and_params(params, method, 'removeRepeated', removeRepeated)
calls = 0
result = []
errors = 0
until = self.safe_integer_n(params, ['until', 'untill', 'till']) # do not omit it from params here
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
if (paginationDirection == 'forward'):
if since is None:
raise ArgumentsRequired(self.id + ' pagination requires a since argument when paginationDirection set to forward')
paginationTimestamp = since
while((calls < maxCalls)):
calls += 1
try:
if paginationDirection == 'backward':
# do it backwards, starting from the last
# UNTIL filtering is required in order to work
if paginationTimestamp is not None:
params['until'] = paginationTimestamp - 1
response = await getattr(self, method)(symbol, None, maxEntriesPerRequest, params)
responseLength = len(response)
if self.verbose:
backwardMessage = 'Dynamic pagination call ' + self.number_to_string(calls) + ' method ' + method + ' response length ' + self.number_to_string(responseLength)
if paginationTimestamp is not None:
backwardMessage += ' timestamp ' + self.number_to_string(paginationTimestamp)
self.log(backwardMessage)
if responseLength == 0:
break
errors = 0
result = self.array_concat(result, response)
firstElement = self.safe_value(response, 0)
paginationTimestamp = self.safe_integer_2(firstElement, 'timestamp', 0)
if (since is not None) and (paginationTimestamp <= since):
break
else:
# do it forwards, starting from the since
response = await getattr(self, method)(symbol, paginationTimestamp, maxEntriesPerRequest, params)
responseLength = len(response)
if self.verbose:
forwardMessage = 'Dynamic pagination call ' + self.number_to_string(calls) + ' method ' + method + ' response length ' + self.number_to_string(responseLength)
if paginationTimestamp is not None:
forwardMessage += ' timestamp ' + self.number_to_string(paginationTimestamp)
self.log(forwardMessage)
if responseLength == 0:
break
errors = 0
result = self.array_concat(result, response)
last = self.safe_value(response, responseLength - 1)
paginationTimestamp = self.safe_integer(last, 'timestamp') + 1
if (until is not None) and (paginationTimestamp >= until):
break
except Exception as e:
errors += 1
if errors > maxRetries:
raise e
uniqueResults = result
if removeRepeatedOption:
uniqueResults = self.remove_repeated_elements_from_array(result)
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
return self.filter_by_since_limit(uniqueResults, since, limit, key)
async def safe_deterministic_call(self, method: str, symbol: Str = None, since: Int = None, limit: Int = None, timeframe: Str = None, params={}):
maxRetries = None
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
errors = 0
while(errors <= maxRetries):
try:
if timeframe and method != 'fetchFundingRateHistory':
return await getattr(self, method)(symbol, timeframe, since, limit, params)
else:
return await getattr(self, method)(symbol, since, limit, params)
except Exception as e:
if isinstance(e, RateLimitExceeded):
raise e # if we are rate limited, we should not retry and fail fast
errors += 1
if errors > maxRetries:
raise e
return []
async def fetch_paginated_call_deterministic(self, method: str, symbol: Str = None, since: Int = None, limit: Int = None, timeframe: Str = None, params={}, maxEntriesPerRequest=None):
maxCalls = None
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
current = self.milliseconds()
tasks = []
time = self.parse_timeframe(timeframe) * 1000
step = time * maxEntriesPerRequest
currentSince = current - (maxCalls * step) - 1
if since is not None:
currentSince = max(currentSince, since)
else:
currentSince = max(currentSince, 1241440531000) # avoid timestamps older than 2009
until = self.safe_integer_2(params, 'until', 'till') # do not omit it here
if until is not None:
requiredCalls = int(math.ceil((until - since)) / step)
if requiredCalls > maxCalls:
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))
for i in range(0, maxCalls):
if (until is not None) and (currentSince >= until):
break
if currentSince >= current:
break
tasks.append(self.safe_deterministic_call(method, symbol, currentSince, maxEntriesPerRequest, timeframe, params))
currentSince = self.sum(currentSince, step) - 1
results = await asyncio.gather(*tasks)
result = []
for i in range(0, len(results)):
result = self.array_concat(result, results[i])
uniqueResults = self.remove_repeated_elements_from_array(result)
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
return self.filter_by_since_limit(uniqueResults, since, limit, key)
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):
maxCalls = None
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
maxRetries = None
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
cursorValue = None
i = 0
errors = 0
result = []
timeframe = self.safe_string(params, 'timeframe')
params = self.omit(params, 'timeframe') # reading the timeframe from the method arguments to avoid changing the signature
while(i < maxCalls):
try:
if cursorValue is not None:
if cursorIncrement is not None:
cursorValue = self.parse_to_int(cursorValue) + cursorIncrement
params[cursorSent] = cursorValue
response = None
if method == 'fetchAccounts':
response = await getattr(self, method)(params)
elif method == 'getLeverageTiersPaginated' or method == 'fetchPositions':
response = await getattr(self, method)(symbol, params)
elif method == 'fetchOpenInterestHistory':
response = await getattr(self, method)(symbol, timeframe, since, maxEntriesPerRequest, params)
else:
response = await getattr(self, method)(symbol, since, maxEntriesPerRequest, params)
errors = 0
responseLength = len(response)
if self.verbose:
cursorString = '' if (cursorValue is None) else cursorValue
iteration = (i + 1)
cursorMessage = 'Cursor pagination call ' + str(iteration) + ' method ' + method + ' response length ' + str(responseLength) + ' cursor ' + cursorString
self.log(cursorMessage)
if responseLength == 0:
break
result = self.array_concat(result, response)
last = self.safe_dict(response, responseLength - 1)
# cursorValue = self.safe_value(last['info'], cursorReceived)
cursorValue = None # search for the cursor
for j in range(0, responseLength):
index = responseLength - j - 1
entry = self.safe_dict(response, index)
info = self.safe_dict(entry, 'info')
cursor = self.safe_value(info, cursorReceived)
if cursor is not None:
cursorValue = cursor
break
if cursorValue is None:
break
lastTimestamp = self.safe_integer(last, 'timestamp')
if lastTimestamp is not None and lastTimestamp < since:
break
except Exception as e:
errors += 1
if errors > maxRetries:
raise e
i += 1
sorted = self.sort_cursor_paginated_result(result)
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
return self.filter_by_since_limit(sorted, since, limit, key)
async def fetch_paginated_call_incremental(self, method: str, symbol: Str = None, since=None, limit=None, params={}, pageKey=None, maxEntriesPerRequest=None):
maxCalls = None
maxCalls, params = self.handle_option_and_params(params, method, 'paginationCalls', 10)
maxRetries = None
maxRetries, params = self.handle_option_and_params(params, method, 'maxRetries', 3)
maxEntriesPerRequest, params = self.handle_max_entries_per_request_and_params(method, maxEntriesPerRequest, params)
i = 0
errors = 0
result = []
while(i < maxCalls):
try:
params[pageKey] = i + 1
response = await getattr(self, method)(symbol, since, maxEntriesPerRequest, params)
errors = 0
responseLength = len(response)
if self.verbose:
iteration = (i + str(1))
incrementalMessage = 'Incremental pagination call ' + iteration + ' method ' + method + ' response length ' + str(responseLength)
self.log(incrementalMessage)
if responseLength == 0:
break
result = self.array_concat(result, response)
except Exception as e:
errors += 1
if errors > maxRetries:
raise e
i += 1
sorted = self.sort_cursor_paginated_result(result)
key = 0 if (method == 'fetchOHLCV') else 'timestamp'
return self.filter_by_since_limit(sorted, since, limit, key)
async def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}):
"""
fetches the history of margin added or reduced from contract isolated positions
:param str [symbol]: unified market symbol
:param int [since]: timestamp in ms of the position
:param int [limit]: the maximum amount of candles to fetch, default=1000
:param dict params: extra parameters specific to the exchange api endpoint
:returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
"""
if self.has['fetchPositionsHistory']:
positions = await self.fetch_positions_history([symbol], since, limit, params)
return positions
else:
raise NotSupported(self.id + ' fetchPositionHistory() is not supported yet')
async def fetch_positions_history(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}):
"""
fetches the history of margin added or reduced from contract isolated positions
:param str [symbol]: unified market symbol
:param int [since]: timestamp in ms of the position
:param int [limit]: the maximum amount of candles to fetch, default=1000
:param dict params: extra parameters specific to the exchange api endpoint
:returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
"""
raise NotSupported(self.id + ' fetchPositionsHistory() is not supported yet')
async def fetch_transfer(self, id: str, code: Str = None, params={}):
"""
fetches a transfer
:param str id: transfer id
:param [str] code: unified currency code
:param dict params: extra parameters specific to the exchange api endpoint
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
"""
raise NotSupported(self.id + ' fetchTransfer() is not supported yet')
async def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
"""
fetches a transfer
:param str id: transfer id
:param int [since]: timestamp in ms of the earliest transfer to fetch
:param int [limit]: the maximum amount of transfers to fetch
:param dict params: extra parameters specific to the exchange api endpoint
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
"""
raise NotSupported(self.id + ' fetchTransfers() is not supported yet')
async def un_watch_ohlcv(self, symbol: str, timeframe: str = '1m', params={}):
"""
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
:param str symbol: unified symbol of the market to fetch OHLCV data for
:param str timeframe: the length of time each candle represents
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns int[][]: A list of candles ordered, open, high, low, close, volume
"""
raise NotSupported(self.id + ' unWatchOHLCV() is not supported yet')
async def watch_mark_price(self, symbol: str, params={}):
"""
watches a mark price for a specific market
:param str symbol: unified symbol of the market to fetch the ticker for
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
"""
raise NotSupported(self.id + ' watchMarkPrice() is not supported yet')
async def watch_mark_prices(self, symbols: Strings = None, params={}):
"""
watches the mark price for all markets
:param str[] symbols: unified symbol of the market to fetch the ticker for
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
"""
raise NotSupported(self.id + ' watchMarkPrices() is not supported yet')
async def withdraw_ws(self, code: str, amount: float, address: str, tag: Str = None, params={}):
"""
make a withdrawal
:param str code: unified currency code
:param float amount: the amount to withdraw
:param str address: the address to withdraw to
:param str tag:
:param dict [params]: extra parameters specific to the bitvavo api endpoint
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
"""
raise NotSupported(self.id + ' withdrawWs() is not supported yet')
async def un_watch_my_trades(self, symbol: Str = None, params={}):
"""
unWatches information on multiple trades made by the user
:param str symbol: unified market symbol of the market orders were made in
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
"""
raise NotSupported(self.id + ' unWatchMyTrades() is not supported yet')
async def create_orders_ws(self, orders: List[OrderRequest], params={}):
"""
create a list of trade orders
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
"""
raise NotSupported(self.id + ' createOrdersWs() is not supported yet')
async def fetch_orders_by_status_ws(self, status: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
"""
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
:param str symbol: unified symbol of the market to fetch the order book for
:param int [limit]: the maximum amount of order book entries to return
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
"""
raise NotSupported(self.id + ' fetchOrdersByStatusWs() is not supported yet')
async def un_watch_bids_asks(self, symbols: Strings = None, params={}):
"""
unWatches best bid & ask for symbols
:param str[] symbols: unified symbol of the market to fetch the ticker for
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
"""
raise NotSupported(self.id + ' unWatchBidsAsks() is not supported yet')