async def show_balances(self): total_col_name = f'Total ({RateOracle.global_token_symbol})' self._notify("Updating balances, please wait...") network_timeout = float(global_config_map["other_commands_timeout"].value) try: all_ex_bals = await asyncio.wait_for( UserBalances.instance().all_balances_all_exchanges(), network_timeout ) except asyncio.TimeoutError: self._notify("\nA network error prevented the balances to update. See logs for more details.") raise all_ex_avai_bals = UserBalances.instance().all_avai_balances_all_exchanges() all_ex_limits: Optional[Dict[str, Dict[str, str]]] = global_config_map["balance_asset_limit"].value if all_ex_limits is None: all_ex_limits = {} exchanges_total = 0 for exchange, bals in all_ex_bals.items(): self._notify(f"\n{exchange}:") df, allocated_total = await self.exchange_balances_extra_df(bals, all_ex_avai_bals.get(exchange, {})) if df.empty: self._notify("You have no balance on this exchange.") else: lines = [" " + line for line in df.to_string(index=False).split("\n")] self._notify("\n".join(lines)) self._notify(f"\n Total: {RateOracle.global_token_symbol} {PerformanceMetrics.smart_round(df[total_col_name].sum())} " f"Allocated: {allocated_total / df[total_col_name].sum():.2%}") exchanges_total += df[total_col_name].sum() self._notify(f"\n\nExchanges Total: {RateOracle.global_token_symbol} {exchanges_total:.0f} ") celo_address = global_config_map["celo_address"].value if celo_address is not None: try: if not CeloCLI.unlocked: await self.validate_n_connect_celo() df = await self.celo_balances_df() lines = [" " + line for line in df.to_string(index=False).split("\n")] self._notify("\ncelo:") self._notify("\n".join(lines)) except Exception as e: self._notify(f"\ncelo CLI Error: {str(e)}") eth_address = global_config_map["ethereum_wallet"].value if eth_address is not None: eth_df = await self.ethereum_balances_df() lines = [" " + line for line in eth_df.to_string(index=False).split("\n")] self._notify("\nethereum:") self._notify("\n".join(lines)) # XDAI balances xdai_df = await self.xdai_balances_df() lines = [" " + line for line in xdai_df.to_string(index=False).split("\n")] self._notify("\nxdai:") self._notify("\n".join(lines))
async def get_current_balances( self, # type: HummingbotApplication market: str): if market in self.markets and self.markets[market].ready: return self.markets[market].get_all_balances() elif "Paper" in market: paper_balances = global_config_map[ "paper_trade_account_balance"].value if paper_balances is None: return {} return { token: Decimal(str(bal)) for token, bal in paper_balances.items() } elif "perpetual_finance" == market: return await UserBalances.xdai_balances() else: gateway_eth_connectors = [ cs.name for cs in CONNECTOR_SETTINGS.values() if cs.use_ethereum_wallet and cs.type == ConnectorType.Connector ] if market in gateway_eth_connectors: return await UserBalances.instance().eth_n_erc20_balances() else: await UserBalances.instance().update_exchange_balance(market) return UserBalances.instance().all_balances(market)
async def connection_df(self # type: HummingbotApplication ): columns = [ "Exchange", " Keys Added", " Keys Confirmed", " Connector Status" ] data = [] failed_msgs = {} network_timeout = float( global_config_map["other_commands_timeout"].value) try: err_msgs = await asyncio.wait_for( UserBalances.instance().update_exchanges(reconnect=True), network_timeout) except asyncio.TimeoutError: self._notify( "\nA network error prevented the connection table to populate. See logs for more details." ) raise for option in sorted(OPTIONS): keys_added = "No" keys_confirmed = 'No' status = get_connector_status(option) if option == "ethereum": eth_address = global_config_map["ethereum_wallet"].value if eth_address is not None and eth_address in Security.private_keys( ): keys_added = "Yes" err_msg = UserBalances.validate_ethereum_wallet() if err_msg is not None: failed_msgs[option] = err_msg else: keys_confirmed = 'Yes' elif option == "celo": celo_address = global_config_map["celo_address"].value if celo_address is not None and Security.encrypted_file_exists( "celo_password"): keys_added = "Yes" err_msg = await self.validate_n_connect_celo(True) if err_msg is not None: failed_msgs[option] = err_msg else: keys_confirmed = 'Yes' else: api_keys = (await Security.api_keys(option)).values() if len(api_keys) > 0: keys_added = "Yes" err_msg = err_msgs.get(option) if err_msg is not None: failed_msgs[option] = err_msg else: keys_confirmed = 'Yes' data.append([option, keys_added, keys_confirmed, status]) return pd.DataFrame(data=data, columns=columns), failed_msgs
async def show_balances(self): self._notify("Updating balances, please wait...") all_ex_bals = await UserBalances.instance().all_balances_all_exchanges( ) all_ex_avai_bals = UserBalances.instance( ).all_avai_balances_all_exchanges() all_ex_limits: Optional[Dict[str, Dict[ str, str]]] = global_config_map["balance_asset_limit"].value if all_ex_limits is None: all_ex_limits = {} for exchange, bals in all_ex_bals.items(): self._notify(f"\n{exchange}:") # df = await self.exchange_balances_df(bals, all_ex_limits.get(exchange, {})) df, allocated_total = await self.exchange_balances_usd_df( bals, all_ex_avai_bals.get(exchange, {})) if df.empty: self._notify("You have no balance on this exchange.") else: lines = [ " " + line for line in df.to_string(index=False).split("\n") ] self._notify("\n".join(lines)) self._notify( f"\n Total: $ {df['Total ($)'].sum():.0f} " f"Allocated: {allocated_total / df['Total ($)'].sum():.2%}" ) celo_address = global_config_map["celo_address"].value if celo_address is not None: try: if not CeloCLI.unlocked: await self.validate_n_connect_celo() df = await self.celo_balances_df() lines = [ " " + line for line in df.to_string(index=False).split("\n") ] self._notify("\ncelo:") self._notify("\n".join(lines)) except Exception as e: self._notify(f"\ncelo CLI Error: {str(e)}") eth_address = global_config_map["ethereum_wallet"].value if eth_address is not None: df = await self.ethereum_balances_df() lines = [ " " + line for line in df.to_string(index=False).split("\n") ] self._notify("\nethereum:") self._notify("\n".join(lines))
async def get_current_balances(self, # type: HummingbotApplication market: str): if market in self.markets and self.markets[market].ready: return self.markets[market].get_all_balances() elif "Paper" in market: paper_balances = self.client_config_map.paper_trade.paper_trade_account_balance if paper_balances is None: return {} return {token: Decimal(str(bal)) for token, bal in paper_balances.items()} else: await UserBalances.instance().update_exchange_balance(market, self.client_config_map) return UserBalances.instance().all_balances(market)
async def connect_exchange(self, # type: HummingbotApplication exchange): self.app.clear_input() self.placeholder_mode = True self.app.hide_input = True if exchange == "kraken": self._notify("Reminder: Please ensure your Kraken API Key Nonce Window is at least 10.") exchange_configs = [c for c in global_config_map.values() if c.key in settings.CONNECTOR_SETTINGS[exchange].config_keys and c.is_connect_key] to_connect = True if Security.encrypted_file_exists(exchange_configs[0].key): await Security.wait_til_decryption_done() api_key_config = [c for c in exchange_configs if "api_key" in c.key] if api_key_config: api_key_config = api_key_config[0] api_key = Security.decrypted_value(api_key_config.key) prompt = f"Would you like to replace your existing {exchange} API key {api_key} (Yes/No)? >>> " else: prompt = f"Would you like to replace your existing {exchange_configs[0].key} (Yes/No)? >>> " answer = await self.app.prompt(prompt=prompt) if self.app.to_stop_config: self.app.to_stop_config = False return if answer.lower() not in ("yes", "y"): to_connect = False if to_connect: for config in exchange_configs: await self.prompt_a_config(config) if self.app.to_stop_config: self.app.to_stop_config = False return Security.update_secure_config(config.key, config.value) api_keys = await Security.api_keys(exchange) network_timeout = float(global_config_map["other_commands_timeout"].value) try: err_msg = await asyncio.wait_for( UserBalances.instance().add_exchange(exchange, **api_keys), network_timeout ) except asyncio.TimeoutError: self._notify("\nA network error prevented the connection to complete. See logs for more details.") self.placeholder_mode = False self.app.hide_input = False self.app.change_prompt(prompt=">>> ") raise if err_msg is None: self._notify(f"\nYou are now connected to {exchange}.") else: self._notify(f"\nError: {err_msg}") self.placeholder_mode = False self.app.hide_input = False self.app.change_prompt(prompt=">>> ")
async def get_current_balances(self, # type: HummingbotApplication market: str): paper_trade_suffix = '_PaperTrade' if market in self.markets and self.markets[market].ready: return self.markets[market].get_all_balances() elif paper_trade_suffix in market: return self.markets[market[:-len(paper_trade_suffix)]].get_all_balances() elif "perpetual_finance" == market: return await UserBalances.xdai_balances() else: gateway_eth_connectors = [cs.name for cs in CONNECTOR_SETTINGS.values() if cs.use_ethereum_wallet and cs.type == ConnectorType.Connector] if market in gateway_eth_connectors: return await UserBalances.instance().eth_n_erc20_balances() else: await UserBalances.instance().update_exchange_balance(market) return UserBalances.instance().all_balances(market)
async def start_check(self, # type: HummingbotApplication log_level: Optional[str] = None, restore: Optional[bool] = False, strategy_file_name: Optional[str] = None): if self.strategy_task is not None and not self.strategy_task.done(): self.notify('The bot is already running - please run "stop" first') return if settings.required_rate_oracle: # If the strategy to run requires using the rate oracle to find FX rates, validate there is a rate for # each configured token pair if not (await self.confirm_oracle_conversion_rate()): self.notify("The strategy failed to start.") return if strategy_file_name: file_name = strategy_file_name.split(".")[0] self.strategy_file_name = file_name self.strategy_name = file_name elif not await self.status_check_all(notify_success=False): self.notify("Status checks failed. Start aborted.") return if self._last_started_strategy_file != self.strategy_file_name: init_logging("hummingbot_logs.yml", override_log_level=log_level.upper() if log_level else None, strategy_file_path=self.strategy_file_name) self._last_started_strategy_file = self.strategy_file_name # If macOS, disable App Nap. if platform.system() == "Darwin": import appnope appnope.nope() self._initialize_notifiers() try: self._initialize_strategy(self.strategy_name) except NotImplementedError: self.strategy_name = None self.strategy_file_name = None self.notify("Invalid strategy. Start aborted.") raise if any([str(exchange).endswith("paper_trade") for exchange in settings.required_exchanges]): self.notify("\nPaper Trading Active: All orders are simulated and no real orders are placed.") for exchange in settings.required_exchanges: connector: str = str(exchange) status: str = get_connector_status(connector) warning_msg: Optional[str] = warning_messages.get(connector, None) # confirm gateway connection conn_setting: settings.ConnectorSetting = settings.AllConnectorSettings.get_connector_settings()[connector] if conn_setting.uses_gateway_generic_connector(): connector_details: Dict[str, Any] = conn_setting.conn_init_parameters() if connector_details: data: List[List[str]] = [ ["chain", connector_details['chain']], ["network", connector_details['network']], ["wallet_address", connector_details['wallet_address']] ] await UserBalances.instance().update_exchange_balance(connector) balances: List[str] = [ f"{str(PerformanceMetrics.smart_round(v, 8))} {k}" for k, v in UserBalances.instance().all_balances(connector).items() ] data.append(["balances", ""]) for bal in balances: data.append(["", bal]) wallet_df: pd.DataFrame = pd.DataFrame(data=data, columns=["", f"{connector} configuration"]) self.notify(wallet_df.to_string(index=False)) self.app.clear_input() self.placeholder_mode = True use_configuration = await self.app.prompt(prompt="Do you want to continue? (Yes/No) >>> ") self.placeholder_mode = False self.app.change_prompt(prompt=">>> ") if use_configuration in ["N", "n", "No", "no"]: return if use_configuration not in ["Y", "y", "Yes", "yes"]: self.notify("Invalid input. Please execute the `start` command again.") return # Display custom warning message for specific connectors elif warning_msg is not None: self.notify(f"\nConnector status: {status}\n" f"{warning_msg}") # Display warning message if the exchange connector has outstanding issues or not working elif not status.endswith("GREEN"): self.notify(f"\nConnector status: {status}. This connector has one or more issues.\n" "Refer to our Github page for more info: https://github.com/coinalpha/hummingbot") self.notify(f"\nStatus check complete. Starting '{self.strategy_name}' strategy...") await self.start_market_making(restore) # We always start the RateOracle. It is required for PNL calculation. RateOracle.get_instance().start()
async def show_balances(self # type: HummingbotApplication ): total_col_name = f'Total ({RateOracle.global_token_symbol})' sum_not_for_show_name = "sum_not_for_show" self.notify("Updating balances, please wait...") network_timeout = float( self.client_config_map.commands_timeout.other_commands_timeout) try: all_ex_bals = await asyncio.wait_for( UserBalances.instance().all_balances_all_exchanges( self.client_config_map), network_timeout) except asyncio.TimeoutError: self.notify( "\nA network error prevented the balances to update. See logs for more details." ) raise all_ex_avai_bals = UserBalances.instance( ).all_available_balances_all_exchanges() exchanges_total = 0 for exchange, bals in all_ex_bals.items(): self.notify(f"\n{exchange}:") df, allocated_total = await self.exchange_balances_extra_df( exchange, bals, all_ex_avai_bals.get(exchange, {})) if df.empty: self.notify("You have no balance on this exchange.") else: lines = [ " " + line for line in df.drop(sum_not_for_show_name, axis=1). to_string(index=False).split("\n") ] self.notify("\n".join(lines)) self.notify( f"\n Total: {RateOracle.global_token_symbol} " f"{PerformanceMetrics.smart_round(df[total_col_name].sum())}" ) allocated_percentage = 0 if df[sum_not_for_show_name].sum() != Decimal("0"): allocated_percentage = allocated_total / df[ sum_not_for_show_name].sum() self.notify(f"Allocated: {allocated_percentage:.2%}") exchanges_total += df[total_col_name].sum() self.notify( f"\n\nExchanges Total: {RateOracle.global_token_symbol} {exchanges_total:.0f} " ) celo_address = CELO_KEYS.celo_address if hasattr( CELO_KEYS, "celo_address") else None if celo_address is not None: try: if not CeloCLI.unlocked: await self.validate_n_connect_celo() df = await self.celo_balances_df() lines = [ " " + line for line in df.to_string(index=False).split("\n") ] self.notify("\ncelo:") self.notify("\n".join(lines)) except Exception as e: self.notify(f"\ncelo CLI Error: {str(e)}")