diff --git a/example/restful/getaccount.py b/example/restful/getaccount.py index 5c21b22..8297c43 100644 --- a/example/restful/getaccount.py +++ b/example/restful/getaccount.py @@ -2,21 +2,14 @@ from huobi.constant.test import * from huobi.base.printobject import * from huobi.model import Account - request_client = RequestClient(api_key=g_api_key, secret_key=g_secret_key) -account_balance_list = request_client.get_account_balance() +account_balance_list = request_client.get_accounts() if account_balance_list and len(account_balance_list): for account in account_balance_list: print("======= ID", account.id, "=======") print("Account Status", account.account_state) print("Account Type", account.account_type) print("Subtype", account.subtype) - if account.balances and len(account.balances): - for balance in account.balances: - print("\tBalance Currency", balance.currency) - print("\tBalance Type", balance.balance_type) - print("\tBalance", balance.balance) - print() print() diff --git a/example/restful/getaccountbalance.py b/example/restful/getaccountbalance.py new file mode 100644 index 0000000..4d91b45 --- /dev/null +++ b/example/restful/getaccountbalance.py @@ -0,0 +1,20 @@ +from huobi import RequestClient +from huobi.constant.test import * +from huobi.base.printobject import * +from huobi.model import Account +request_client = RequestClient(api_key=g_api_key, secret_key=g_secret_key) +account_balance_list = request_client.get_account_balance() +if account_balance_list and len(account_balance_list): + for account in account_balance_list: + print("======= ID", account.id, "=======") + print("Account Status", account.account_state) + print("Account Type", account.account_type) + print("Subtype", account.subtype) + if account.balances and len(account.balances): + for balance in account.balances: + print("\tBalance Currency", balance.currency) + print("\tBalance Type", balance.balance_type) + print("\tBalance", balance.balance) + print() + print() + diff --git a/example/restful/getsubuserdepositaddress.py b/example/restful/getsubuserdepositaddress.py new file mode 100644 index 0000000..760314b --- /dev/null +++ b/example/restful/getsubuserdepositaddress.py @@ -0,0 +1,13 @@ +from huobi import RequestClient +from huobi.constant.test import * + + +def print_obj_list(list_obj): + if list_obj and len(list_obj): + for obj in list_obj: + obj.print_object() + print() + +client = RequestClient(api_key=g_api_key, secret_key=g_secret_key) +list_obj = client.get_sub_user_deposit_address(sub_uid=g_sub_uid, currency="btc") +print_obj_list(list_obj) \ No newline at end of file diff --git a/example/restful/getsubuserdeposithistory.py b/example/restful/getsubuserdeposithistory.py new file mode 100644 index 0000000..158f2eb --- /dev/null +++ b/example/restful/getsubuserdeposithistory.py @@ -0,0 +1,14 @@ +from huobi import RequestClient +from huobi.constant.test import * + + +def print(deposit_history): + if deposit_history.data and len(deposit_history.data): + print(deposit_history.nextId) + for obj in deposit_history.data: + obj.print_object() + print() + +client = RequestClient(api_key=g_api_key, secret_key=g_secret_key) +deposit_history = client.get_sub_user_deposit_history(sub_uid=g_sub_uid) +print(deposit_history) \ No newline at end of file diff --git a/huobi/impl/accountinfomap.py b/huobi/impl/accountinfomap.py index 333acb6..f713eea 100644 --- a/huobi/impl/accountinfomap.py +++ b/huobi/impl/accountinfomap.py @@ -6,12 +6,20 @@ class AccountInfoMap: user_map = dict() + account_id_type_map = dict() + account_type_id_map = dict() def update_user_info(self, api_key, request_impl): accounts = call_sync(request_impl.get_accounts()) user = User() user.accounts = accounts self.user_map[api_key] = user + if accounts and len(accounts): + self.account_id_type_map[api_key] = {} + self.account_type_id_map[api_key] = {} + for account_item in accounts: + self.account_id_type_map[api_key][account_item.id] = account_item.account_type + self.account_type_id_map[api_key][account_item.account_type] = account_item.id def get_user(self, api_key): if api_key is None or api_key == "": @@ -29,5 +37,29 @@ def get_account_by_id(self, api_key, account_id): api_key + ", account id: " + str(account_id)) return account + def get_all_accounts(self, api_key): + user = self.get_user(api_key) + return user.accounts + + def get_account_type_by_id(self, api_key, account_id): + if api_key is None or api_key == "": + raise HuobiApiException(HuobiApiException.KEY_MISSING, "[User] Key is empty or null") + if api_key not in self.account_id_type_map: + raise HuobiApiException(HuobiApiException.RUNTIME_ERROR, "[User] Cannot found account_id by key: " + api_key) + return self.account_id_type_map.get(api_key, {}).get(account_id, None) + + def get_account_id_by_type(self, api_key, account_type): + if api_key is None or api_key == "": + raise HuobiApiException(HuobiApiException.KEY_MISSING, "[User] Key is empty or null") + if api_key not in self.account_type_id_map: + raise HuobiApiException(HuobiApiException.RUNTIME_ERROR, "[User] Cannot found account_type by key: " + api_key) + return self.account_type_id_map.get(api_key, {}).get(account_type, None) + + def get_all_accounts_without_check(self, api_key): + if api_key is None or api_key == "": + raise HuobiApiException(HuobiApiException.KEY_MISSING, "[User] Key is empty or null") + + user = self.user_map.get(api_key, None) + return None if (user is None) else user.accounts account_info_map = AccountInfoMap() diff --git a/huobi/impl/restapiinvoker.py b/huobi/impl/restapiinvoker.py index 444e207..9188f2d 100644 --- a/huobi/impl/restapiinvoker.py +++ b/huobi/impl/restapiinvoker.py @@ -4,6 +4,7 @@ from huobi.impl.utils.etfresult import etf_result_check from huobi.impl.utils import * +session = requests.Session() def check_response(json_wrapper): if json_wrapper.contain_key("status"): @@ -27,7 +28,8 @@ def check_response(json_wrapper): elif json_wrapper.contain_key("code"): code = json_wrapper.get_int("code") if code != 200: - raise HuobiApiException(HuobiApiException.EXEC_ERROR, "[Executing] " + str(code)) + err_msg = json_wrapper.get_string_or_default("message", "") + raise HuobiApiException(HuobiApiException.EXEC_ERROR, "[Executing] " + str(code) + ": " + err_msg) else: raise HuobiApiException(HuobiApiException.RUNTIME_ERROR, "[Invoking] Status cannot be found in response.") @@ -35,7 +37,7 @@ def check_response(json_wrapper): def call_sync(request, is_checked=False): if request.method == "GET": # print("call_sync url : " , request.host + request.url) - response = requests.get(request.host + request.url, headers=request.header) + response = session.get(request.host + request.url, headers=request.header) # print("receive data : " + response.text) if is_checked is True: return response.text @@ -43,7 +45,7 @@ def call_sync(request, is_checked=False): check_response(json_wrapper) return request.json_parser(json_wrapper) elif request.method == "POST": - response = requests.post(request.host + request.url, data=json.dumps(request.post_body), headers=request.header) + response = session.post(request.host + request.url, data=json.dumps(request.post_body), headers=request.header) # print("receive data : " + response.text) json_wrapper = parse_json_from_string(response.text) check_response(json_wrapper) @@ -52,7 +54,8 @@ def call_sync(request, is_checked=False): def call_sync_perforence_test(request, is_checked=False): if request.method == "GET": inner_start_time = time.time() - response = requests.get(request.host + request.url, headers=request.header) + # print("call_sync_perforence_test url : ", request.host + request.url) + response = session.get(request.host + request.url, headers=request.header) #print("call_sync_perforence_test data :", response.text) inner_end_time = time.time() cost_manual = round(inner_end_time - inner_start_time, 6) @@ -64,7 +67,7 @@ def call_sync_perforence_test(request, is_checked=False): return request.json_parser(json_wrapper), req_cost, cost_manual elif request.method == "POST": inner_start_time = time.time() - response = requests.post(request.host + request.url, data=json.dumps(request.post_body), headers=request.header) + response = session.post(request.host + request.url, data=json.dumps(request.post_body), headers=request.header) inner_end_time = time.time() cost_manual = round(inner_end_time - inner_start_time, 6) req_cost = response.elapsed.total_seconds() diff --git a/huobi/impl/restapirequestimpl.py b/huobi/impl/restapirequestimpl.py index 0285fe1..ee3df50 100644 --- a/huobi/impl/restapirequestimpl.py +++ b/huobi/impl/restapirequestimpl.py @@ -7,6 +7,7 @@ from huobi.impl.utils.timeservice import * from huobi.model import * from huobi.model.accountledger import AccountLedger +from huobi.model.deposithistory import DepositHistory, History from huobi.model.feerate import FeeRate from huobi.model.marketticker import MarketTicker @@ -329,6 +330,41 @@ def parse(json_wrapper): request.json_parser = parse return request + def get_sub_user_deposit_history(self, sub_uid, currency=None, start_time=None, end_time=None, sort=None, limit=None, from_id=None): + check_should_not_none(sub_uid, "sub_uid") + + builder = UrlParamsBuilder() + builder.put_url("subUid", sub_uid) + builder.put_url("currency", currency) + builder.put_url("startTime", start_time) + builder.put_url("endTime", end_time) + builder.put_url("sort", sort) + builder.put_url("limit", limit) + builder.put_url("fromId", from_id) + request = self.__create_request_by_get_with_signature("/v2/sub-user/query-deposit", builder) + + def parse(json_wrapper): + deposit_history = DepositHistory() + deposit_history.nextId = json_wrapper.get_int_or_default("nextId", 0) + deposit_history.data = list() + list_array = json_wrapper.get_array("data") + for item in list_array.get_items(): + history = History() + history.id = item.get_int("id") + history.currency = item.get_string("currency") + history.txHash = item.get_string("txHash") + history.amount = item.get_float("amount") + history.address = item.get_string("address") + history.addressTag = item.get_string("addressTag") + history.deposit_state = item.get_string("state") + history.created_timestamp = item.get_int("createTime") + history.updated_timestamp = item.get_int("updateTime") + deposit_history.data.append(history) + return deposit_history + + request.json_parser = parse + return request + def get_balance(self, account): path = "/v1/account/accounts/{}/balance" path = path.format(account.id) @@ -1322,6 +1358,26 @@ def parse(json_wrapper): request.json_parser = parse return request + def get_sub_user_deposit_address(self, sub_uid, currency): + builder = UrlParamsBuilder() + builder.put_url("subUid", sub_uid) + builder.put_url("currency", currency) + request = self.__create_request_by_get_with_signature("/v2/sub-user/deposit-address", builder) + + def parse(json_wrapper): + ret_list = [] + data_array = json_wrapper.get_array("data") + for address_data in data_array.get_items(): + obj = ChainDepositAddress() + obj.currency = address_data.get_string("currency") + obj.address = address_data.get_string("address") + obj.addressTag = address_data.get_string("addressTag") + obj.chain = address_data.get_string("chain") + ret_list.append(obj) + return ret_list + + request.json_parser = parse + return request def get_account_withdraw_quota(self, currency): check_should_not_none(currency, "currency") diff --git a/huobi/model/balance.py b/huobi/model/balance.py index bbb44ce..52a7a72 100644 --- a/huobi/model/balance.py +++ b/huobi/model/balance.py @@ -1,3 +1,5 @@ +import json + from huobi.model.constant import * @@ -29,4 +31,18 @@ def print_object(self, format_data=""): from huobi.base.printobject import PrintBasic PrintBasic.print_basic(self.currency, format_data + "Currency") PrintBasic.print_basic(self.balance_type, format_data + "Balance Type") - PrintBasic.print_basic(self.balance, format_data + "Balance") \ No newline at end of file + PrintBasic.print_basic(self.balance, format_data + "Balance") + + @staticmethod + def parse_from_api_response(dict_data): + response_status = dict_data.get("status", None) + balance_data_list = dict_data.get("data", {}).get("list", {}) + balance_list = [] + if ((response_status == "ok") and (balance_data_list is not None) and len(balance_data_list)): + for item in balance_data_list: + balance = Balance() + balance.balance = item.get("balance") + balance.currency = item.get("currency") + balance.balance_type = item.get("type") + balance_list.append(balance) + return balance_list \ No newline at end of file diff --git a/huobi/model/deposithistory.py b/huobi/model/deposithistory.py new file mode 100644 index 0000000..7a05db2 --- /dev/null +++ b/huobi/model/deposithistory.py @@ -0,0 +1,50 @@ +from huobi.model.constant import * + + +class DepositHistory: + """ + The deposit history + + :member + id: The transfer id. + currency: The crypto currency to deposit. + txHash: The on-chain transaction hash. + amount: The number of crypto asset transferred in its minimum unit. + address: The deposit source address. + addressTag: The user defined address tag. + deposit_state: The deposit state of this transfer. + created_timestamp: The UNIX formatted timestamp in UTC for the transfer creation. + updated_timestamp: The UNIX formatted timestamp in UTC for the transfer's latest update. + """ + + def __init__(self): + self.data = list() + self.nextId = 0 + + +class History: + + def __init__(self): + self.id = 0 + self.currency = "" + self.txHash = "" + self.chain = "" + self.amount = 0.0 + self.address = "" + self.addressTag = "" + self.deposit_state = WithdrawState.INVALID + self.created_timestamp = 0 + self.updated_timestamp = 0 + + def print_object(self, format_data=""): + from huobi.base.printobject import PrintBasic + PrintBasic.print_basic(self.id, format_data + "ID") + PrintBasic.print_basic(self.currency, format_data + "Currency") + PrintBasic.print_basic(self.chain, format_data + "Chain") + PrintBasic.print_basic(self.txHash, format_data + "Trade Hash") + PrintBasic.print_basic(self.amount, format_data + "Amount") + PrintBasic.print_basic(self.address, format_data + "Address") + PrintBasic.print_basic(self.addressTag, format_data + "Address Tag") + PrintBasic.print_basic(self.deposit_state, format_data + "Deposit State") + PrintBasic.print_basic(self.created_timestamp, format_data + "Create Time") + PrintBasic.print_basic(self.updated_timestamp, format_data + "Update Time") diff --git a/huobi/requstclient.py b/huobi/requstclient.py index d9fd9e6..c384de5 100644 --- a/huobi/requstclient.py +++ b/huobi/requstclient.py @@ -1,13 +1,19 @@ +import aiohttp +import asyncio + from huobi.constant.system import RestApiDefine from huobi.impl.restapirequestimpl import RestApiRequestImpl from huobi.impl.restapiinvoker import call_sync -from huobi.impl.accountinfomap import account_info_map from huobi.impl.utils.inputchecker import * from huobi.model import * +from huobi.impl.accountinfomap import account_info_map +from huobi.model.balance import Balance +from huobi.model.deposithistory import DepositHistory class RequestClient(object): - + api_key = None + server_url = None def __init__(self, **kwargs): """ Create the request client instance. @@ -16,18 +22,17 @@ def __init__(self, **kwargs): secret_key: The private key applied from Huobi. server_url: The URL name like "https://api.huobi.pro". """ - api_key = None secret_key = None - url = RestApiDefine.Url + self.server_url = RestApiDefine.Url if "api_key" in kwargs: - api_key = kwargs["api_key"] + self.api_key = kwargs["api_key"] if "secret_key" in kwargs: secret_key = kwargs["secret_key"] if "url" in kwargs: - url = kwargs["url"] + self.server_url = kwargs["url"] try: - self.request_impl = RestApiRequestImpl(api_key, secret_key, url) - account_info_map.update_user_info(api_key, self.request_impl) + self.request_impl = RestApiRequestImpl(self.api_key, secret_key, self.server_url) + account_info_map.update_user_info(self.api_key, self.request_impl) except Exception: pass @@ -182,6 +187,23 @@ def get_deposit_history(self, currency: 'str', from_id: 'int', size: 'int', dire """ return call_sync(self.request_impl.get_deposit_history(currency, from_id, size, direct)) + def get_sub_user_deposit_history(self, sub_uid: 'int', currency: 'str' = None, + start_time: 'int' = None, end_time: 'int' = None, + sort: 'str' = None, limit: 'int' = None, from_id: 'int' = None) -> DepositHistory: + """ + Parent get sub user depoist history. + + :param sub_uid: Sub user id. (mandatory) + :param currency: Cryptocurrency. + :param start_time: Farthest time + :param end_time: Nearest time + :param sort: Sorting order + :param limit: Maximum number of items in one page + :param from_id: First record Id in this query + """ + return call_sync(self.request_impl.get_sub_user_deposit_history(sub_uid, currency, start_time, end_time, + sort, limit, from_id)) + def transfer(self, symbol: 'str', from_account: 'AccountType', to_account: 'AccountType', currency: 'str', amount: 'float') -> int: """ @@ -252,16 +274,55 @@ def get_last_trade_and_best_quote(self, symbol: 'str') -> LastTradeAndBestQuote: last_trade_and_best_quote.last_trade_amount = last_trade.amount return last_trade_and_best_quote + def get_accounts(self) -> list: + """ + Get all accounts. + + :return: The information of all account balance. + """ + global account_info_map + accounts = account_info_map.get_all_accounts_without_check(self.api_key) + if accounts and len(accounts): + return accounts + + return call_sync(self.request_impl.get_accounts()) + + async def async_get_account_balance(self, balance_full_url, account_id, ret_map): + async with aiohttp.ClientSession() as session: + async with session.get(balance_full_url) as resp: + json = await resp.json() + ret_map[account_id] = json + return json + + def get_account_balance(self) -> list: """ Get the balance of a all accounts. :return: The information of all account balance. """ - accounts = call_sync(self.request_impl.get_accounts()) + tasks = [] + accounts = self.get_accounts() + account_balance_map = {} + for item in accounts: + balance_requset = self.request_impl.get_balance(item) + balance_url = self.server_url + balance_requset.url + tasks.append(asyncio.ensure_future(self.async_get_account_balance(balance_url, item.id, account_balance_map))) + + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(asyncio.wait(tasks)) + except Exception as ee: + print(ee) + finally: + # loop.close() #for thread safe, the event loop can't be closed + pass + for item in accounts: - balances = call_sync(self.request_impl.get_balance(item)) - item.balances = balances + item.balances = Balance.parse_from_api_response(account_balance_map[ item.id]) + + del account_balance_map + del tasks return accounts def get_account_balance_by_account_type(self, account_type: "AccountType") -> Account: @@ -272,7 +333,7 @@ def get_account_balance_by_account_type(self, account_type: "AccountType") -> Ac :return: The information of the account that is specified type. """ check_should_not_none(account_type, "account_type") - accounts = call_sync(self.request_impl.get_accounts()) + accounts = self.get_accounts() for item in accounts: if account_type == item.account_type: balances = call_sync(self.request_impl.get_balance(item)) @@ -636,6 +697,16 @@ def get_account_withdraw_quota(self, currency: 'str')->list: """ return call_sync(self.request_impl.get_account_withdraw_quota(currency)) + def get_sub_user_deposit_address(self, sub_uid: 'int', currency: 'str') -> list: + """ + Parent get sub user deposit address + + :param sub_uid: Sub user id + :param currency: Cryptocurrency, like "btc". (mandatory) + :return: + """ + return call_sync(self.request_impl.get_sub_user_deposit_address(sub_uid, currency)) + def get_deposit_withdraw(self, op_type:'str', currency: 'str'=None, from_id: 'int'=None, size: 'int'=None, direct:'str'=None) -> list: """ Get the withdraw records of an account. diff --git a/performance/requsttest.py b/performance/requsttest.py index df2b279..c5af553 100644 --- a/performance/requsttest.py +++ b/performance/requsttest.py @@ -1,13 +1,18 @@ +import aiohttp +import asyncio + from huobi.constant.system import RestApiDefine from huobi.impl.restapirequestimpl import RestApiRequestImpl from huobi.impl.restapiinvoker import call_sync_perforence_test from huobi.impl.accountinfomap import account_info_map from huobi.impl.utils.inputchecker import * from huobi.model import * - +from huobi.model.balance import Balance +import time class RequestTest(object): - + api_key = None + server_url = None def __init__(self, **kwargs): """ Create the request client instance. @@ -16,18 +21,17 @@ def __init__(self, **kwargs): secret_key: The private key applied from Huobi. server_url: The URL name like "https://api.huobi.pro". """ - api_key = None secret_key = None - url = RestApiDefine.Url + self.server_url = RestApiDefine.Url if "api_key" in kwargs: - api_key = kwargs["api_key"] + self.api_key = kwargs["api_key"] if "secret_key" in kwargs: secret_key = kwargs["secret_key"] if "url" in kwargs: - url = kwargs["url"] + self.server_url = kwargs["url"] try: - self.request_impl = RestApiRequestImpl(api_key, secret_key, url) - account_info_map.update_user_info(api_key, self.request_impl) + self.request_impl = RestApiRequestImpl(self.api_key, secret_key, self.server_url) + account_info_map.update_user_info(self.api_key, self.request_impl) except Exception: pass @@ -241,7 +245,7 @@ def get_last_trade_and_best_quote(self, symbol: 'str') -> LastTradeAndBestQuote: :param symbol: The symbol, like "btcusdt". (mandatory) :return: The data includes last trade, best bid and best ask. """ - best_quote = call_sync_perforence_test(self.request_impl.get_best_quote(symbol)) + best_quote, req_cost, cost_manual = call_sync_perforence_test(self.request_impl.get_best_quote(symbol)) last_trade = self.get_last_trade(symbol) last_trade_and_best_quote = LastTradeAndBestQuote() last_trade_and_best_quote.bid_amount = best_quote.bid_amount @@ -250,7 +254,27 @@ def get_last_trade_and_best_quote(self, symbol: 'str') -> LastTradeAndBestQuote: last_trade_and_best_quote.ask_price = best_quote.ask_price last_trade_and_best_quote.last_trade_price = last_trade.price last_trade_and_best_quote.last_trade_amount = last_trade.amount - return last_trade_and_best_quote + return last_trade_and_best_quote, req_cost, cost_manual + + def get_accounts(self) -> list: + """ + Get all accounts. + + :return: The information of all account balance. + """ + global account_info_map + accounts = account_info_map.get_all_accounts_without_check(self.api_key) + if accounts and len(accounts): + return accounts, 0.0, 0.0 + + return call_sync_perforence_test(self.request_impl.get_accounts()) + + async def async_get_account_balance(self, balance_full_url, account_id, ret_map): + async with aiohttp.ClientSession() as session: + async with session.get(balance_full_url) as resp: + json = await resp.json() + ret_map[account_id] = json + def get_account_balance(self) -> list: """ @@ -258,13 +282,40 @@ def get_account_balance(self) -> list: :return: The information of all account balance. """ - accounts, req_cost, cost_manual = call_sync_perforence_test(self.request_impl.get_accounts()) + start_time = time.time() + + tasks = [] + accounts,req_cost, cost_manual = self.get_accounts() + + if (accounts is not None and len(accounts)): + for account_item in accounts: + print ("account id in : ", account_item.id) + + account_balance_map = {} for item in accounts: - balances, req_cost_tmp, cost_manual_tmp = call_sync_perforence_test(self.request_impl.get_balance(item)) - item.balances = balances - req_cost = req_cost + req_cost_tmp - cost_manual = cost_manual + cost_manual_tmp - return accounts, req_cost, cost_manual + balance_requset = self.request_impl.get_balance(item) + balance_url = self.server_url + balance_requset.url + tasks.append(asyncio.ensure_future(self.async_get_account_balance(balance_url, item.id, account_balance_map))) + + loop = asyncio.get_event_loop() + + try: + loop.run_until_complete(asyncio.wait(tasks)) + except Exception as ee: + print(ee) + finally: + # loop.close() for thread safe, the event loop can't be closed + pass + + for item in accounts: + item.balances = Balance.parse_from_api_response(account_balance_map[item.id]) + end_time = time.time() + + cost_time = end_time - start_time + del account_balance_map + del tasks + + return accounts, cost_time, cost_time def get_account_balance_by_account_type(self, account_type: "AccountType") -> Account: """ @@ -274,12 +325,12 @@ def get_account_balance_by_account_type(self, account_type: "AccountType") -> Ac :return: The information of the account that is specified type. """ check_should_not_none(account_type, "account_type") - accounts = call_sync_perforence_test(self.request_impl.get_accounts()) + accounts = self.get_accounts() for item in accounts: if account_type == item.account_type: - balances = call_sync_perforence_test(self.request_impl.get_balance(item)) + balances, req_cost, cost_manual = call_sync_perforence_test(self.request_impl.get_balance(item)) item.balances = balances - return item + return item, req_cost, cost_manual def create_order(self, symbol: 'str', account_type: 'AccountType', order_type: 'OrderType', amount: 'float', price: 'float', client_order_id=None, stop_price=None, operator=None) -> int: @@ -321,7 +372,7 @@ def get_open_orders(self, symbol: 'str', account_type: 'AccountType', side: 'Ord The request of get open orders. :param symbol: The symbol, like "btcusdt". (mandatory) - :param account_type: The order side, buy or sell. If no side defined, will return all open orders of the account. (mandatory) + :param account_type: account type, all defination to see AccountType in SDK. (mandatory) :param side: The order side, buy or sell. If no side defined, will return all open orders of the account. (optional) :param size: The number of orders to return. Range is [1, 500]. Default is 100. (optional) :param direct: 1:prev order by ID asc from from_id, 2:next order by ID desc from from_id @@ -443,7 +494,7 @@ def cancel_withdraw(self, currency: 'str', withdraw_id: 'int') -> None: def get_historical_orders(self, symbol: 'str', order_state: 'OrderState', order_type: 'OrderType' = None, start_date: 'str' = None, end_date: 'str' = None, start_id: 'int' = None, - size: 'int' = None) -> list: + size: 'int' = None, start_time:'int'=None, end_time:'int'=None) -> list: """ Get historical orders. @@ -454,11 +505,13 @@ def get_historical_orders(self, symbol: 'str', order_state: 'OrderState', order_ :param end_date: End date in format yyyy-mm-dd. (optional) :param start_id: Start id. (optional) :param size: The size of orders. (optional) + :param start_time: millseconds time. (optional) + :param end_time: millseconds time and (end_time - start_time) must less than 48 hours. (optional) :return: """ return call_sync_perforence_test( self.request_impl.get_historical_orders(symbol, order_state, order_type, start_date, end_date, start_id, - size)) + size, start_time, end_time)) def transfer_between_parent_and_sub(self, sub_uid: 'int', currency: 'str', amount: 'float', transfer_type: 'TransferMasterType'): @@ -553,6 +606,32 @@ def get_fee_rate(self, symbols: 'str') -> list: """ return call_sync_perforence_test(self.request_impl.get_fee_rate(symbols)) + def get_margin_loan_info(self, symbols: 'str'=None) -> list: + """ + The request of get margin loan info, can return currency loan info list. + + :param symbols: The symbol, like "btcusdt,htusdt". (optional) + :return: The cross margin loan info. + """ + return call_sync_perforence_test(self.request_impl.get_margin_loan_info(symbols)) + + def get_cross_margin_loan_info(self) -> list: + """ + The request of currency loan info list. + + :return: The cross margin loan info list. + """ + return call_sync_perforence_test(self.request_impl.get_cross_margin_loan_info()) + + def get_reference_transact_fee_rate(self, symbols: 'str') -> list: + """ + The request of get transact fee rate list. + + :param symbols: The symbol, like "btcusdt,htusdt". (mandatory) + :return: The transact fee rate list. + """ + return call_sync_perforence_test(self.request_impl.get_reference_transact_fee_rate(symbols)) + def transfer_between_futures_and_pro(self, currency: 'str', amount: 'float', transfer_type: 'TransferFuturesPro')-> int: """ diff --git a/performance/testcase.py b/performance/testcase.py index f3338d4..6b108e3 100644 --- a/performance/testcase.py +++ b/performance/testcase.py @@ -566,12 +566,22 @@ def test_match_result(self): tc.add_record() def test_account(self): + spot_account_id = 0 + + # case get_account_balance + tc = TimeCost(function_name="(" + self.test_client.get_accounts.__name__ + " GET request call once)") + result, tc.server_req_cost, tc.server_api_cost = self.test_client.get_accounts() + tc.run_status = RunStatus.SUCCESS if result and len(result) else RunStatus.FAILED + tc.add_record() + for row in result: + if row.account_type == AccountType.SPOT: + spot_account_id = row.id + break + print("test_account spot account id : ", spot_account_id) # case get_account_balance tc = TimeCost(function_name="(" + self.test_client.get_account_balance.__name__ + " GET request call once)") result, tc.server_req_cost, tc.server_api_cost = self.test_client.get_account_balance() - global count_offset - count_offset = count_offset + len(result) # call get balance in loop tc.run_status = RunStatus.SUCCESS if result and len(result) else RunStatus.FAILED tc.add_record() spot_account_id = 0 @@ -616,7 +626,7 @@ def test_account(self): # case get_account_ledger tc = TimeCost(function_name=self.test_client.get_account_ledger.__name__) - result, tc.server_req_cost, tc.server_api_cost = self.test_client.get_account_ledger(account_id=g_account_id) + result, tc.server_req_cost, tc.server_api_cost = self.test_client.get_account_ledger(account_id=spot_account_id) tc.run_status = RunStatus.SUCCESS if result else RunStatus.FAILED tc.add_record() @@ -668,6 +678,19 @@ def test_get_system_status(self): tc.run_status = RunStatus.SUCCESS if result else RunStatus.FAILED tc.add_record() + def test_account_balance_performance(self): + + # case get_account_balance + tc = TimeCost(function_name="(" + self.test_client.get_account_balance.__name__ + " GET request call once)") + result, tc.server_req_cost, tc.server_api_cost = self.test_client.get_account_balance() + tc.run_status = RunStatus.SUCCESS if result and len(result) else RunStatus.FAILED + tc.add_record() + spot_account_id = 0 + for row in result: + if row.account_type == AccountType.SPOT: + spot_account_id = row.id + break + print("test_account spot account id : ", spot_account_id) if __name__ == "__main__": test_case = RestfulTestCaseSeq() @@ -680,6 +703,7 @@ def test_get_system_status(self): test_case.test_batch_cancel_get_orders() test_case.test_match_result() test_case.test_account() + test_case.test_account_balance_performance() test_case.test_etf() test_case.test_trade() test_case.test_cross_margin() diff --git a/setup.py b/setup.py index 46d0a50..42d2250 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="huobi-client", - version="1.0.13", + version="1.0.14", packages=['huobi', 'huobi.impl', 'huobi.impl.utils', 'huobi.exception', 'huobi.model', 'huobi.base', 'huobi.constant', "performance", "tests", "huobi.demo_service", "huobi.demo_service.mbp"], install_requires=['requests', 'apscheduler', 'websocket-client', 'urllib3']